-
Notifications
You must be signed in to change notification settings - Fork 7
Unavailable scopes - behaviour expected #73
Description
I succesfully tested allowed_scopes and I found a default behaviour in oidcendpoint and oidcRP that I'd like to discuss.
When OidcRP have in its configuration some scopes not supported by OP (as found in Provider discovery) it simply omit them and send a authn request with which found available in provider discovery.
oidcendpoint when get a authz request with unavailable scopes, it simply ignore these and release its defaults (openid profile email address phone). The resulting access token could be used by a Client/RP (or a faulty RS) to give access to a resource for which the OP doesn't release the token for (simply ignoring the authz response and the auth code, no token introspection and the worst things ...).
The same behaviour if it have some allowed_scopes defined for a client_id that ask for a scope not configured for it.
In oidc.authorization we put a filter that increase this check:
oidcendpoint/oidc/authorization.py(682)process_request()
-> _cid = request_info["client_id"]
(Pdb) ll
672 def process_request(self, request_info=None, **kwargs):
673 """ The AuthorizationRequest endpoint
674
675 :param request_info: The authorization request as a dictionary
676 :return: dictionary
677 """
678
679 if isinstance(request_info, AuthorizationErrorResponse):
680 return request_info
681
682 -> _cid = request_info["client_id"]
683 cinfo = self.endpoint_context.cdb[_cid]
we have request_info e cinfo as follow
(Pdb) request_info
<oidcmsg.oidc.AuthorizationRequest object at 0x7feeb9e2a3d0>
(Pdb) request_info.__dict__
{'_dict': {'redirect_uri': 'https://127.0.0.1:8099/authz_cb/django_oidc_op', 'scope': ['openid', 'that_scope', 'profile', 'email', 'address', 'phone'], 'response_type': ['code'], 'nonce': '1mWXHQc7WEpe4HCOimA3s6Ko', 'state': 'P1y9a0KTqm1znr4ALOu31sNN6t8yXhRg', 'code_challenge': 'hz3Nx5jHHPdgaDUN6zuI8v9e4JOwHxo34FUFsCAtp3k', 'code_challenge_method': 'S256', 'client_id': '1UUl6cwNigmj'}, 'lax': False, 'jwt': None, 'jws_header': None, 'jwe_header': None, 'verify_ssl': True}
and
(Pdb) cinfo
{'id': 1, 'client_id': '1UUl6cwNigmj', 'client_salt': 'vWRsHApW', 'registration_access_token': 'dyIinaJe3gWFwJPqL2dVUHKKGcZhJdrv', 'registration_client_uri': 'https://127.0.0.1:8000/registration_api?client_id=1UUl6cwNigmj', 'client_id_issued_at': 1595799959, 'client_secret': '78be88872d5877c4ddb209335f4eb2fc5118a481a195a454c8b2ebcb', 'client_secret_expires_at': 1598391959, 'application_type': 'web', 'token_endpoint_auth_method': 'client_secret_basic', 'jwks_uri': 'https://127.0.0.1:8099/static/jwks.json', 'contacts': ['[email protected]'], 'grant_types': ['authorization_code'], 'response_types': ['code'], 'post_logout_redirect_uris': [], 'redirect_uris': [('https://127.0.0.1:8099/authz_cb/django_oidc_op', {})], 'allowed_scopes': ['that_custom_scope', 'openid']}
@rohe I suggest to put a simple filter here, somethings like:
# this prevents that authz would be released for unavailable scopes
for scope in request_info['scope']:
if scope not in client_allowed_scopes:
_msg = '{} requested an unauthorized scope ({})'
logger.warning(_msg.format(cinfo['client_id'],
scope))
raise UnAuthorizedClientScope()