Skip to content

Commit 7bce76d

Browse files
committed
Calculate what metadata to use, before modifying the
metadata based on provider info annd client registration.
1 parent fba8677 commit 7bce76d

13 files changed

+220
-34
lines changed

src/idpyoidc/client/service_context.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ def __init__(
187187

188188
self.construct_uris(response_types=_response_types)
189189

190+
self.map_supported_to_preferred()
191+
self.map_preferred_to_registered()
192+
190193
def __setitem__(self, key, value):
191194
setattr(self, key, value)
192195

tests/afs/client_1.lock.lock

Whitespace-only changes.

tests/afs/client_2.lock.lock

Whitespace-only changes.

tests/private/token_jwks.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"keys": [{"kty": "oct", "use": "enc", "kid": "code", "k": "vSHDkLBHhDStkR0NWu8519rmV5zmnm5_"}, {"kty": "oct", "use": "enc", "kid": "refresh", "k": "XB2_T04TbhR_hmpm439FntWuuidEDy-H"}]}
1+
{"keys": [{"kty": "oct", "use": "enc", "kid": "code", "k": "vSHDkLBHhDStkR0NWu8519rmV5zmnm5_"}, {"kty": "oct", "use": "enc", "kid": "refresh", "k": "Ps_KwX5Kw9lB89TaXnArVOZGClLgW2CX"}]}

tests/pub_client.jwks

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"keys": [{"kty": "EC", "use": "sig", "kid": "azZQQ2FEQjh3QnVZWVdrbHJkMEZSaWR6aVJ0LTBjeUFfeWRlbTRrRFZ5VQ", "crv": "P-256", "x": "2ADe18caWWGp6hpRbfa9HqQHDFNpid9xUmR56Wzm_wc", "y": "HnD_8QBanz4Y-UF8mKQFZXfqkGkXUSm34mLsdDKtSyk"}, {"kty": "RSA", "use": "sig", "kid": "SHEyYWcwNVk0LTdROTZzZ2FUWndIVXdack0xWUM5SEpwcS03dVUxWU4zRQ", "e": "AQAB", "n": "rRz52ddyP9Y2ezSlRsnkt-sjXfV_Ii7vOFX-cStLE3IUlVeSJGEe_kAASLr2r3BE2unjntaxj67NP8D95h_rzG1SpCklTEn-aTe3FOwNyTzUH_oiDVeRoEcf04Y43ciRGYRB5PhI6ii-2lYuig6hyUr776Qxiu6-0zw-M_ay2MgGSy5CEj55dDSvcUyxStUObxGpPWnEvybO1vnE7iJEWGNe0L5uPe5nLidOiR-JwjxSWEx1xZYtIjxaf2Ulu-qu4hwgwBUQdx4bNZyBfljKj55skWuHqPMG3xMjnedQC6Ms5bR3rIkbBpvmgI3kJK-4CZikM6ruyLo94-Lk19aYQw"}]}
1+
{"keys": [{"kty": "EC", "use": "sig", "kid": "azZQQ2FEQjh3QnVZWVdrbHJkMEZSaWR6aVJ0LTBjeUFfeWRlbTRrRFZ5VQ", "crv": "P-256", "x": "2ADe18caWWGp6hpRbfa9HqQHDFNpid9xUmR56Wzm_wc", "y": "HnD_8QBanz4Y-UF8mKQFZXfqkGkXUSm34mLsdDKtSyk"}, {"kty": "RSA", "use": "sig", "kid": "SHEyYWcwNVk0LTdROTZzZ2FUWndIVXdack0xWUM5SEpwcS03dVUxWU4zRQ", "n": "rRz52ddyP9Y2ezSlRsnkt-sjXfV_Ii7vOFX-cStLE3IUlVeSJGEe_kAASLr2r3BE2unjntaxj67NP8D95h_rzG1SpCklTEn-aTe3FOwNyTzUH_oiDVeRoEcf04Y43ciRGYRB5PhI6ii-2lYuig6hyUr776Qxiu6-0zw-M_ay2MgGSy5CEj55dDSvcUyxStUObxGpPWnEvybO1vnE7iJEWGNe0L5uPe5nLidOiR-JwjxSWEx1xZYtIjxaf2Ulu-qu4hwgwBUQdx4bNZyBfljKj55skWuHqPMG3xMjnedQC6Ms5bR3rIkbBpvmgI3kJK-4CZikM6ruyLo94-Lk19aYQw", "e": "AQAB"}]}

