Skip to content
This repository was archived by the owner on Jun 23, 2023. It is now read-only.

Commit bfdb7d7

Browse files
committed
Merge branch 'develop' of https://github.com/IdentityPython/oidc-op into develop
2 parents f6056af + 2f87d37 commit bfdb7d7

File tree

4 files changed

+166
-11
lines changed

4 files changed

+166
-11
lines changed

src/oidcop/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import secrets
22

3-
__version__ = "2.3.4"
3+
__version__ = "2.3.5"
44

55
DEF_SIGN_ALG = {
66
"id_token": "RS256",

src/oidcop/endpoint_context.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,13 @@ class EndpointContext(OidcContext):
119119
}
120120

121121
def __init__(
122-
self,
123-
conf: Union[dict, OPConfiguration],
124-
server_get: Callable,
125-
keyjar: Optional[KeyJar] = None,
126-
cwd: Optional[str] = "",
127-
cookie_handler: Optional[Any] = None,
128-
httpc: Optional[Any] = None,
122+
self,
123+
conf: Union[dict, OPConfiguration],
124+
server_get: Callable,
125+
keyjar: Optional[KeyJar] = None,
126+
cwd: Optional[str] = "",
127+
cookie_handler: Optional[Any] = None,
128+
httpc: Optional[Any] = None,
129129
):
130130
OidcContext.__init__(self, conf, keyjar, entity_id=conf.get("issuer", ""))
131131
self.conf = conf
@@ -162,7 +162,7 @@ def __init__(
162162
self.login_hint2acrs = None
163163
self.par_db = {}
164164
self.provider_info = {}
165-
self.scope2claims = SCOPE2CLAIMS
165+
self.scope2claims = conf.get("scopes_to_claims", SCOPE2CLAIMS)
166166
self.session_manager = None
167167
self.sso_ttl = 14400 # 4h
168168
self.symkey = rndstr(24)
@@ -216,7 +216,6 @@ def __init__(
216216
"cookie_handler",
217217
"authentication",
218218
"id_token",
219-
"scope2claims",
220219
]:
221220
_func = getattr(self, "do_{}".format(item), None)
222221
if _func:

tests/test_05_jwt_token.py

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from oidcmsg.oidc import AccessTokenRequest
77
from oidcmsg.oidc import AuthorizationRequest
88
from oidcmsg.time_util import utc_time_sans_frac
9+
from oidcop.scopes import SCOPE2CLAIMS
910

1011
from oidcop import user_info
1112
from oidcop.authn_event import create_authn_event
@@ -275,3 +276,157 @@ def test_is_expired(self):
275276
assert access_token.is_active()
276277
# 4000 seconds in the future. Passed the lifetime.
277278
assert access_token.is_active(now=utc_time_sans_frac() + 4000) is False
279+
280+
281+
class TestEndpointWebID(object):
282+
@pytest.fixture(autouse=True)
283+
def create_endpoint(self):
284+
_scope2claims = SCOPE2CLAIMS.copy()
285+
_scope2claims.update({"webid": ["webid"]})
286+
conf = {
287+
"issuer": ISSUER,
288+
"httpc_params": {"verify": False, "timeout": 1},
289+
"capabilities": CAPABILITIES,
290+
"keys": {"uri_path": "jwks.json", "key_defs": KEYDEFS},
291+
"token_handler_args": {
292+
"jwks_file": "private/token_jwks.json",
293+
"code": {"lifetime": 600},
294+
"token": {
295+
"class": "oidcop.token.jwt_token.JWTToken",
296+
"kwargs": {
297+
"lifetime": 3600,
298+
"base_claims": {"eduperson_scoped_affiliation": None},
299+
"add_claims_by_scope": True,
300+
"aud": ["https://example.org/appl"],
301+
},
302+
},
303+
"refresh": {
304+
"class": "oidcop.token.jwt_token.JWTToken",
305+
"kwargs": {"lifetime": 3600, "aud": ["https://example.org/appl"], },
306+
},
307+
"id_token": {
308+
"class": "oidcop.token.id_token.IDToken",
309+
"kwargs": {
310+
"base_claims": {
311+
"email": {"essential": True},
312+
"email_verified": {"essential": True},
313+
}
314+
},
315+
},
316+
},
317+
"endpoint": {
318+
"provider_config": {
319+
"path": "{}/.well-known/openid-configuration",
320+
"class": ProviderConfiguration,
321+
"kwargs": {},
322+
},
323+
"registration": {"path": "{}/registration", "class": Registration, "kwargs": {}, },
324+
"authorization": {
325+
"path": "{}/authorization",
326+
"class": Authorization,
327+
"kwargs": {},
328+
},
329+
"token": {"path": "{}/token", "class": Token, "kwargs": {}},
330+
"session": {"path": "{}/end_session", "class": Session},
331+
"introspection": {"path": "{}/introspection", "class": Introspection},
332+
},
333+
"client_authn": verify_client,
334+
"authentication": {
335+
"anon": {
336+
"acr": INTERNETPROTOCOLPASSWORD,
337+
"class": "oidcop.user_authn.user.NoAuthn",
338+
"kwargs": {"user": "diana"},
339+
}
340+
},
341+
"template_dir": "template",
342+
"userinfo": {
343+
"class": user_info.UserInfo,
344+
"kwargs": {"db_file": full_path("users.json")},
345+
},
346+
"authz": {
347+
"class": AuthzHandling,
348+
"kwargs": {
349+
"grant_config": {
350+
"usage_rules": {
351+
"authorization_code": {
352+
"supports_minting": ["access_token", "refresh_token", "id_token", ],
353+
"max_usage": 1,
354+
},
355+
"access_token": {},
356+
"refresh_token": {
357+
"supports_minting": ["access_token", "refresh_token"],
358+
},
359+
},
360+
"expires_in": 43200,
361+
}
362+
},
363+
},
364+
"claims_interface": {"class": "oidcop.session.claims.ClaimsInterface", "kwargs": {}},
365+
"scopes_to_claims": _scope2claims,
366+
}
367+
server = Server(conf, keyjar=KEYJAR)
368+
self.endpoint_context = server.endpoint_context
369+
self.endpoint_context.cdb["client_1"] = {
370+
"client_secret": "hemligt",
371+
"redirect_uris": [("https://example.com/cb", None)],
372+
"client_salt": "salted",
373+
"token_endpoint_auth_method": "client_secret_post",
374+
"response_types": ["code", "token", "code id_token", "id_token"],
375+
"add_claims": {
376+
"always": {},
377+
"by_scope": {},
378+
},
379+
}
380+
self.session_manager = self.endpoint_context.session_manager
381+
self.user_id = "diana"
382+
self.endpoint = server.server_get("endpoint", "session")
383+
384+
def _create_session(self, auth_req, sub_type="public", sector_identifier=""):
385+
if sector_identifier:
386+
authz_req = auth_req.copy()
387+
authz_req["sector_identifier_uri"] = sector_identifier
388+
else:
389+
authz_req = auth_req
390+
client_id = authz_req["client_id"]
391+
ae = create_authn_event(self.user_id)
392+
return self.session_manager.create_session(
393+
ae, authz_req, self.user_id, client_id=client_id, sub_type=sub_type
394+
)
395+
396+
def _mint_token(self, token_class, grant, session_id, based_on=None, **kwargs):
397+
# Constructing an authorization code is now done
398+
return grant.mint_token(
399+
session_id=session_id,
400+
endpoint_context=self.endpoint_context,
401+
token_class=token_class,
402+
token_handler=self.session_manager.token_handler.handler[token_class],
403+
expires_at=utc_time_sans_frac() + 300, # 5 minutes from now
404+
based_on=based_on,
405+
**kwargs
406+
)
407+
408+
def test_parse(self):
409+
_auth_req = AuthorizationRequest(
410+
client_id="client_1",
411+
redirect_uri="https://example.com/cb",
412+
scope=["openid", "webid"],
413+
state="STATE",
414+
response_type="code",
415+
)
416+
417+
session_id = self._create_session(_auth_req)
418+
# apply consent
419+
grant = self.endpoint_context.authz(session_id=session_id, request=_auth_req)
420+
# grant = self.session_manager[session_id]
421+
code = self._mint_token("authorization_code", grant, session_id)
422+
access_token = self._mint_token(
423+
"access_token", grant, session_id, code, resources=[_auth_req["client_id"]]
424+
)
425+
426+
_verifier = JWT(self.endpoint_context.keyjar)
427+
_info = _verifier.unpack(access_token.value)
428+
429+
assert _info["token_class"] == "access_token"
430+
# assert _info["eduperson_scoped_affiliation"] == ["staff@example.org"]
431+
assert set(_info["aud"]) == {"client_1"}
432+
assert "webid" in _info

tests/users.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
},
1616
"eduperson_scoped_affiliation": [
1717
"staff@example.org"
18-
]
18+
],
19+
"webid": "http://bblfish.net/#hjs"
1920
},
2021
"babs": {
2122
"name": "Barbara J Jensen",

0 commit comments

Comments
 (0)