Skip to content

Commit 4ac1af6

Browse files
committed
Cleaned up.
response_type is about what's returned. response_mode is how.
1 parent d126975 commit 4ac1af6

21 files changed

+189
-67
lines changed

src/idpyoidc/client/claims/transform.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"subject_type": "subject_types_supported",
2222
"token_endpoint_auth_method": "token_endpoint_auth_methods_supported",
2323
"response_types": "response_types_supported",
24+
"response_modes": "response_modes_supported",
2425
"grant_types": "grant_types_supported",
2526
# In OAuth2 but not in OIDC
2627
"scope": "scopes_supported",

src/idpyoidc/client/defaults.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,12 @@
9292
SAML2_BEARER_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:saml2-bearer"
9393

9494
BASECHR = string.ascii_letters + string.digits
95+
96+
DEFAULT_RESPONSE_MODE = {
97+
"code": "query",
98+
"id_token": "fragment",
99+
"token": "fragment",
100+
"code token": "fragment",
101+
"code id_token": "fragment",
102+
"code id_token token": "fragment",
103+
}

src/idpyoidc/client/oauth2/authorization.py

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ class Authorization(Service):
4040
}
4141

4242
_callback_path = {
43-
"redirect_uris": { # based on response_types
44-
"code": "authz_cb",
45-
"implicit": "authz_im_cb",
43+
"redirect_uris": { # based on response_mode
44+
"query": "authz_cb",
45+
"fragment": "authz_im_cb",
4646
# "form_post": "form"
4747
}
4848
}
@@ -100,18 +100,21 @@ def post_parse_response(self, response, **kwargs):
100100
pass
101101
return response
102102

103-
def _do_flow(self, flow_type, response_types, context):
104-
if flow_type == "code":
103+
def _do_flow(self, flow_type, response_types, context) -> str:
104+
if flow_type == "query":
105105
if "code" in response_types:
106-
return True
107-
elif flow_type in ["implicit", "hybrid"]:
106+
return "query"
107+
elif flow_type == "fragment":
108108
if implicit_response_types(response_types):
109-
return True
109+
return "fragment"
110110
elif flow_type == 'form_post':
111111
rm = context.get_preference('response_modes_supported')
112112
if rm and 'form_post' in rm:
113-
return context.config.conf.get("separate_form_post_cb", True)
114-
return False
113+
if context.config.conf.get("separate_form_post_cb", True):
114+
return "form_post"
115+
else:
116+
return "query"
117+
return ''
115118

116119
def _do_redirect_uris(self, base_url, hex, context, callback_uris, response_types):
117120
_redirect_uris = context.get_preference("redirect_uris", [])
@@ -127,16 +130,20 @@ def _do_redirect_uris(self, base_url, hex, context, callback_uris, response_type
127130
pass
128131
else:
129132
callback_uris["redirect_uris"] = {}
130-
for flow_type, path in self._callback_path["redirect_uris"].items():
131-
if self._do_flow(flow_type, response_types, context):
133+
for flow_type in self._callback_path["redirect_uris"].keys():
134+
_var = self._do_flow(flow_type, response_types, context)
135+
if _var:
136+
_path = self._callback_path["redirect_uris"][_var]
132137
callback_uris["redirect_uris"][flow_type] = [
133-
self.get_uri(base_url, path, hex)
138+
self.get_uri(base_url, _path, hex)
134139
]
135140
else:
136141
callback_uris["redirect_uris"] = {}
137-
for flow_type, path in self._callback_path["redirect_uris"].items():
138-
if self._do_flow(flow_type, response_types, context):
139-
callback_uris["redirect_uris"][flow_type] = [self.get_uri(base_url, path, hex)]
142+
for flow_type in self._callback_path["redirect_uris"].keys():
143+
_var = self._do_flow(flow_type, response_types, context)
144+
if _var:
145+
_path = self._callback_path["redirect_uris"][_var]
146+
callback_uris["redirect_uris"][flow_type] = [self.get_uri(base_url, _path, hex)]
140147
return callback_uris
141148

142149
def construct_uris(

src/idpyoidc/client/oauth2/stand_alone_client.py

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from cryptojwt.key_bundle import keybundle_from_local_file
99

1010
from idpyoidc import verified_claim_name
11+
from idpyoidc.client.defaults import DEFAULT_RESPONSE_MODE
1112
from idpyoidc.client.exception import ConfigurationError
1213
from idpyoidc.client.exception import OidcServiceError
1314
from idpyoidc.client.oauth2 import Client
@@ -17,8 +18,8 @@
1718
from idpyoidc.exception import MissingRequiredAttribute
1819
from idpyoidc.exception import NotForMe
1920
from idpyoidc.message import Message
20-
from idpyoidc.message.oauth2 import is_error_message
2121
from idpyoidc.message.oauth2 import ResponseMessage
22+
from idpyoidc.message.oauth2 import is_error_message
2223
from idpyoidc.message.oidc import AuthorizationRequest
2324
from idpyoidc.message.oidc import AuthorizationResponse
2425
from idpyoidc.message.oidc import Claims
@@ -33,7 +34,7 @@
3334

3435
class StandAloneClient(Client):
3536

36-
def get_session_information(self,key):
37+
def get_session_information(self, key):
3738
"""
3839
This is the second of the methods users of this class should know about.
3940
It will return the complete session information as an
@@ -144,8 +145,32 @@ def _get_response_type(self, context, req_args: Optional[dict] = None):
144145
else:
145146
return context.claims.get_usage("response_types")[0]
146147

147-
def _get_response_mode(self, context, response_type):
148-
pass
148+
def _get_response_mode(self, context, response_type, request_args):
149+
if request_args:
150+
_requested = request_args.get('response_mode')
151+
else:
152+
_requested = None
153+
_supported = context.claims.get_usage('response_modes')
154+
if _requested:
155+
if _supported and _requested not in _supported:
156+
raise ValueError(
157+
"You can not use a response_mode you have not stated should be supported")
158+
159+
if DEFAULT_RESPONSE_MODE[response_type] == _requested:
160+
return None
161+
else:
162+
return _requested
163+
elif _supported:
164+
_type = response_type.split(' ')
165+
_type.sort()
166+
response_type = " ".join(_type)
167+
# Is it the default response mode
168+
if DEFAULT_RESPONSE_MODE[response_type] in _supported:
169+
return None
170+
else:
171+
return _supported[0]
172+
else:
173+
return None
149174

150175
def init_authorization(
151176
self,
@@ -167,14 +192,16 @@ def init_authorization(
167192

168193
_context = self.get_context()
169194
_response_type = self._get_response_type(_context, req_args)
195+
_response_mode = self._get_response_mode(_context, _response_type, req_args)
196+
170197
request_args = {
171198
"redirect_uri": pick_redirect_uri(
172-
_context, request_args=req_args, response_type=_response_type
199+
_context, request_args=req_args, response_type=_response_type,
200+
response_mode=_response_mode
173201
),
174202
"response_type": _response_type,
175203
}
176204

177-
_response_mode = self._get_response_mode(_context, _response_type)
178205
if _response_mode:
179206
request_args['response_mode'] = _response_mode
180207

src/idpyoidc/client/oauth2/utils.py

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ def pick_redirect_uri(
2727
context,
2828
request_args: Optional[Union[Message, dict]] = None,
2929
response_type: Optional[str] = "",
30+
response_mode: Optional[str] = ""
3031
):
3132
if request_args is None:
3233
request_args = {}
@@ -36,33 +37,31 @@ def pick_redirect_uri(
3637

3738
_callback_uris = context.get_preference("callback_uris")
3839
if _callback_uris:
39-
_callback_uris = _callback_uris.get("redirect_uris")
40-
41-
if _callback_uris:
42-
if not response_type:
43-
_conf_resp_types = context.get_usage("response_types", [])
44-
response_type = request_args.get("response_type")
45-
if not response_type and _conf_resp_types:
46-
response_type = _conf_resp_types[0]
47-
48-
_response_mode = request_args.get("response_mode")
40+
_redirect_uris = _callback_uris.get("redirect_uris")
41+
_response_mode = request_args.get("response_mode") or response_mode
4942

5043
if _response_mode:
5144
if _response_mode == "form_post":
5245
try:
53-
redirect_uri = _callback_uris["form_post"][0]
46+
redirect_uri = _redirect_uris["form_post"][0]
5447
except KeyError:
55-
redirect_uri = _callback_uris["code"][0]
48+
redirect_uri = _redirect_uris["code"][0]
5649
elif response_type == "code" or response_type == ["code"]:
57-
redirect_uri = _callback_uris["code"][0]
50+
redirect_uri = _redirect_uris["code"][0]
5851
else:
59-
redirect_uri = _callback_uris["implicit"][0]
52+
redirect_uri = _redirect_uris["implicit"][0]
6053
else:
54+
if not response_type:
55+
_conf_resp_types = context.get_usage("response_types", [])
56+
response_type = request_args.get("response_type")
57+
if not response_type and _conf_resp_types:
58+
response_type = _conf_resp_types[0]
59+
6160
if response_type == "code" or response_type == ["code"]:
62-
_response_mode = "code"
61+
_response_mode = "query"
6362
else:
64-
_response_mode = "implicit"
65-
redirect_uri = _callback_uris[_response_mode][0]
63+
_response_mode = "fragment"
64+
redirect_uri = _redirect_uris[_response_mode][0]
6665

6766
logger.debug(
6867
f"pick_redirect_uris: response_type={response_type}, response_mode={_response_mode}, "

src/idpyoidc/client/oidc/authorization.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ class Authorization(authorization.Authorization):
4747

4848
_callback_path = {
4949
"request_uris": ["req"],
50-
"redirect_uris": { # based on response_types
51-
"code": "authz_cb",
52-
"implicit": "authz_tok_cb",
50+
"redirect_uris": { # based on response_mode
51+
"query": "authz_cb",
52+
"fragment": "authz_tok_cb",
5353
"form_post": "authz_cb_form",
5454
},
5555
}
@@ -368,15 +368,15 @@ def _do_request_uris(self, base_url, hex, context, callback_uris):
368368
def _do_type(self, context, typ, response_types):
369369
if typ == "code" and "code" in response_types:
370370
if typ in context.get_preference("response_modes_supported"):
371-
return True
371+
return "query"
372372
elif typ == "implicit":
373373
if typ in context.get_preference("response_modes_supported"):
374374
if implicit_response_types(response_types):
375-
return True
375+
return "fragment"
376376
elif typ == "form_post":
377377
if typ in context.get_preference("response_modes_supported"):
378-
return True
379-
return False
378+
return "form_post"
379+
return ''
380380

381381
def construct_uris(
382382
self,

src/idpyoidc/message/oidc/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,7 @@ class RegistrationRequest(Message):
635635
"backchannel_logout_session_required": SINGLE_OPTIONAL_BOOLEAN,
636636
# "federation_type": OPTIONAL_LIST_OF_STRINGS,
637637
# "organization_name": SINGLE_OPTIONAL_STRING,
638+
"response_modes": OPTIONAL_LIST_OF_STRINGS,
638639
}
639640
c_default = {"application_type": "web", "response_types": ["code"]}
640641
c_allowed_values = {

src/idpyoidc/server/claims/oidc.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"subject_type": "subject_types_supported",
2222
"token_endpoint_auth_method": "token_endpoint_auth_methods_supported",
2323
"response_types": "response_types_supported",
24+
"response_modes": "response_modes_supported",
2425
"grant_types": "grant_types_supported",
2526
# In OAuth2 but not in OIDC
2627
"scope": "scopes_supported",

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": "c5ww2m_bA2iOZXxyDJfTpxQjymMdLmqG"}]}
1+
{"keys": [{"kty": "oct", "use": "enc", "kid": "code", "k": "vSHDkLBHhDStkR0NWu8519rmV5zmnm5_"}, {"kty": "oct", "use": "enc", "kid": "refresh", "k": "ygvi663s6qysl0MvtSqO4EH6tBeDjOQ8"}]}

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"}]}

0 commit comments

Comments
 (0)