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

Commit ce04493

Browse files
authored
Merge pull request #113 from ctriant/per_client_claims_by_scope
WIP: Introduce add_claims_by_scope per client configuration
2 parents 78cae68 + a84eadf commit ce04493

6 files changed

Lines changed: 76 additions & 18 deletions

File tree

src/oidcop/session/claims.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,11 @@ def authorization_request_claims(self,
4242

4343
def _get_client_claims(self, client_id, usage):
4444
client_info = self.server_get("endpoint_context").cdb.get(client_id, {})
45-
client_claims = client_info.get("{}_claims".format(usage), {})
45+
client_claims = (
46+
client_info.get("add_claims", {})
47+
.get("always", {})
48+
.get(usage, {})
49+
)
4650
if isinstance(client_claims, list):
4751
client_claims = {k: None for k in client_claims}
4852
return client_claims
@@ -95,8 +99,19 @@ def get_claims(self, session_id: str, scopes: str, claims_release_point: str) ->
9599

96100
claims.update(base_claims)
97101

98-
# Scopes can in some cases equate to set of claims, is that used here ?
99-
if module.kwargs.get("add_claims_by_scope"):
102+
# If specific client configuration exists overwrite add_claims_by_scope
103+
if client_id in _context.cdb:
104+
add_claims_by_scope = (
105+
_context.cdb[client_id].get("add_claims", {})
106+
.get("by_scope", {})
107+
.get(claims_release_point, {})
108+
)
109+
if isinstance(add_claims_by_scope, dict) and not add_claims_by_scope:
110+
add_claims_by_scope = module.kwargs.get("add_claims_by_scope")
111+
else:
112+
add_claims_by_scope = module.kwargs.get("add_claims_by_scope")
113+
114+
if add_claims_by_scope:
100115
if scopes:
101116
_scopes = _context.scopes_handler.filter_scopes(client_id, _context, scopes)
102117

tests/test_01_claims.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ def create_idtoken(self):
114114
"client_salt": "salted",
115115
"token_endpoint_auth_method": "client_secret_post",
116116
"response_types": ["code", "token", "code id_token", "id_token"],
117+
"add_claims": {
118+
"always": {},
119+
},
117120
}
118121
server.endpoint_context.keyjar.add_symmetric(
119122
"client_1", "hemligtochintekort", ["sig", "enc"]
@@ -173,17 +176,17 @@ def test_get_client_claims_0(self, usage):
173176
assert claims == {}
174177

175178
def test_get_client_claims_id_token_1(self):
176-
self.endpoint_context.cdb["client_1"]["id_token_claims"] = ["name", "email"]
179+
self.endpoint_context.cdb["client_1"]["add_claims"]["always"]["id_token"] = ["name", "email"]
177180
claims = self.claims_interface._get_client_claims("client_1", "id_token")
178181
assert set(claims.keys()) == {"name", "email"}
179182

180183
def test_get_client_claims_userinfo_1(self):
181-
self.endpoint_context.cdb["client_1"]["userinfo_claims"] = ["email", "address"]
184+
self.endpoint_context.cdb["client_1"]["add_claims"]["always"]["userinfo"] = ["email", "address"]
182185
claims = self.claims_interface._get_client_claims("client_1", "userinfo")
183186
assert set(claims.keys()) == {"address", "email"}
184187

185188
def test_get_client_claims_introspection_1(self):
186-
self.endpoint_context.cdb["client_1"]["introspection_claims"] = ["email"]
189+
self.endpoint_context.cdb["client_1"]["add_claims"]["always"]["introspection"] = ["email"]
187190
claims = self.claims_interface._get_client_claims("client_1", "introspection")
188191
assert set(claims.keys()) == {"email"}
189192

@@ -207,7 +210,7 @@ def test_get_claims_id_token_2(self):
207210
"base_claims": {"email": None, "email_verified": None},
208211
"enable_claims_per_client": True,
209212
}
210-
self.endpoint_context.cdb["client_1"]["id_token_claims"] = ["name", "email"]
213+
self.endpoint_context.cdb["client_1"]["add_claims"]["always"]["id_token"] = ["name", "email"]
211214