tests/request123456.jwt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
eyJhbGciOiJSUzI1NiIsImtpZCI6IlNIRXlZV2N3TlZrMExUZFJPVFp6WjJGVVduZElWWGRhY2sweFdVTTVTRXB3Y1MwM2RWVXhXVTR6UlEifQ.eyJyZXNwb25zZV90eXBlIjogImNvZGUiLCAic3RhdGUiOiAic3RhdGUiLCAicmVkaXJlY3RfdXJpIjogImh0dHBzOi8vZXhhbXBsZS5jb20vY2xpL2F1dGh6X2NiIiwgInNjb3BlIjogIm9wZW5pZCIsICJub25jZSI6ICI1ams1WkdMLTE3NXpHT0FPQW5yTlZra2paZXltS0JwOVFoek81QV90eDQwIiwgImNsaWVudF9pZCI6ICJjbGllbnRfaWQiLCAiaXNzIjogImNsaWVudF9pZCIsICJpYXQiOiAxNjg3MTgwNzk0LCAiYXVkIjogWyJodHRwczovL2V4YW1wbGUuY29tIl19.HUbiyiC0pypd8hamG9JJ-xQaJ7FEAVjDoy4jH00hJ5FtLqm87PAKIvD5aptYv8VzdpA5X8hCDUW4g0noNBbEsmvXeJpoXHSeVz_A4Ue8Ziz7z6dnrYf7BNFt3NyTibKVlkcWNGPBhEjyw0k4r6O86lQ2mSQjINJuqpR7VeEQyK7CBhDl5bicPctB4yGm4VksvC39695hhyGtUrUyrGW539g54VkG-x0kKv2HMc_ZGsnsEgFrT0fHKWuc1hPRkGi2XuSyhhD20zhnZhMGyTovwoZxmbx2seiIinjd0_wZVMZS277yUvMQTCvjOHJyu80XLLZqI71GguonCWdxIIrblQ
1+
eyJhbGciOiJSUzI1NiIsImtpZCI6IlNIRXlZV2N3TlZrMExUZFJPVFp6WjJGVVduZElWWGRhY2sweFdVTTVTRXB3Y1MwM2RWVXhXVTR6UlEifQ.eyJyZXNwb25zZV90eXBlIjogImNvZGUiLCAic3RhdGUiOiAic3RhdGUiLCAicmVkaXJlY3RfdXJpIjogImh0dHBzOi8vZXhhbXBsZS5jb20vY2xpL2F1dGh6X2NiIiwgInNjb3BlIjogIm9wZW5pZCIsICJub25jZSI6ICJpcno4SG5ELXFsOVhNYVJYUll1S3BpcEpHM2hiRWZ5akxBYXQwMjNLZEdvIiwgImNsaWVudF9pZCI6ICJjbGllbnRfaWQiLCAiaXNzIjogImNsaWVudF9pZCIsICJpYXQiOiAxNzEwODM2MDQwLCAiYXVkIjogWyJodHRwczovL2V4YW1wbGUuY29tIl19.EDvgPn7QJFm6O4d9QFU9gVZEmAREDIfl1RTiMtec7_ZJ4vGag3dxCyXgz15GbDrQgo6mqCydCe-Mal_4HBlRwMctqhy9NMIGM5PxIKzrqMjsk88jxAoz-WWw3I-pKrJUS4m23mEgLZkGQpB1N3YgO_RhG-7vGCkiJd_8VuomRMd2dX5_Jax3j12T7vhM_TUI9S6XJ5zsLn2ZOPQVXfoprr7HHY6UJjJ65Fp_hoGA3gmfJiHwbxYss8D2X1BNoLmEMze_e6cS-DGe648t2U47E77BvHdzsKi791Y1L3eizkm364gJ371KWbi3avvbSkTi4hEd3OikkyeMQZk6vDiJww

tests/test_09_work_condition.py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,141 @@ def test_registration_response(self):
252252

