From c14d2f055a638e4244f48f5957beb6a01d010df4 Mon Sep 17 00:00:00 2001 From: Ignacio Fiorentino Date: Fri, 9 Sep 2016 14:49:41 -0300 Subject: [PATCH] Remove Params() object from endpoints classes. --- oidc_provider/lib/endpoints/authorize.py | 102 ++++++++++------------- oidc_provider/lib/endpoints/token.py | 66 +++++++-------- oidc_provider/lib/utils/params.py | 7 -- oidc_provider/views.py | 33 ++++---- 4 files changed, 94 insertions(+), 114 deletions(-) delete mode 100644 oidc_provider/lib/utils/params.py diff --git a/oidc_provider/lib/endpoints/authorize.py b/oidc_provider/lib/endpoints/authorize.py index f6161b5..1844eb6 100644 --- a/oidc_provider/lib/endpoints/authorize.py +++ b/oidc_provider/lib/endpoints/authorize.py @@ -14,7 +14,6 @@ from oidc_provider.lib.errors import ( ClientIdError, RedirectUriError, ) -from oidc_provider.lib.utils.params import Params from oidc_provider.lib.utils.token import ( create_code, create_id_token, @@ -35,22 +34,22 @@ class AuthorizeEndpoint(object): def __init__(self, request): self.request = request - self.params = Params() + self.params = {} self._extract_params() # Determine which flow to use. - if self.params.response_type in ['code']: + if self.params['response_type'] in ['code']: self.grant_type = 'authorization_code' - elif self.params.response_type in ['id_token', 'id_token token', 'token']: + elif self.params['response_type'] in ['id_token', 'id_token token', 'token']: self.grant_type = 'implicit' - elif self.params.response_type in ['code token', 'code id_token', 'code id_token token']: + elif self.params['response_type'] in ['code token', 'code id_token', 'code id_token token']: self.grant_type = 'hybrid' else: self.grant_type = None # Determine if it's an OpenID Authentication request (or OAuth2). - self.is_authentication = 'openid' in self.params.scope + self.is_authentication = 'openid' in self.params['scope'] def _extract_params(self): """ @@ -64,58 +63,54 @@ class AuthorizeEndpoint(object): query_dict = (self.request.POST if self.request.method == 'POST' else self.request.GET) - self.params.client_id = query_dict.get('client_id', '') - self.params.redirect_uri = query_dict.get('redirect_uri', '') - self.params.response_type = query_dict.get('response_type', '') - self.params.scope = query_dict.get('scope', '').split() - self.params.state = query_dict.get('state', '') - - self.params.nonce = query_dict.get('nonce', '') - self.params.prompt = query_dict.get('prompt', '') - self.params.code_challenge = query_dict.get('code_challenge', '') - self.params.code_challenge_method = query_dict.get('code_challenge_method', '') + self.params['client_id'] = query_dict.get('client_id', '') + self.params['redirect_uri'] = query_dict.get('redirect_uri', '') + self.params['response_type'] = query_dict.get('response_type', '') + self.params['scope'] = query_dict.get('scope', '').split() + self.params['state'] = query_dict.get('state', '') + self.params['nonce'] = query_dict.get('nonce', '') + self.params['prompt'] = query_dict.get('prompt', '') + self.params['code_challenge'] = query_dict.get('code_challenge', '') + self.params['code_challenge_method'] = query_dict.get('code_challenge_method', '') def validate_params(self): # Client validation. try: - self.client = Client.objects.get(client_id=self.params.client_id) + self.client = Client.objects.get(client_id=self.params['client_id']) except Client.DoesNotExist: - logger.debug('[Authorize] Invalid client identifier: %s', self.params.client_id) + logger.debug('[Authorize] Invalid client identifier: %s', self.params['client_id']) raise ClientIdError() # Redirect URI validation. - if self.is_authentication and not self.params.redirect_uri: + if self.is_authentication and not self.params['redirect_uri']: logger.debug('[Authorize] Missing redirect uri.') raise RedirectUriError() - clean_redirect_uri = urlsplit(self.params.redirect_uri) + clean_redirect_uri = urlsplit(self.params['redirect_uri']) clean_redirect_uri = urlunsplit(clean_redirect_uri._replace(query='')) if not (clean_redirect_uri in self.client.redirect_uris): - logger.debug('[Authorize] Invalid redirect uri: %s', self.params.redirect_uri) + logger.debug('[Authorize] Invalid redirect uri: %s', self.params['redirect_uri']) raise RedirectUriError() # Grant type validation. if not self.grant_type: - logger.debug('[Authorize] Invalid response type: %s', self.params.response_type) - raise AuthorizeError(self.params.redirect_uri, 'unsupported_response_type', - self.grant_type) + logger.debug('[Authorize] Invalid response type: %s', self.params['response_type']) + raise AuthorizeError(self.params['redirect_uri'], 'unsupported_response_type', self.grant_type) # Nonce parameter validation. - if self.is_authentication and self.grant_type == 'implicit' and not self.params.nonce: - raise AuthorizeError(self.params.redirect_uri, 'invalid_request', - self.grant_type) + if self.is_authentication and self.grant_type == 'implicit' and not self.params['nonce']: + raise AuthorizeError(self.params['redirect_uri'], 'invalid_request', self.grant_type) # Response type parameter validation. - if self.is_authentication and self.params.response_type != self.client.response_type: - raise AuthorizeError(self.params.redirect_uri, 'invalid_request', - self.grant_type) + if self.is_authentication and self.params['response_type'] != self.client.response_type: + raise AuthorizeError(self.params['redirect_uri'], 'invalid_request', self.grant_type) # PKCE validation of the transformation method. - if self.params.code_challenge: - if not (self.params.code_challenge_method in ['plain', 'S256']): - raise AuthorizeError(self.params.redirect_uri, 'invalid_request', self.grant_type) + if self.params['code_challenge']: + if not (self.params['code_challenge_method'] in ['plain', 'S256']): + raise AuthorizeError(self.params['redirect_uri'], 'invalid_request', self.grant_type) def create_response_uri(self): - uri = urlsplit(self.params.redirect_uri) + uri = urlsplit(self.params['redirect_uri']) query_params = parse_qs(uri.query) query_fragment = parse_qs(uri.fragment) @@ -124,24 +119,24 @@ class AuthorizeEndpoint(object): code = create_code( user=self.request.user, client=self.client, - scope=self.params.scope, - nonce=self.params.nonce, + scope=self.params['scope'], + nonce=self.params['nonce'], is_authentication=self.is_authentication, - code_challenge=self.params.code_challenge, - code_challenge_method=self.params.code_challenge_method) + code_challenge=self.params['code_challenge'], + code_challenge_method=self.params['code_challenge_method']) code.save() if self.grant_type == 'authorization_code': query_params['code'] = code.code - query_params['state'] = self.params.state if self.params.state else '' + query_params['state'] = self.params['state'] if self.params['state'] else '' elif self.grant_type in ['implicit', 'hybrid']: token = create_token( user=self.request.user, client=self.client, - scope=self.params.scope) + scope=self.params['scope']) # Check if response_type must include access_token in the response. - if self.params.response_type in ['id_token token', 'token', 'code token', 'code id_token token']: + if self.params['response_type'] in ['id_token token', 'token', 'code token', 'code id_token token']: query_fragment['access_token'] = token.access_token # We don't need id_token if it's an OAuth2 request. @@ -149,9 +144,9 @@ class AuthorizeEndpoint(object): kwargs = { 'user': self.request.user, 'aud': self.client.client_id, - 'nonce': self.params.nonce, + 'nonce': self.params['nonce'], 'request': self.request, - 'scope': self.params.scope, + 'scope': self.params['scope'], } # Include at_hash when access_token is being returned. if 'access_token' in query_fragment: @@ -159,7 +154,7 @@ class AuthorizeEndpoint(object): id_token_dic = create_id_token(**kwargs) # Check if response_type must include id_token in the response. - if self.params.response_type in ['id_token', 'id_token token', 'code id_token', 'code id_token token']: + if self.params['response_type'] in ['id_token', 'id_token token', 'code id_token', 'code id_token token']: query_fragment['id_token'] = encode_id_token(id_token_dic, self.client) else: id_token_dic = {} @@ -176,14 +171,11 @@ class AuthorizeEndpoint(object): query_fragment['expires_in'] = settings.get('OIDC_TOKEN_EXPIRE') - query_fragment['state'] = self.params.state if self.params.state else '' + query_fragment['state'] = self.params['state'] if self.params['state'] else '' except Exception as error: logger.debug('[Authorize] Error when trying to create response uri: %s', error) - raise AuthorizeError( - self.params.redirect_uri, - 'server_error', - self.grant_type) + raise AuthorizeError(self.params['redirect_uri'], 'server_error', self.grant_type) uri = uri._replace(query=urlencode(query_params, doseq=True)) uri = uri._replace(fragment=urlencode(query_fragment, doseq=True)) @@ -208,7 +200,7 @@ class AuthorizeEndpoint(object): 'date_given': date_given, } ) - uc.scope = self.params.scope + uc.scope = self.params['scope'] # Rewrite expires_at and date_given if object already exists. if not created: @@ -225,10 +217,8 @@ class AuthorizeEndpoint(object): """ value = False try: - uc = UserConsent.objects.get(user=self.request.user, - client=self.client) - if (set(self.params.scope).issubset(uc.scope)) and \ - not (uc.has_expired()): + uc = UserConsent.objects.get(user=self.request.user, client=self.client) + if (set(self.params['scope']).issubset(uc.scope)) and not (uc.has_expired()): value = True except UserConsent.DoesNotExist: pass @@ -239,9 +229,9 @@ class AuthorizeEndpoint(object): """ Return a list with the description of all the scopes requested. """ - scopes = StandardScopeClaims.get_scopes_info(self.params.scope) + scopes = StandardScopeClaims.get_scopes_info(self.params['scope']) if settings.get('OIDC_EXTRA_SCOPE_CLAIMS'): - scopes_extra = settings.get('OIDC_EXTRA_SCOPE_CLAIMS', import_str=True).get_scopes_info(self.params.scope) + scopes_extra = settings.get('OIDC_EXTRA_SCOPE_CLAIMS', import_str=True).get_scopes_info(self.params['scope']) for index_extra, scope_extra in enumerate(scopes_extra): for index, scope in enumerate(scopes[:]): if scope_extra['scope'] == scope['scope']: diff --git a/oidc_provider/lib/endpoints/token.py b/oidc_provider/lib/endpoints/token.py index 77cd636..707f403 100644 --- a/oidc_provider/lib/endpoints/token.py +++ b/oidc_provider/lib/endpoints/token.py @@ -12,7 +12,6 @@ from django.http import JsonResponse from oidc_provider.lib.errors import ( TokenError, ) -from oidc_provider.lib.utils.params import Params from oidc_provider.lib.utils.token import ( create_id_token, create_token, @@ -33,23 +32,22 @@ class TokenEndpoint(object): def __init__(self, request): self.request = request - self.params = Params() + self.params = {} self._extract_params() def _extract_params(self): client_id, client_secret = self._extract_client_auth() - self.params.client_id = client_id - self.params.client_secret = client_secret - self.params.redirect_uri = unquote(self.request.POST.get('redirect_uri', '')) - self.params.grant_type = self.request.POST.get('grant_type', '') - self.params.code = self.request.POST.get('code', '') - self.params.state = self.request.POST.get('state', '') - self.params.scope = self.request.POST.get('scope', '') - self.params.refresh_token = self.request.POST.get('refresh_token', '') - - # PKCE parameters. - self.params.code_verifier = self.request.POST.get('code_verifier') + self.params['client_id'] = client_id + self.params['client_secret'] = client_secret + self.params['redirect_uri'] = unquote(self.request.POST.get('redirect_uri', '')) + self.params['grant_type'] = self.request.POST.get('grant_type', '') + self.params['code'] = self.request.POST.get('code', '') + self.params['state'] = self.request.POST.get('state', '') + self.params['scope'] = self.request.POST.get('scope', '') + self.params['refresh_token'] = self.request.POST.get('refresh_token', '') + # PKCE parameter. + self.params['code_verifier'] = self.request.POST.get('code_verifier') def _extract_client_auth(self): """ @@ -76,68 +74,68 @@ class TokenEndpoint(object): def validate_params(self): try: - self.client = Client.objects.get(client_id=self.params.client_id) + self.client = Client.objects.get(client_id=self.params['client_id']) except Client.DoesNotExist: - logger.debug('[Token] Client does not exist: %s', self.params.client_id) + logger.debug('[Token] Client does not exist: %s', self.params['client_id']) raise TokenError('invalid_client') if self.client.client_type == 'confidential': - if not (self.client.client_secret == self.params.client_secret): + if not (self.client.client_secret == self.params['client_secret']): logger.debug('[Token] Invalid client secret: client %s do not have secret %s', self.client.client_id, self.client.client_secret) raise TokenError('invalid_client') - if self.params.grant_type == 'authorization_code': - if not (self.params.redirect_uri in self.client.redirect_uris): - logger.debug('[Token] Invalid redirect uri: %s', self.params.redirect_uri) + if self.params['grant_type'] == 'authorization_code': + if not (self.params['redirect_uri'] in self.client.redirect_uris): + logger.debug('[Token] Invalid redirect uri: %s', self.params['redirect_uri']) raise TokenError('invalid_client') try: - self.code = Code.objects.get(code=self.params.code) + self.code = Code.objects.get(code=self.params['code']) except Code.DoesNotExist: - logger.debug('[Token] Code does not exist: %s', self.params.code) + logger.debug('[Token] Code does not exist: %s', self.params['code']) raise TokenError('invalid_grant') if not (self.code.client == self.client) \ or self.code.has_expired(): logger.debug('[Token] Invalid code: invalid client or code has expired', - self.params.redirect_uri) + self.params['redirect_uri']) raise TokenError('invalid_grant') # Validate PKCE parameters. - if self.params.code_verifier: + if self.params['code_verifier']: if self.code.code_challenge_method == 'S256': new_code_challenge = urlsafe_b64encode( - hashlib.sha256(self.params.code_verifier.encode('ascii')).digest() + hashlib.sha256(self.params['code_verifier'].encode('ascii')).digest() ).decode('utf-8').replace('=', '') else: - new_code_challenge = self.params.code_verifier + new_code_challenge = self.params['code_verifier'] # TODO: We should explain the error. if not (new_code_challenge == self.code.code_challenge): raise TokenError('invalid_grant') - elif self.params.grant_type == 'refresh_token': - if not self.params.refresh_token: + elif self.params['grant_type'] == 'refresh_token': + if not self.params['refresh_token']: logger.debug('[Token] Missing refresh token') raise TokenError('invalid_grant') try: - self.token = Token.objects.get(refresh_token=self.params.refresh_token, + self.token = Token.objects.get(refresh_token=self.params['refresh_token'], client=self.client) except Token.DoesNotExist: - logger.debug('[Token] Refresh token does not exist: %s', self.params.refresh_token) + logger.debug('[Token] Refresh token does not exist: %s', self.params['refresh_token']) raise TokenError('invalid_grant') else: - logger.debug('[Token] Invalid grant type: %s', self.params.grant_type) + logger.debug('[Token] Invalid grant type: %s', self.params['grant_type']) raise TokenError('unsupported_grant_type') def create_response_dic(self): - if self.params.grant_type == 'authorization_code': + if self.params['grant_type'] == 'authorization_code': return self.create_code_response_dic() - elif self.params.grant_type == 'refresh_token': + elif self.params['grant_type'] == 'refresh_token': return self.create_refresh_response_dic() def create_code_response_dic(self): @@ -153,7 +151,7 @@ class TokenEndpoint(object): nonce=self.code.nonce, at_hash=token.at_hash, request=self.request, - scope=self.params.scope, + scope=self.params['scope'], ) else: id_token_dic = {} @@ -189,7 +187,7 @@ class TokenEndpoint(object): nonce=None, at_hash=token.at_hash, request=self.request, - scope=self.params.scope, + scope=self.params['scope'], ) else: id_token_dic = {} diff --git a/oidc_provider/lib/utils/params.py b/oidc_provider/lib/utils/params.py deleted file mode 100644 index 961424a..0000000 --- a/oidc_provider/lib/utils/params.py +++ /dev/null @@ -1,7 +0,0 @@ - - -class Params(object): - """ - The purpose of this class is for accesing params via dot notation. - """ - pass \ No newline at end of file diff --git a/oidc_provider/views.py b/oidc_provider/views.py index 912c8fc..ec3fd65 100644 --- a/oidc_provider/views.py +++ b/oidc_provider/views.py @@ -46,24 +46,24 @@ class AuthorizeView(View): return hook_resp if settings.get('OIDC_SKIP_CONSENT_ALWAYS') and not (authorize.client.client_type == 'public') \ - and not (authorize.params.prompt == 'consent'): + and not (authorize.params['prompt'] == 'consent'): return redirect(authorize.create_response_uri()) if settings.get('OIDC_SKIP_CONSENT_ENABLE'): # Check if user previously give consent. if authorize.client_has_user_consent() and not (authorize.client.client_type == 'public') \ - and not (authorize.params.prompt == 'consent'): + and not (authorize.params['prompt'] == 'consent'): return redirect(authorize.create_response_uri()) - if authorize.params.prompt == 'none': - raise AuthorizeError(authorize.params.redirect_uri, 'interaction_required', authorize.grant_type) + if authorize.params['prompt'] == 'none': + raise AuthorizeError(authorize.params['redirect_uri'], 'interaction_required', authorize.grant_type) - if authorize.params.prompt == 'login': + if authorize.params['prompt'] == 'login': return redirect_to_login(request.get_full_path()) - if authorize.params.prompt == 'select_account': + if authorize.params['prompt'] == 'select_account': # TODO: see how we can support multiple accounts for the end-user. - raise AuthorizeError(authorize.params.redirect_uri, 'account_selection_required', authorize.grant_type) + raise AuthorizeError(authorize.params['redirect_uri'], 'account_selection_required', authorize.grant_type) # Generate hidden inputs for the form. context = { @@ -73,8 +73,8 @@ class AuthorizeView(View): # Remove `openid` from scope list # since we don't need to print it. - if 'openid' in authorize.params.scope: - authorize.params.scope.remove('openid') + if 'openid' in authorize.params['scope']: + authorize.params['scope'].remove('openid') context = { 'client': authorize.client, @@ -85,8 +85,8 @@ class AuthorizeView(View): return render(request, 'oidc_provider/authorize.html', context) else: - if authorize.params.prompt == 'none': - raise AuthorizeError(authorize.params.redirect_uri, 'login_required', authorize.grant_type) + if authorize.params['prompt'] == 'none': + raise AuthorizeError(authorize.params['redirect_uri'], 'login_required', authorize.grant_type) return redirect_to_login(request.get_full_path()) @@ -100,8 +100,8 @@ class AuthorizeView(View): except (AuthorizeError) as error: uri = error.create_uri( - authorize.params.redirect_uri, - authorize.params.state) + authorize.params['redirect_uri'], + authorize.params['state']) return redirect(uri) @@ -112,7 +112,7 @@ class AuthorizeView(View): authorize.validate_params() if not request.POST.get('allow'): - raise AuthorizeError(authorize.params.redirect_uri, + raise AuthorizeError(authorize.params['redirect_uri'], 'access_denied', authorize.grant_type) @@ -125,8 +125,8 @@ class AuthorizeView(View): except (AuthorizeError) as error: uri = error.create_uri( - authorize.params.redirect_uri, - authorize.params.state) + authorize.params['redirect_uri'], + authorize.params['state']) return redirect(uri) @@ -134,7 +134,6 @@ class AuthorizeView(View): class TokenView(View): def post(self, request, *args, **kwargs): - token = TokenEndpoint(request) try: