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

Commit d920971

Browse files
authored
Merge pull request #124 from nsklikas/feature-grant-types-per-client
Add grant_types_supported per client
2 parents 906a1be + 675be13 commit d920971

4 files changed

Lines changed: 75 additions & 4 deletions

File tree

docs/source/contents/conf.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,3 +712,11 @@ How to configure the release of the user claims per clients::
712712
"id_token": False,
713713
},
714714
},
715+
716+
Some of the allowed client configurations are (this is an ongoing work):
717+
718+
---------------------
719+
grant_types_supported
720+
---------------------
721+
722+
Configure the allowed grant types on the token endpoint.

src/oidcop/oauth2/token.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
from cryptojwt.jwe.exception import JWEException
66
from cryptojwt.jwt import utc_time_sans_frac
7-
87
from oidcmsg.message import Message
98
from oidcmsg.oauth2 import AccessTokenResponse
109
from oidcmsg.oauth2 import ResponseMessage
@@ -390,13 +389,20 @@ def configure_grant_types(self, grant_types_supported):
390389
def _post_parse_request(
391390
self, request: Union[Message, dict], client_id: Optional[str] = "", **kwargs
392391
):
393-
_helper = self.helper.get(request["grant_type"])
392+
grant_type = request["grant_type"]
393+
_helper = self.helper.get(grant_type)
394+
client = kwargs["endpoint_context"].cdb[client_id]
395+
if "grant_types_supported" in client and grant_type not in client["grant_types_supported"]:
396+
return self.error_cls(
397+
error="invalid_request",
398+
error_description=f"Unsupported grant_type: {grant_type}",
399+
)
394400
if _helper:
395401
return _helper.post_parse_request(request, client_id, **kwargs)
396402
else:
397403
return self.error_cls(
398404
error="invalid_request",
399-
error_description=f"Unsupported grant_type: {request['grant_type']}",
405+
error_description=f"Unsupported grant_type: {grant_type}",
400406
)
401407

402408
def process_request(self, request: Optional[Union[Message, dict]] = None, **kwargs):

tests/test_24_oauth2_token_endpoint.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,28 @@ def test_parse(self):
234234

235235
assert set(_req.keys()) == set(_token_request.keys())
236236

237+
def test_auth_code_grant_disallowed_per_client(self):
238+
areq = AUTH_REQ.copy()
239+
areq["scope"] = ["email"]
240+
self.endpoint_context.cdb["client_1"]["grant_types_supported"] = []
241+
242+
session_id = self._create_session(areq)
243+
grant = self.endpoint_context.authz(session_id, areq)
244+
code = self._mint_code(grant, areq["client_id"])
245+
246+
_cntx = self.endpoint_context
247+
248+
_token_request = TOKEN_REQ_DICT.copy()
249+
_token_request["code"] = code.value
250+
_req = self.token_endpoint.parse_request(_token_request)
251+
_resp = self.token_endpoint.process_request(request=_req, issue_refresh=True)
252+
253+
assert isinstance(_req, TokenErrorResponse)
254+
assert _req.to_dict() == {
255+
"error": "invalid_request",
256+
"error_description": "Unsupported grant_type: authorization_code",
257+
}
258+
237259
def test_process_request(self):
238260
session_id = self._create_session(AUTH_REQ)
239261
grant = self.session_manager[session_id]
@@ -336,6 +358,40 @@ def test_do_refresh_access_token(self):
336358
msg = self.token_endpoint.do_response(request=_req, **_resp)
337359
assert isinstance(msg, dict)
338360

361+
def test_refresh_grant_disallowed_per_client(self):
362+
areq = AUTH_REQ.copy()
363+
areq["scope"] = ["email"]
364+
self.endpoint_context.cdb["client_1"]["grant_types_supported"] = [
365+
"authorization_code"
366+
]
367+
368+
session_id = self._create_session(areq)
369+
grant = self.endpoint_context.authz(session_id, areq)
370+
code = self._mint_code(grant, areq["client_id"])
371+
372+
_cntx = self.endpoint_context
373+
374+
_token_request = TOKEN_REQ_DICT.copy()
375+
_token_request["code"] = code.value
376+
_req = self.token_endpoint.parse_request(_token_request)
377+
_resp = self.token_endpoint.process_request(request=_req, issue_refresh=True)
378+
379+
_request = REFRESH_TOKEN_REQ.copy()
380+
_request["refresh_token"] = _resp["response_args"]["refresh_token"]
381+
382+
_token_value = _resp["response_args"]["refresh_token"]
383+
_session_info = self.session_manager.get_session_info_by_token(_token_value)
384+
_token = self.session_manager.find_token(_session_info["session_id"], _token_value)
385+
_token.usage_rules["supports_minting"] = ["access_token", "refresh_token"]
386+
387+
_req = self.token_endpoint.parse_request(_request.to_json())
388+
389+
assert isinstance(_req, TokenErrorResponse)
390+
assert _req.to_dict() == {
391+
"error": "invalid_request",
392+
"error_description": "Unsupported grant_type: refresh_token",
393+
}
394+
339395
def test_do_2nd_refresh_access_token(self):
340396
areq = AUTH_REQ.copy()
341397
areq["scope"] = ["email"]

tests/test_35_oidc_token_endpoint.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from oidcop.user_authn.authn_context import INTERNETPROTOCOLPASSWORD
3030
from oidcop.user_info import UserInfo
3131
from oidcop.util import lv_pack
32+
from tests.test_24_oauth2_token_endpoint import TestEndpoint as _TestEndpoint
3233

3334
KEYDEFS = [
3435
{"type": "RSA", "key": "", "use": ["sig"]},
@@ -183,7 +184,7 @@ def conf():
183184
}
184185

185186

186-
class TestEndpoint(object):
187+
class TestEndpoint(_TestEndpoint):
187188
@pytest.fixture(autouse=True)
188189
def create_endpoint(self, conf):
189190
server = Server(OPConfiguration(conf=conf, base_path=BASEDIR), cwd=BASEDIR)

0 commit comments

Comments
 (0)