253253
# Not what I asked for but something I can handle
254254
assert to_use["subject_type"] == "pairwise"
255+
256+
def test_registration_response_consistence(self):
257+
client_conf = {
258+
"application_type": "web",
259+
"base_url": "https://client.example.org/",
260+
"redirect_uris": [
261+
"https://client.example.org/callback",
262+
"https://client.example.org/callback2",
263+
],
264+
"client_name": "My Example",
265+
"client_id": "client_id",
266+
"keys": {"key_defs": KEYSPEC, "read_only": True},
267+
"client_secret": "a longesh password",
268+
"logo_uri": "https://client.example.org/logo.png",
269+
"contacts": ["ve7jtb@example.org", "mary@example.org"],
270+
}
271+
272+
self.claims.load_conf(client_conf, self.supported)
273+
274+
self.claims.prefer = supported_to_preferred(
275+
supported=self.supported,
276+
preference=self.claims.prefer,
277+
base_url="https://example.com",
278+
)
279+
to_use_1 = preferred_to_registered(
280+
prefers=self.claims.prefer,
281+
supported=self.supported,
282+
)
283+
284+
OP_BASEURL = "https://example.com"
285+
provider_info_response = {
286+
"version": "3.0",
287+
"token_endpoint_auth_methods_supported": [
288+
"client_secret_post",
289+
"client_secret_basic",
290+
"client_secret_jwt",
291+
"private_key_jwt",
292+
],
293+
"issuer": OP_BASEURL,
294+
"jwks_uri": f"{OP_BASEURL}/static/jwks_tE2iLbOAqXhe8bqh.json",
295+
"authorization_endpoint": f"{OP_BASEURL}/authorization",
296+
"token_endpoint": f"{OP_BASEURL}/token",
297+
"userinfo_endpoint": f"{OP_BASEURL}/userinfo",
298+
"registration_endpoint": f"{OP_BASEURL}/registration",
299+
"end_session_endpoint": f"{OP_BASEURL}/end_session",
300+
# below are a set which the RP has default values but the OP overwrites
301+
"scopes_supported": ["openid", "fee", "faa", "foo", "fum"],
302+
"response_types_supported": ["code", "id_token", "code id_token"],
303+
"response_modes_supported": ["query", "form_post", "new_fangled"],
304+
# this does not have a default value
305+
"acr_values_supported": ["mfa"],
306+
}
307+
308+
pref = self.claims.prefer = supported_to_preferred(
309+
supported=self.supported,
310+
preference=self.claims.prefer,
311+
base_url="https://example.com",
312+
info=provider_info_response,
313+
)
314+
315+
registration_request = create_registration_request(self.claims.prefer, self.supported)
316+
317+
assert set(registration_request.keys()) == {
318+
"application_type",
319+
"client_name",
320+
"contacts",
321+
"default_max_age",
322+
"id_token_signed_response_alg",
323+
"jwks",
324+
"logo_uri",
325+
"redirect_uris",
326+
"request_object_signing_alg",
327+
"response_modes", # non-standard
328+
"response_types",
329+
"subject_type",
330+
"token_endpoint_auth_method",
331+
"token_endpoint_auth_signing_alg",
332+
"userinfo_signed_response_alg",
333+
}
334+
335+
assert registration_request["subject_type"] == "public"
336+
337+
registration_response = {
338+
"application_type": "web",
339+
"redirect_uris": [
340+
"https://client.example.org/callback",
341+
"https://client.example.org/callback2",
342+
],
343+
"client_name": "My Example",
344+
"logo_uri": "https://client.example.org/logo.png",
345+
"subject_type": "pairwise",
346+
"sector_identifier_uri": "https://other.example.net/file_of_redirect_uris.json",
347+
"token_endpoint_auth_method": "client_secret_basic",
348+
"jwks_uri": "https://client.example.org/my_public_keys.jwks",
349+
"userinfo_encrypted_response_alg": "RSA1_5",
350+
"userinfo_encrypted_response_enc": "A128CBC-HS256",
351+
"contacts": ["ve7jtb@example.org", "mary@example.org"],
352+
"request_uris": [
353+
"https://client.example.org/rf.txt#qpXaRLh_n93TTR9F252ValdatUQvQiJi5BDub2BeznA"
354+
],
355+
}
356+
357+
to_use_2 = preferred_to_registered(
358+
prefers=self.claims.prefer,
359+
supported=self.supported,
360+
registration_response=registration_response,
361+
)
362+
363+
assert set(to_use_2.keys()) == {
364+
"application_type",
365+
"client_id",
366+
"client_name",
367+
"client_secret",
368+
"contacts",
369+
"default_max_age",
370+
"encrypt_request_object_supported",
371+
"encrypt_userinfo_supported",
372+
"id_token_signed_response_alg",
373+
"jwks",
374+
"jwks_uri",
375+
"logo_uri",
376+
"redirect_uris",
377+
"request_object_signing_alg",
378+
"request_uris",
379+
"response_modes",
380+
"response_types",
381+
"scope",
382+
"sector_identifier_uri",
383+
"subject_type",
384+
"token_endpoint_auth_method",
385+
"token_endpoint_auth_signing_alg",
386+
"userinfo_encrypted_response_alg",
387+
"userinfo_encrypted_response_enc",
388+
"userinfo_signed_response_alg",
389+
}
390+
391+
# Not what I asked for but something I can handle
392+
assert to_use_2["subject_type"] == "pairwise"

tests/test_client_21_oidc_service.py

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import os
22

3-
import pytest
4-
import responses
53
from cryptojwt.exception import UnsupportedAlgorithm
64
from cryptojwt.jws import jws
75
from cryptojwt.jws.utils import left_hash
86
from cryptojwt.jwt import JWT
97
from cryptojwt.key_jar import build_keyjar
108
from cryptojwt.key_jar import init_key_jar
9+
import pytest
10+
import responses
1111