212215
claims = self.claims_interface.get_claims(session_id, [], "id_token")
213216
assert set(claims.keys()) == {"name", "email", "email_verified"}
@@ -219,7 +222,7 @@ def test_get_claims_id_token_3(self):
219222
"enable_claims_per_client": True,
220223
"add_claims_by_scope": True,
221224
}
222-
self.endpoint_context.cdb["client_1"]["id_token_claims"] = ["name", "email"]
225+
self.endpoint_context.cdb["client_1"]["add_claims"]["always"]["id_token"] = ["name", "email"]
223226

224227
claims = self.claims_interface.get_claims(session_id, ["openid", "address"], "id_token")
225228
assert set(claims.keys()) == {
@@ -238,7 +241,7 @@ def test_get_claims_userinfo_3(self):
238241
"enable_claims_per_client": True,
239242
"add_claims_by_scope": True,
240243
}
241-
self.endpoint_context.cdb["client_1"]["userinfo_claims"] = ["name", "email"]
244+
self.endpoint_context.cdb["client_1"]["add_claims"]["always"]["userinfo"] = ["name", "email"]
242245

243246
claims = self.claims_interface.get_claims(session_id, ["openid", "address"], "userinfo")
244247
assert set(claims.keys()) == {
@@ -256,7 +259,7 @@ def test_get_claims_introspection_3(self):
256259
"enable_claims_per_client": True,
257260
"add_claims_by_scope": True,
258261
}
259-
self.endpoint_context.cdb["client_1"]["introspection_claims"] = [
262+
self.endpoint_context.cdb["client_1"]["add_claims"]["always"]["introspection"] = [
260263
"name",
261264
"email",
262265
]
@@ -280,7 +283,7 @@ def test_get_claims_access_token_3(self):
280283
"enable_claims_per_client": True,
281284
"add_claims_by_scope": True,
282285
}
283-
self.endpoint_context.cdb["client_1"]["access_token_claims"] = ["name", "email"]
286+
self.endpoint_context.cdb["client_1"]["add_claims"]["always"]["access_token"] = ["name", "email"]
284287

285288
session_id = self._create_session(AREQ)
286289
claims = self.claims_interface.get_claims(session_id, ["openid", "address"], "access_token")
@@ -320,7 +323,7 @@ def test_get_claims_all_usage_2(self):
320323
self.server.server_get("endpoint", "userinfo").kwargs = {
321324
"enable_claims_per_client": True,
322325
}
323-
self.endpoint_context.cdb["client_1"]["userinfo_claims"] = ["name", "email"]
326+
self.endpoint_context.cdb["client_1"]["add_claims"]["always"]["userinfo"] = ["name", "email"]
324327

325328
self.server.server_get("endpoint", "introspection").kwargs = {"add_claims_by_scope": True}
326329

@@ -349,7 +352,7 @@ def test_get_user_claims(self):
349352
self.server.server_get("endpoint", "userinfo").kwargs = {
350353
"enable_claims_per_client": True,
351354
}
352-
self.endpoint_context.cdb["client_1"]["userinfo_claims"] = ["name", "email"]
355+
self.endpoint_context.cdb["client_1"]["add_claims"]["always"]["userinfo"] = ["name", "email"]
353356

354357
self.server.server_get("endpoint", "introspection").kwargs = {"add_claims_by_scope": True}
355358

tests/test_05_id_token.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ def create_session_manager(self):
170170
"client_salt": "salted",
171171
"token_endpoint_auth_method": "client_secret_post",
172172
"response_types": ["code", "token", "code id_token", "id_token"],
173+
"add_claims": {
174+
"always": {},
175+
"by_scope": {},
176+
},
173177
}
174178
self.endpoint_context.keyjar.add_symmetric("client_1", "hemligtochintekort", ["sig", "enc"])
175179
self.session_manager = self.endpoint_context.session_manager
@@ -487,7 +491,7 @@ def test_client_claims(self):
487491
grant = self.session_manager[session_id]
488492

489493
self.session_manager.token_handler["id_token"].kwargs["enable_claims_per_client"] = True
490-
self.endpoint_context.cdb["client_1"]["id_token_claims"] = {"address": None}
494+
self.endpoint_context.cdb["client_1"]["add_claims"]["always"]["id_token"] = {"address": None}
491495

