Skip to content

Commit 8909e23

Browse files
committed
Introduce AnonymousToken
1 parent 794f889 commit 8909e23

4 files changed

Lines changed: 66 additions & 35 deletions

File tree

gcl_iam/drivers.py

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,6 @@ def get_algorithm(
142142

143143

144144
class AnonDriver(AbstractAuthDriver):
145-
def __init__(self):
146-
self.algorithm_keys: tp.Dict[str, AlgorithmKeys] = {}
147-
148145
def get_introspection_info(self, token_info, otp_code=None):
149146
return {
150147
"user_info": {
@@ -164,28 +161,7 @@ def get_algorithm(
164161
self,
165162
token_info: tokens.UnverifiedToken,
166163
) -> tp.Optional[algorithms.AbstractAlgorithm]:
167-
# For anonymous users, we don't need algorithm validation
168-
if token_info is None:
169-
return None
170-
171-
audience = token_info.audience_name
172-
if audience not in self.algorithm_keys:
173-
raise KeyError(f"Unknown audience: {audience}")
174-
keys = self.algorithm_keys[audience]
175-
176-
if isinstance(keys, HS256AlgorithmKeys):
177-
return algorithms.HS256(
178-
key=keys.key,
179-
previous_key=keys.previous_key,
180-
)
181-
182-
if isinstance(keys, RS256AlgorithmKeys):
183-
return algorithms.RS256VerifyOnly(
184-
public_key=keys.public_key,
185-
previous_public_key=keys.previous_public_key,
186-
)
187-
188-
raise TypeError(f"Unexpected algorithm keys type: {type(keys)!r}")
164+
raise NotImplementedError("AnonDriver does not support token validation.")
189165

190166

191167
class HttpDriver(AbstractAuthDriver):

gcl_iam/engines.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ def last_name(self):
4545
def email(self):
4646
return self._info["email"]
4747

48+
@property
49+
def type(self):
50+
return self._info["type"]
51+
4852

4953
class IntrospectionInfo:
5054
def __init__(self, info):
@@ -75,9 +79,9 @@ def __init__(self, auth_token, algorithm, driver, enforcer=None, otp_code=None):
7579

7680
# Handle anonymous users (no auth token)
7781
if auth_token == "" and algorithm is None:
78-
self._token_info = None
82+
self._token_info = tokens.AnonymousToken()
7983
self._introspection_info = self._driver.get_introspection_info(
80-
token_info=None,
84+
token_info=self._token_info,
8185
otp_code=otp_code,
8286
)
8387
else:
@@ -101,10 +105,7 @@ def __init__(self, auth_token, algorithm, driver, enforcer=None, otp_code=None):
101105
self._introspection_info["permissions"]
102106
)
103107

104-
if self._token_info:
105-
self._introspection_info["otp_enabled"] = self._token_info.otp_enabled
106-
else:
107-
self._introspection_info["otp_enabled"] = False
108+
self._introspection_info["otp_enabled"] = self._token_info.otp_enabled
108109

109110
@property
110111
def token_info(self):

gcl_iam/middlewares.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ def __init__(
6868
)
6969
self._iam_engine_driver = iam_engine_driver
7070
self._skip_auth_endpoints = skip_auth_endpoints or []
71+
self._anon_driver = drivers.AnonDriver()
7172

7273
def _construct_context(self, req):
7374
return self._context_class(req=req, **self._context_kwargs)
@@ -81,7 +82,7 @@ def _should_skip_auth(self, req):
8182
def _get_auth_token(self, req):
8283
header_value = req.headers.get("Authorization", "")
8384
if header_value.lower().startswith("bearer "):
84-
return header_value.split(" ")[1]
85+
return header_value.split(" ", 1)[1]
8586
return None
8687

8788
def _get_otp_code(self, req):
@@ -101,12 +102,10 @@ def _get_response(self, ctx, req):
101102
auth_token = self._get_auth_token(req)
102103
if auth_token is None:
103104
# Create IamEngine with anonymous user data using AnonDriver
104-
105-
anon_driver = drivers.AnonDriver()
106105
iam_context = engines.IamEngine(
107106
auth_token="",
108107
algorithm=None,
109-
driver=anon_driver,
108+
driver=self._anon_driver,
110109
otp_code=None,
111110
)
112111
else:

gcl_iam/tokens.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
# under the License.
1616

1717
import datetime
18+
import time
1819
import typing as tp
1920
import uuid
2021

@@ -174,3 +175,57 @@ def __init__(
174175
ignore_expiration=ignore_expiration,
175176
verify=verify,
176177
)
178+
179+
180+
class AnonymousToken(BaseToken):
181+
"""Token for anonymous users with mock JWT data"""
182+
183+
def __init__(self):
184+
# Mock JWT token info for anonymous user
185+
token_info = {
186+
"exp": int(time.time()) + 360000, # Far future expiration
187+
"iat": int(time.time()),
188+
"auth_time": int(time.time()),
189+
"jti": "11111111-1111-1111-1111-111111111111", # Fixed UUID for anon
190+
"iss": "genesis-core-iam",
191+
"aud": "anon",
192+
"sub": "11111111-1111-1111-1111-111111111111",
193+
"typ": "anon",
194+
}
195+
196+
super().__init__(
197+
token="", # No actual token for anonymous users
198+
token_info=token_info,
199+
audience="anon",
200+
)
201+
202+
@property
203+
def expiration_datetime(self):
204+
exp = self._token_info["exp"]
205+
return datetime.datetime.fromtimestamp(exp, tz=datetime.timezone.utc)
206+
207+
@property
208+
def created_at(self):
209+
iat = self._token_info["iat"]
210+
return datetime.datetime.fromtimestamp(iat, tz=datetime.timezone.utc)
211+
212+
@property
213+
def issuer_url(self):
214+
return self._token_info["iss"]
215+
216+
@property
217+
def user_uuid(self):
218+
return uuid.UUID(self._token_info["sub"])
219+
220+
@property
221+
def autenticated_at(self):
222+
auth_time = self._token_info["auth_time"]
223+
return datetime.datetime.fromtimestamp(auth_time, tz=datetime.timezone.utc)
224+
225+
@property
226+
def token_type(self):
227+
return self._token_info["typ"]
228+
229+
@property
230+
def otp_enabled(self):
231+
return False

0 commit comments

Comments
 (0)