From a58e54d55fbbef7525d2587b90065228d756d03b Mon Sep 17 00:00:00 2001 From: Niels van Huijstee Date: Thu, 1 Dec 2016 15:49:25 +0100 Subject: [PATCH 01/10] Support grant type password - basics --- oidc_provider/lib/endpoints/token.py | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/oidc_provider/lib/endpoints/token.py b/oidc_provider/lib/endpoints/token.py index 0bf52da..cf1e10c 100644 --- a/oidc_provider/lib/endpoints/token.py +++ b/oidc_provider/lib/endpoints/token.py @@ -27,12 +27,10 @@ from oidc_provider.models import ( ) from oidc_provider import settings - logger = logging.getLogger(__name__) class TokenEndpoint(object): - def __init__(self, request): self.request = request self.params = {} @@ -53,6 +51,9 @@ class TokenEndpoint(object): # PKCE parameter. self.params['code_verifier'] = self.request.POST.get('code_verifier') + self.params['username'] = self.request.POST.get('username', '') + self.params['password'] = self.request.POST.get('password', '') + def _extract_client_auth(self): """ Get client credentials using HTTP Basic Authentication method. @@ -120,6 +121,25 @@ class TokenEndpoint(object): if not (new_code_challenge == self.code.code_challenge): raise TokenError('invalid_grant') + elif self.params['grant_type'] == 'password': + from django.contrib.auth import authenticate + user = authenticate(username=self.params['username'], password=self.params['password']) + if not user: + raise TokenError('Invalid user credentials') + + self.token = create_token(user, self.client, self.params['scope'].split(' ')) + + self.token.id_token = create_id_token( + user=user, + aud=self.client.client_id, + nonce='self.code.nonce', + at_hash=self.token.at_hash, + request=self.request, + scope=self.params['scope'], + ) + + self.token.save() + elif self.params['grant_type'] == 'refresh_token': if not self.params['refresh_token']: logger.debug('[Token] Missing refresh token') @@ -142,6 +162,8 @@ class TokenEndpoint(object): return self.create_code_response_dic() elif self.params['grant_type'] == 'refresh_token': return self.create_refresh_response_dic() + elif self.params['grant_type'] == 'password': + return {'access_token': self.token.access_token} def create_code_response_dic(self): token = create_token( From 2e0072cad7e5c7de2cc7d1f5ec6be398f0f35d19 Mon Sep 17 00:00:00 2001 From: Niels van Huijstee Date: Wed, 7 Dec 2016 10:05:33 +0100 Subject: [PATCH 02/10] Add tests for Resource Owner Password Credentials Flow --- oidc_provider/tests/test_token_endpoint.py | 86 ++++++++++++++++++++-- 1 file changed, 80 insertions(+), 6 deletions(-) diff --git a/oidc_provider/tests/test_token_endpoint.py b/oidc_provider/tests/test_token_endpoint.py index de7972e..50f556e 100644 --- a/oidc_provider/tests/test_token_endpoint.py +++ b/oidc_provider/tests/test_token_endpoint.py @@ -51,6 +51,14 @@ class TokenTestCase(TestCase): self.user = create_fake_user() self.client = create_fake_client(response_type='code') + def _password_grant_post_data(self): + return { + 'username': 'johndoe', + 'password': '1234', + 'grant_type': 'password', + 'scope': 'openid email', + } + def _auth_code_post_data(self, code): """ All the data that will be POSTed to the Token Endpoint. @@ -128,6 +136,77 @@ class TokenTestCase(TestCase): return userinfo(request) + def _auth_header(self): + user_pass = self.client.client_id + ':' + self.client.client_secret + auth = b'Basic ' + b64encode(user_pass.encode('utf-8')) + auth_header = {'HTTP_AUTHORIZATION': auth.decode('utf-8')} + return auth_header + + # Resource Owner Password Credentials Grant + # requirements to satisfy in all test_password_grant methods + # https://tools.ietf.org/html/rfc6749#section-4.3.2 + # + # grant_type + # REQUIRED. Value MUST be set to "password". + # username + # REQUIRED. The resource owner username. + # password + # REQUIRED. The resource owner password. + # scope + # OPTIONAL. The scope of the access request as described by + # Section 3.3. + # + # The authorization server MUST: + # o require client authentication for confidential clients or for any + # client that was issued client credentials (or with other + # authentication requirements), + # o authenticate the client if client authentication is included, and + # o validate the resource owner password credentials using its + # existing password validation algorithm. + + def test_password_grant_get_access_token_without_scope(self): + post_data = self._password_grant_post_data() + del (post_data['scope']) + + response = self._post_request( + post_data=post_data, + extras=self._auth_header() + ) + + response_dict = json.loads(response.content.decode('utf-8')) + self.assertIn('access_token', response_dict) + + def test_password_grant_get_access_token_with_scope(self): + response = self._post_request( + post_data=self._password_grant_post_data(), + extras=self._auth_header() + ) + + response_dict = json.loads(response.content.decode('utf-8')) + self.assertIn('access_token', response_dict) + + def test_password_grant_get_access_token_invalid_user_credentials(self): + invalid_post = self._password_grant_post_data() + invalid_post['password'] = 'wrong!' + + response = self._post_request( + post_data=invalid_post, + extras=self._auth_header() + ) + + self.assertEqual(400, response.status_code) + + def test_password_grant_get_access_token_invalid_client_credentials(self): + self.client.client_id = 'foo' + self.client.client_secret = 'bar' + + response = self._post_request( + post_data=self._password_grant_post_data(), + extras=self._auth_header() + ) + + self.assertEqual(400, response.status_code) + @override_settings(OIDC_TOKEN_EXPIRE=720) def test_authorization_code(self): """ @@ -307,12 +386,7 @@ class TokenTestCase(TestCase): del basicauth_data['client_id'] del basicauth_data['client_secret'] - # Generate HTTP Basic Auth header with id and secret. - user_pass = self.client.client_id + ':' + self.client.client_secret - auth_header = b'Basic ' + b64encode(user_pass.encode('utf-8')) - response = self._post_request(basicauth_data, { - 'HTTP_AUTHORIZATION': auth_header.decode('utf-8'), - }) + response = self._post_request(basicauth_data, self._auth_header()) response.content.decode('utf-8') self.assertEqual('invalid_client' in response.content.decode('utf-8'), From 0633b664a017a00815ee06933e0bb17314bb2316 Mon Sep 17 00:00:00 2001 From: Niels van Huijstee Date: Wed, 7 Dec 2016 11:51:24 +0100 Subject: [PATCH 03/10] Password Grant -Response according to specification --- oidc_provider/lib/endpoints/token.py | 48 ++++++++++++++-------- oidc_provider/tests/test_token_endpoint.py | 25 ++++++++++- 2 files changed, 56 insertions(+), 17 deletions(-) diff --git a/oidc_provider/lib/endpoints/token.py b/oidc_provider/lib/endpoints/token.py index cf1e10c..327ed81 100644 --- a/oidc_provider/lib/endpoints/token.py +++ b/oidc_provider/lib/endpoints/token.py @@ -2,7 +2,7 @@ from base64 import b64decode, urlsafe_b64encode import hashlib import logging import re - +from django.contrib.auth import authenticate from oidc_provider.lib.utils.common import cleanup_url_from_query_string try: @@ -34,6 +34,7 @@ class TokenEndpoint(object): def __init__(self, request): self.request = request self.params = {} + self.user = None self._extract_params() def _extract_params(self): @@ -122,23 +123,15 @@ class TokenEndpoint(object): raise TokenError('invalid_grant') elif self.params['grant_type'] == 'password': - from django.contrib.auth import authenticate - user = authenticate(username=self.params['username'], password=self.params['password']) + user = authenticate( + username=self.params['username'], + password=self.params['password'] + ) + if not user: raise TokenError('Invalid user credentials') - self.token = create_token(user, self.client, self.params['scope'].split(' ')) - - self.token.id_token = create_id_token( - user=user, - aud=self.client.client_id, - nonce='self.code.nonce', - at_hash=self.token.at_hash, - request=self.request, - scope=self.params['scope'], - ) - - self.token.save() + self.user = user elif self.params['grant_type'] == 'refresh_token': if not self.params['refresh_token']: @@ -163,7 +156,30 @@ class TokenEndpoint(object): elif self.params['grant_type'] == 'refresh_token': return self.create_refresh_response_dic() elif self.params['grant_type'] == 'password': - return {'access_token': self.token.access_token} + return self.create_access_token_response_dic() + + def create_access_token_response_dic(self): + token = create_token( + self.user, + self.client, + self.params['scope'].split(' ')) + + token.id_token = create_id_token( + user=self.user, + aud=self.client.client_id, + nonce='self.code.nonce', + at_hash=token.at_hash, + request=self.request, + scope=self.params['scope'], + ) + + token.save() + return { + 'access_token': token.access_token, + 'refresh_token': token.refresh_token, + 'expires_in': settings.get('OIDC_TOKEN_EXPIRE'), + 'token_type': 'bearer' + } def create_code_response_dic(self): token = create_token( diff --git a/oidc_provider/tests/test_token_endpoint.py b/oidc_provider/tests/test_token_endpoint.py index 50f556e..1da2c07 100644 --- a/oidc_provider/tests/test_token_endpoint.py +++ b/oidc_provider/tests/test_token_endpoint.py @@ -19,7 +19,7 @@ from django.utils import timezone from jwkest.jwk import KEYS from jwkest.jws import JWS from jwkest.jwt import JWT -from mock import patch +from mock import patch, Mock from oidc_provider.lib.utils.token import create_code from oidc_provider.models import Token @@ -207,6 +207,29 @@ class TokenTestCase(TestCase): self.assertEqual(400, response.status_code) + @patch('oidc_provider.lib.utils.token.uuid') + @override_settings(OIDC_TOKEN_EXPIRE=120) + def test_password_grant_full_response(self, mock_uuid): + test_hex = 'fake_token' + mock_uuid4 = Mock(spec=uuid.uuid4) + mock_uuid4.hex = test_hex + mock_uuid.uuid4.return_value = mock_uuid4 + + response = self._post_request( + post_data=self._password_grant_post_data(), + extras=self._auth_header() + ) + + response_dict = json.loads(response.content.decode('utf-8')) + expected_response_dic = { + "access_token": 'fake_token', + "refresh_token": 'fake_token', + "expires_in": 120, + "token_type": "bearer", + } + + self.assertDictEqual(expected_response_dic, response_dict) + @override_settings(OIDC_TOKEN_EXPIRE=720) def test_authorization_code(self): """ From 39111a83884ed5b5cad4878e787e156918bb89f9 Mon Sep 17 00:00:00 2001 From: Niels van Huijstee Date: Tue, 13 Dec 2016 13:40:14 +0100 Subject: [PATCH 04/10] Better tests for errors, disable grant type password by default --- oidc_provider/lib/endpoints/token.py | 6 ++++- oidc_provider/lib/errors.py | 15 +++++++++++++ oidc_provider/settings.py | 16 +++++++++++++ oidc_provider/tests/test_token_endpoint.py | 26 +++++++++++++++++++++- oidc_provider/views.py | 4 ++-- 5 files changed, 63 insertions(+), 4 deletions(-) diff --git a/oidc_provider/lib/endpoints/token.py b/oidc_provider/lib/endpoints/token.py index 327ed81..5503b4c 100644 --- a/oidc_provider/lib/endpoints/token.py +++ b/oidc_provider/lib/endpoints/token.py @@ -14,6 +14,7 @@ from django.http import JsonResponse from oidc_provider.lib.errors import ( TokenError, + UserAuthError, ) from oidc_provider.lib.utils.token import ( create_id_token, @@ -123,13 +124,16 @@ class TokenEndpoint(object): raise TokenError('invalid_grant') elif self.params['grant_type'] == 'password': + if not settings.get('OIDC_GRANT_TYPE_PASSWORD_ENABLE'): + raise TokenError('unsupported_grant_type') + user = authenticate( username=self.params['username'], password=self.params['password'] ) if not user: - raise TokenError('Invalid user credentials') + raise UserAuthError() self.user = user diff --git a/oidc_provider/lib/errors.py b/oidc_provider/lib/errors.py index ce84811..47f4b10 100644 --- a/oidc_provider/lib/errors.py +++ b/oidc_provider/lib/errors.py @@ -16,6 +16,21 @@ class ClientIdError(Exception): description = 'The client identifier (client_id) is missing or invalid.' +class UserAuthError(Exception): + """ + Specific to the Resource Owner Password Credentials flow when + the Resource Owners credentials are not valid. + """ + error = 'access_denied' + description = 'The resource owner or authorization server denied ' \ + 'the request' + + def create_dict(self): + return { + 'error': self.error, + 'error_description': self.description, + } + class AuthorizeError(Exception): _errors = { diff --git a/oidc_provider/settings.py b/oidc_provider/settings.py index 610534c..c277d3c 100644 --- a/oidc_provider/settings.py +++ b/oidc_provider/settings.py @@ -115,6 +115,22 @@ class DefaultSettings(object): """ return 'oidc_provider.lib.utils.common.default_idtoken_processing_hook' + @property + def OIDC_GRANT_TYPE_PASSWORD_ENABLE(self): + """ + OPTIONAL. A boolean to set whether to allow the Resource Owner Password + Credentials Grant. https://tools.ietf.org/html/rfc6749#section-4.3 + + From the specification: + Since this access token request utilizes the resource owner's + password, the authorization server MUST protect the endpoint + against brute force attacks (e.g., using rate-limitation or + generating alerts). + + How you do this, is up to you. + """ + return False + default_settings = DefaultSettings() diff --git a/oidc_provider/tests/test_token_endpoint.py b/oidc_provider/tests/test_token_endpoint.py index 1da2c07..8a3ca22 100644 --- a/oidc_provider/tests/test_token_endpoint.py +++ b/oidc_provider/tests/test_token_endpoint.py @@ -164,6 +164,20 @@ class TokenTestCase(TestCase): # o validate the resource owner password credentials using its # existing password validation algorithm. + def test_default_setting_does_not_allow_grant_type_password(self): + post_data = self._password_grant_post_data() + + response = self._post_request( + post_data=post_data, + extras=self._auth_header() + ) + + response_dict = json.loads(response.content.decode('utf-8')) + + self.assertEqual(400, response.status_code) + self.assertEqual('unsupported_grant_type', response_dict['error']) + + @override_settings(OIDC_GRANT_TYPE_PASSWORD_ENABLE=True) def test_password_grant_get_access_token_without_scope(self): post_data = self._password_grant_post_data() del (post_data['scope']) @@ -176,6 +190,7 @@ class TokenTestCase(TestCase): response_dict = json.loads(response.content.decode('utf-8')) self.assertIn('access_token', response_dict) + @override_settings(OIDC_GRANT_TYPE_PASSWORD_ENABLE=True) def test_password_grant_get_access_token_with_scope(self): response = self._post_request( post_data=self._password_grant_post_data(), @@ -185,6 +200,7 @@ class TokenTestCase(TestCase): response_dict = json.loads(response.content.decode('utf-8')) self.assertIn('access_token', response_dict) + @override_settings(OIDC_GRANT_TYPE_PASSWORD_ENABLE=True) def test_password_grant_get_access_token_invalid_user_credentials(self): invalid_post = self._password_grant_post_data() invalid_post['password'] = 'wrong!' @@ -194,7 +210,11 @@ class TokenTestCase(TestCase): extras=self._auth_header() ) + response_dict = json.loads(response.content.decode('utf-8')) + print(response_dict) + self.assertEqual(400, response.status_code) + self.assertEqual('access_denied', response_dict['error']) def test_password_grant_get_access_token_invalid_client_credentials(self): self.client.client_id = 'foo' @@ -205,10 +225,14 @@ class TokenTestCase(TestCase): extras=self._auth_header() ) + response_dict = json.loads(response.content.decode('utf-8')) + self.assertEqual(400, response.status_code) + self.assertEqual('invalid_client', response_dict['error']) @patch('oidc_provider.lib.utils.token.uuid') - @override_settings(OIDC_TOKEN_EXPIRE=120) + @override_settings(OIDC_TOKEN_EXPIRE=120, + OIDC_GRANT_TYPE_PASSWORD_ENABLE=True) def test_password_grant_full_response(self, mock_uuid): test_hex = 'fake_token' mock_uuid4 = Mock(spec=uuid.uuid4) diff --git a/oidc_provider/views.py b/oidc_provider/views.py index 6bf142f..1c94d05 100644 --- a/oidc_provider/views.py +++ b/oidc_provider/views.py @@ -28,7 +28,7 @@ from oidc_provider.lib.errors import ( ClientIdError, RedirectUriError, TokenError, -) + UserAuthError) from oidc_provider.lib.utils.common import ( redirect, get_site_url, @@ -167,7 +167,7 @@ class TokenView(View): return TokenEndpoint.response(dic) - except (TokenError) as error: + except (TokenError, UserAuthError) as error: return TokenEndpoint.response(error.create_dict(), status=400) From f7908bb1b9018a710dc0613691bb479b4e26b4e6 Mon Sep 17 00:00:00 2001 From: Niels van Huijstee Date: Tue, 13 Dec 2016 14:13:57 +0100 Subject: [PATCH 05/10] Add documentation for grant type password --- docs/index.rst | 2 ++ docs/sections/settings.rst | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/docs/index.rst b/docs/index.rst index cb4816a..1a15854 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -8,6 +8,7 @@ Also implements the following specifications: * `OpenID Connect Discovery 1.0 `_ * `OpenID Connect Session Management 1.0 `_ * `OAuth 2.0 for Native Apps `_ +* `OAuth 2.0 Resource Owner Password Credentials Grant `_ * `Proof Key for Code Exchange by OAuth Public Clients `_ -------------------------------------------------------------------------------- @@ -16,6 +17,7 @@ Before getting started there are some important things that you should know: * Despite that implementation MUST support TLS. You can make request without using SSL. There is no control on that. * Supports only for requesting Claims using Scope values. +* If you enable the Resource Owner Password Credentials Grant, you MUST implement protection against brute force attacks on the token endpoint -------------------------------------------------------------------------------- diff --git a/docs/sections/settings.rst b/docs/sections/settings.rst index bba57d7..2a6c85b 100644 --- a/docs/sections/settings.rst +++ b/docs/sections/settings.rst @@ -147,3 +147,20 @@ Example usage:: .. note:: Please **DO NOT** add extra keys or delete the existing ones in the ``claims`` dict. If you want to add extra claims to some scopes you can use the ``OIDC_EXTRA_SCOPE_CLAIMS`` setting. + +OIDC_GRANT_TYPE_PASSWORD_ENABLE +=============================== +OPTIONAL. A boolean to set whether to allow the Resource Owner Password +Credentials Grant. https://tools.ietf.org/html/rfc6749#section-4.3 + +.. important:: + From the specification: + "Since this access token request utilizes the resource owner's + password, the authorization server **MUST** protect the endpoint + against brute force attacks (e.g., using rate-limitation or + generating alerts)." + + There are many ways to implement brute force attack prevention. We cannot + decide what works best for you, so you will have to implement a solution for + this that suits your needs. + From 1a31bc65548a25a59f297dc696c2ce0acc8ebbf5 Mon Sep 17 00:00:00 2001 From: Niels van Huijstee Date: Wed, 21 Dec 2016 15:58:05 +0100 Subject: [PATCH 06/10] User authentication failure to return 403 --- oidc_provider/tests/test_token_endpoint.py | 1 + oidc_provider/views.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/oidc_provider/tests/test_token_endpoint.py b/oidc_provider/tests/test_token_endpoint.py index 8a3ca22..72c1080 100644 --- a/oidc_provider/tests/test_token_endpoint.py +++ b/oidc_provider/tests/test_token_endpoint.py @@ -214,6 +214,7 @@ class TokenTestCase(TestCase): print(response_dict) self.assertEqual(400, response.status_code) + self.assertEqual(403, response.status_code) self.assertEqual('access_denied', response_dict['error']) def test_password_grant_get_access_token_invalid_client_credentials(self): diff --git a/oidc_provider/views.py b/oidc_provider/views.py index 1c94d05..b1eb420 100644 --- a/oidc_provider/views.py +++ b/oidc_provider/views.py @@ -167,8 +167,10 @@ class TokenView(View): return TokenEndpoint.response(dic) - except (TokenError, UserAuthError) as error: + except TokenError as error: return TokenEndpoint.response(error.create_dict(), status=400) + except UserAuthError as error: + return TokenEndpoint.response(error.create_dict(), status=403) @require_http_methods(['GET', 'POST']) From 7b9f08c46c5ac9ea5a686ff7348b87671e244557 Mon Sep 17 00:00:00 2001 From: Niels van Huijstee Date: Wed, 21 Dec 2016 15:58:37 +0100 Subject: [PATCH 07/10] Add id_token to response --- oidc_provider/lib/endpoints/token.py | 7 +++++-- oidc_provider/tests/test_token_endpoint.py | 16 ++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/oidc_provider/lib/endpoints/token.py b/oidc_provider/lib/endpoints/token.py index 5503b4c..cacebd9 100644 --- a/oidc_provider/lib/endpoints/token.py +++ b/oidc_provider/lib/endpoints/token.py @@ -168,7 +168,7 @@ class TokenEndpoint(object): self.client, self.params['scope'].split(' ')) - token.id_token = create_id_token( + id_token_dic = create_id_token( user=self.user, aud=self.client.client_id, nonce='self.code.nonce', @@ -177,12 +177,15 @@ class TokenEndpoint(object): scope=self.params['scope'], ) + token.id_token = id_token_dic token.save() + return { 'access_token': token.access_token, 'refresh_token': token.refresh_token, 'expires_in': settings.get('OIDC_TOKEN_EXPIRE'), - 'token_type': 'bearer' + 'token_type': 'bearer', + 'id_token': encode_id_token(id_token_dic, token.client), } def create_code_response_dic(self): diff --git a/oidc_provider/tests/test_token_endpoint.py b/oidc_provider/tests/test_token_endpoint.py index 72c1080..9c5743e 100644 --- a/oidc_provider/tests/test_token_endpoint.py +++ b/oidc_provider/tests/test_token_endpoint.py @@ -213,7 +213,6 @@ class TokenTestCase(TestCase): response_dict = json.loads(response.content.decode('utf-8')) print(response_dict) - self.assertEqual(400, response.status_code) self.assertEqual(403, response.status_code) self.assertEqual('access_denied', response_dict['error']) @@ -246,14 +245,15 @@ class TokenTestCase(TestCase): ) response_dict = json.loads(response.content.decode('utf-8')) - expected_response_dic = { - "access_token": 'fake_token', - "refresh_token": 'fake_token', - "expires_in": 120, - "token_type": "bearer", - } + id_token = JWS().verify_compact(response_dict['id_token'].encode('utf-8'), self._get_keys()) + print(id_token) - self.assertDictEqual(expected_response_dic, response_dict) + self.assertEqual(response_dict['access_token'], 'fake_token') + self.assertEqual(response_dict['refresh_token'], 'fake_token') + self.assertEqual(response_dict['expires_in'], 120) + self.assertEqual(response_dict['token_type'], 'bearer') + self.assertEqual(id_token['sub'], str(self.user.id)) + self.assertEqual(id_token['aud'], self.client.client_id); @override_settings(OIDC_TOKEN_EXPIRE=720) def test_authorization_code(self): From ed3f9988aa2b5802d2dc0b8c6b105105a08ad391 Mon Sep 17 00:00:00 2001 From: Niels van Huijstee Date: Tue, 28 Mar 2017 10:37:02 +0200 Subject: [PATCH 08/10] Explicit function naming --- oidc_provider/tests/test_token_endpoint.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/oidc_provider/tests/test_token_endpoint.py b/oidc_provider/tests/test_token_endpoint.py index 9c5743e..59b36c1 100644 --- a/oidc_provider/tests/test_token_endpoint.py +++ b/oidc_provider/tests/test_token_endpoint.py @@ -136,7 +136,7 @@ class TokenTestCase(TestCase): return userinfo(request) - def _auth_header(self): + def _password_grant_auth_header(self): user_pass = self.client.client_id + ':' + self.client.client_secret auth = b'Basic ' + b64encode(user_pass.encode('utf-8')) auth_header = {'HTTP_AUTHORIZATION': auth.decode('utf-8')} @@ -169,7 +169,7 @@ class TokenTestCase(TestCase): response = self._post_request( post_data=post_data, - extras=self._auth_header() + extras=self._password_grant_auth_header() ) response_dict = json.loads(response.content.decode('utf-8')) @@ -184,7 +184,7 @@ class TokenTestCase(TestCase): response = self._post_request( post_data=post_data, - extras=self._auth_header() + extras=self._password_grant_auth_header() ) response_dict = json.loads(response.content.decode('utf-8')) @@ -194,7 +194,7 @@ class TokenTestCase(TestCase): def test_password_grant_get_access_token_with_scope(self): response = self._post_request( post_data=self._password_grant_post_data(), - extras=self._auth_header() + extras=self._password_grant_auth_header() ) response_dict = json.loads(response.content.decode('utf-8')) @@ -207,7 +207,7 @@ class TokenTestCase(TestCase): response = self._post_request( post_data=invalid_post, - extras=self._auth_header() + extras=self._password_grant_auth_header() ) response_dict = json.loads(response.content.decode('utf-8')) @@ -222,7 +222,7 @@ class TokenTestCase(TestCase): response = self._post_request( post_data=self._password_grant_post_data(), - extras=self._auth_header() + extras=self._password_grant_auth_header() ) response_dict = json.loads(response.content.decode('utf-8')) @@ -241,7 +241,7 @@ class TokenTestCase(TestCase): response = self._post_request( post_data=self._password_grant_post_data(), - extras=self._auth_header() + extras=self._password_grant_auth_header() ) response_dict = json.loads(response.content.decode('utf-8')) @@ -434,7 +434,7 @@ class TokenTestCase(TestCase): del basicauth_data['client_id'] del basicauth_data['client_secret'] - response = self._post_request(basicauth_data, self._auth_header()) + response = self._post_request(basicauth_data, self._password_grant_auth_header()) response.content.decode('utf-8') self.assertEqual('invalid_client' in response.content.decode('utf-8'), From a6403581828dcd92ccb67264b5b017276a36fd14 Mon Sep 17 00:00:00 2001 From: Niels van Huijstee Date: Tue, 28 Mar 2017 10:37:31 +0200 Subject: [PATCH 09/10] Remove print statements --- oidc_provider/tests/test_token_endpoint.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/oidc_provider/tests/test_token_endpoint.py b/oidc_provider/tests/test_token_endpoint.py index 59b36c1..35c4e16 100644 --- a/oidc_provider/tests/test_token_endpoint.py +++ b/oidc_provider/tests/test_token_endpoint.py @@ -211,7 +211,6 @@ class TokenTestCase(TestCase): ) response_dict = json.loads(response.content.decode('utf-8')) - print(response_dict) self.assertEqual(403, response.status_code) self.assertEqual('access_denied', response_dict['error']) @@ -246,7 +245,6 @@ class TokenTestCase(TestCase): response_dict = json.loads(response.content.decode('utf-8')) id_token = JWS().verify_compact(response_dict['id_token'].encode('utf-8'), self._get_keys()) - print(id_token) self.assertEqual(response_dict['access_token'], 'fake_token') self.assertEqual(response_dict['refresh_token'], 'fake_token') From 82dee87ebee1d0a166bddc891c86230e92901f53 Mon Sep 17 00:00:00 2001 From: Niels van Huijstee Date: Tue, 28 Mar 2017 10:38:43 +0200 Subject: [PATCH 10/10] No need for semicolons, this is Python --- oidc_provider/tests/test_token_endpoint.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oidc_provider/tests/test_token_endpoint.py b/oidc_provider/tests/test_token_endpoint.py index 35c4e16..40c5aaf 100644 --- a/oidc_provider/tests/test_token_endpoint.py +++ b/oidc_provider/tests/test_token_endpoint.py @@ -251,7 +251,7 @@ class TokenTestCase(TestCase): self.assertEqual(response_dict['expires_in'], 120) self.assertEqual(response_dict['token_type'], 'bearer') self.assertEqual(id_token['sub'], str(self.user.id)) - self.assertEqual(id_token['aud'], self.client.client_id); + self.assertEqual(id_token['aud'], self.client.client_id) @override_settings(OIDC_TOKEN_EXPIRE=720) def test_authorization_code(self): @@ -276,7 +276,7 @@ class TokenTestCase(TestCase): self.assertEqual(response_dic['token_type'], 'bearer') self.assertEqual(response_dic['expires_in'], 720) self.assertEqual(id_token['sub'], str(self.user.id)) - self.assertEqual(id_token['aud'], self.client.client_id); + self.assertEqual(id_token['aud'], self.client.client_id) def test_refresh_token(self): """