492496
_claims = self.endpoint_context.claims_interface.get_claims(
493497
session_id=session_id, scopes=AREQ["scope"], claims_release_point="id_token"
@@ -543,6 +547,28 @@ def test_client_claims_scopes(self):
543547
assert "email" in res
544548
assert "nickname" not in res
545549

550+
def test_client_claims_scopes_per_client(self):
551+
session_id = self._create_session(AREQS)
552+
grant = self.session_manager[session_id]
553+
self.session_manager.token_handler["id_token"].kwargs["add_claims_by_scope"] = True
554+
self.endpoint_context.cdb[AREQS["client_id"]]["add_claims"]["by_scope"]["id_token"] = False
555+
556+
_claims = self.endpoint_context.claims_interface.get_claims(
557+
session_id=session_id, scopes=AREQS["scope"], claims_release_point="id_token"
558+
)
559+
grant.claims = {"id_token": _claims}
560+
561+
id_token = self._mint_id_token(grant, session_id)
562+
563+
client_keyjar = KeyJar()
564+
_jwks = self.endpoint_context.keyjar.export_jwks()
565+
client_keyjar.import_jwks(_jwks, self.endpoint_context.issuer)
566+
_jwt = JWT(key_jar=client_keyjar, iss="client_1")
567+
res = _jwt.unpack(id_token.value)
568+
assert "address" not in res
569+
assert "email" in res
570+
assert "nickname" not in res
571+
546572
def test_client_claims_scopes_and_request_claims_no_match(self):
547573
session_id = self._create_session(AREQRC)
548574
grant = self.session_manager[session_id]

tests/test_05_jwt_token.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@ def create_endpoint(self):
186186
"client_salt": "salted",
187187
"token_endpoint_auth_method": "client_secret_post",
188188
"response_types": ["code", "token", "code id_token", "id_token"],
189+
"add_claims": {
190+
"always": {},
191+
"by_scope": {},
192+
},
189193
}
190194
self.session_manager = self.endpoint_context.session_manager
191195
self.user_id = "diana"
@@ -247,7 +251,7 @@ def test_info(self):
247251
@pytest.mark.parametrize("enable_claims_per_client", [True, False])
248252
def test_enable_claims_per_client(self, enable_claims_per_client):
249253
# Set up configuration
250-
self.endpoint_context.cdb["client_1"]["access_token_claims"] = {"address": None}
254+
self.endpoint_context.cdb["client_1"]["add_claims"]["always"]["access_token"] = {"address": None}
251255
self.endpoint_context.session_manager.token_handler.handler["access_token"].kwargs[
252256
"enable_claims_per_client"
253257
] = enable_claims_per_client

tests/test_07_userinfo.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,12 @@ def create_endpoint_context(self):
255255
server = Server(OPConfiguration(conf=conf, base_path=BASEDIR), cwd=BASEDIR)
256256
self.endpoint_context = server.endpoint_context
257257
# Just has to be there
258-
self.endpoint_context.cdb["client1"] = {}
258+
self.endpoint_context.cdb["client1"] = {
259+
"add_claims": {
260+
"always": {},
261+
"by_scope": {},
262+
},
263+
}
259264
self.session_manager = self.endpoint_context.session_manager
260265
self.claims_interface = ClaimsInterface(server.server_get)
261266
self.user_id = "diana"
@@ -371,7 +376,7 @@ def test_collect_user_info_enable_claims_per_client(self):
371376
_userinfo_endpoint.kwargs["enable_claims_per_client"] = True
372377
del _userinfo_endpoint.kwargs["base_claims"]
373378

374-
self.endpoint_context.cdb[_req["client_id"]]["userinfo_claims"] = {"phone_number": None}
379+
self.endpoint_context.cdb[_req["client_id"]]["add_claims"]["always"]["userinfo"] = {"phone_number": None}
375380

376381
_userinfo_restriction = self.claims_interface.get_claims(
377382
session_id=session_id, scopes=_req["scope"], claims_release_point="userinfo"

tests/test_31_oauth2_introspection.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,12 @@ def create_endpoint(self, jwt_token):
192192
"client_salt": "salted",
193193
"token_endpoint_auth_method": "client_secret_post",
194194
"response_types": ["code", "token", "code id_token", "id_token"],
195-
"introspection_claims": {"nickname": None, "eduperson_scoped_affiliation": None,},
195+
"add_claims": {
196+
"always": {
197+
"introspection": ["nickname", "eduperson_scoped_affiliation"],
198+
},
199+
"by_scope": {},
200+
},
196201
}
197202
endpoint_context.keyjar.import_jwks_as_json(
198203
endpoint_context.keyjar.export_jwks_as_json(private=True), endpoint_context.issuer,

0 commit comments

Comments
 (0)