1212
from idpyoidc.client.defaults import DEFAULT_OIDC_SERVICES
1313
from idpyoidc.client.entity import Entity
@@ -725,7 +725,7 @@ def test_post_parse(self):
725725
"end_session_endpoint": "{}/end_session".format(OP_BASEURL),
726726
}
727727
_context = self.service.upstream_get("context")
728-
assert _context.claims.use == {}
728+
# assert _context.claims.use == {}
729729
resp = self.service.post_parse_response(provider_info_response)
730730

731731
iss_jwks = ISS_KEY.export_jwks_as_json(issuer_id=ISS)
@@ -788,7 +788,31 @@ def test_post_parse_2(self):
788788
"end_session_endpoint": "{}/end_session".format(OP_BASEURL),
789789
}
790790
_context = self.service.upstream_get("context")
791-
assert _context.claims.use == {}
791+
assert set(_context.claims.use.keys()) == {
792+
'application_type',
793+
'backchannel_logout_session_required',
794+
'backchannel_logout_uri',
795+
'callback_uris',
796+
'client_id',
797+
'client_secret',
798+
'contacts',
799+
'default_max_age',
800+
'encrypt_id_token_supported',
801+
'encrypt_request_object_supported',
802+
'encrypt_userinfo_supported',
803+
'grant_types',
804+
'id_token_signed_response_alg',
805+
'jwks',
806+
'post_logout_redirect_uris',
807+
'redirect_uris',
808+
'request_object_signing_alg',
809+
'response_modes',
810+
'response_types',
811+
'scope',
812+
'subject_type',
813+
'token_endpoint_auth_method',
814+
'token_endpoint_auth_signing_alg',
815+
'userinfo_signed_response_alg'}
792816
resp = self.service.post_parse_response(provider_info_response)
793817

794818
iss_jwks = ISS_KEY.export_jwks_as_json(issuer_id=ISS)

tests/test_client_22_oidc.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ def test_construct_refresh_token_request(self):
121121
"client_secret": "abcdefghijklmnop",
122122
"grant_type": "refresh_token",
123123
"refresh_token": "refresh_with_me",
124+
'scope': 'openid'
124125
}
125126

126127
def test_do_userinfo_request_init(self):

tests/test_client_30_rp_handler_oidc.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@
44
from urllib.parse import urlparse
55
from urllib.parse import urlsplit
66

7+
from cryptojwt.key_jar import init_key_jar
78
import pytest
89
import responses
9-
from cryptojwt.key_jar import init_key_jar
1010

1111
from idpyoidc.client.entity import Entity
1212
from idpyoidc.client.rp_handler import RPHandler
13-
from idpyoidc.message.oidc import JRD
1413
from idpyoidc.message.oidc import AccessTokenResponse
1514
from idpyoidc.message.oidc import AuthorizationResponse
1615
from idpyoidc.message.oidc import IdToken
16+
from idpyoidc.message.oidc import JRD
1717
from idpyoidc.message.oidc import Link
1818
from idpyoidc.message.oidc import OpenIDSchema
1919
from idpyoidc.message.oidc import ProviderConfigurationResponse
@@ -260,14 +260,21 @@ def test_init_client(self):
260260
}
261261

262262
_pref = [k for k, v in _context.prefers().items() if v]
263-
assert set(_pref) == {
264-
"client_id",
265-
"client_secret",
266-
"redirect_uris",
267-
"response_types_supported",
268-
"callback_uris",
269-
"scopes_supported",
270-
}
263+
assert set(_pref) == {'application_type',
264+
'callback_uris',
265+
'client_id',
266+
'client_secret',
267+
'default_max_age',
268+
'grant_types_supported',
269+
'id_token_signing_alg_values_supported',
270+
'redirect_uris',
271+
'request_object_signing_alg_values_supported',
272+
'response_modes_supported',
273+
'response_types_supported',
274+
'scopes_supported',
275+
'subject_types_supported',
276+
'token_endpoint_auth_signing_alg_values_supported',
277+
'userinfo_signing_alg_values_supported'}
271278

272279
_github_id = iss_id("github")
273280
_keyjar = _context.upstream_get("attribute", "keyjar")
@@ -304,8 +311,9 @@ def test_do_client_registration(self):
304311

305312
assert self.rph.hash2issuer["github"] == issuer
306313
assert (
307-
client.get_context().get_preference("callback_uris").get("post_logout_redirect_uris")
308-
is None
314+
client.get_context().get_preference("callback_uris").get(
315+
"post_logout_redirect_uris")
316+
is None
309317
)
310318

311319
def test_do_client_setup(self):

0 commit comments

Comments
 (0)