Refactoring tests.
This commit is contained in:
parent
49f011b52b
commit
bc6a083571
4 changed files with 69 additions and 186 deletions
|
@ -1,15 +0,0 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXgIBAAKBgQC/O5N0BxpMVbht7i0bFIQyD0q2O4mutyYLoAQn8skYEbDUmcwp
|
||||
9dRe7GTHiDrMqJ3gW9hTZcYm7dt5rhjFqdCYK504PDOcK8LGkCN2CiWeRbCAwaz0
|
||||
Wgh3oJfbTMuYV+LWLFAAPxN4cyN6RoE9mlk7vq7YNYVpdg0VNMAKvW95dQIDAQAB
|
||||
AoGBAIBMdxw0G7e1Fxxh3E87z4lKaySiAzh91f+cps0qfTIxxEKOwMQyEv5weRjJ
|
||||
VDG0ut8on5UsReoeUM5tOF99E92pEnenI7+VfnFf04xCLcdT0XGbKimb+5g6y1Pm
|
||||
8630TD97tVO0ASHcrXOtkSTYNdAUDcqeJUTOwgW0OD3Hyb8BAkEAxODr/Mln86wu
|
||||
NhnxEVf9wuEJxX6JUjnkh62wIWYbZU61D+pIrtofi/0+AYn/9IeBCTDNIM4qTzsC
|
||||
HV/u/3nmwQJBAPiooD4FYBI1VOwZ7RZqR0ZyQN0IkBsfw95K789I1lBeXh34b6r6
|
||||
dik4A72guaAZEuxTz3MPjbSrflGjq47fE7UCQQCPsDSrpvcGYbjMZXyKkvSywXlX
|
||||
OXXRnE0NNReiGJqQArSk6/GmI634hpg1mVlER41GfuaHNdCtSLzPYY/Vx0tBAkAc
|
||||
QFxkb4voxbJuWMu9HjoW4OhJtK1ax5MjcHQqouXmn7IlyZI2ZNqD+F9Ebjxo2jBy
|
||||
NVt+gSfifRGPCP927hV5AkEAwFu9HZipddp8PM8tyF1G09+s3DVSCR3DLMBwX9NX
|
||||
nGA9tOLYOSgG/HKLOWD1qT0G8r/vYtFuktCKMSidVMp5sw==
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -42,13 +42,12 @@ def create_fake_client(response_type, is_public=False):
|
|||
"""
|
||||
client = Client()
|
||||
client.name = 'Some Client'
|
||||
client.client_id = str(random.randint(1, 999999)).zfill(6)
|
||||
if is_public:
|
||||
client.client_type = 'public'
|
||||
client.client_id = 'p123'
|
||||
client.client_secret = ''
|
||||
else:
|
||||
client.client_id = 'c123'
|
||||
client.client_secret = '456'
|
||||
client.client_secret = str(random.randint(1, 999999)).zfill(6)
|
||||
client.response_type = response_type
|
||||
client.redirect_uris = ['http://example.com/']
|
||||
|
||||
|
@ -57,17 +56,6 @@ def create_fake_client(response_type, is_public=False):
|
|||
return client
|
||||
|
||||
|
||||
def create_rsakey():
|
||||
"""
|
||||
Generate and save a sample RSA Key.
|
||||
"""
|
||||
fullpath = os.path.abspath(os.path.dirname(__file__)) + '/RSAKEY.pem'
|
||||
|
||||
with open(fullpath, 'r') as f:
|
||||
key = f.read()
|
||||
RSAKey(key=key).save()
|
||||
|
||||
|
||||
def is_code_valid(url, user, client):
|
||||
"""
|
||||
Check if the code inside the url is valid.
|
||||
|
|
|
@ -6,6 +6,7 @@ import uuid
|
|||
|
||||
from django.contrib.auth import REDIRECT_FIELD_NAME
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.core.management import call_command
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.test import RequestFactory
|
||||
from django.test import TestCase
|
||||
|
@ -22,11 +23,35 @@ class AuthorizationCodeFlowTestCase(TestCase):
|
|||
"""
|
||||
|
||||
def setUp(self):
|
||||
call_command('creatersakey')
|
||||
self.factory = RequestFactory()
|
||||
self.user = create_fake_user()
|
||||
self.client = create_fake_client(response_type='code')
|
||||
self.client_public = create_fake_client(response_type='code', is_public=True)
|
||||
self.client_implicit = create_fake_client(response_type='id_token token')
|
||||
self.state = uuid.uuid4().hex
|
||||
self.nonce = uuid.uuid4().hex
|
||||
|
||||
def _auth_request(self, method, params_or_data={}, is_user_authenticated=False):
|
||||
url = reverse('oidc_provider:authorize')
|
||||
|
||||
if method.lower() == 'get':
|
||||
query_str = urlencode(params_or_data).replace('+', '%20')
|
||||
if query_str:
|
||||
url += '?' + query_str
|
||||
request = self.factory.get(url)
|
||||
elif method.lower() == 'post':
|
||||
request = self.factory.post(url, data=params_or_data)
|
||||
else:
|
||||
raise Exception('Method unsupported for an Authorization Request.')
|
||||
|
||||
# Simulate that the user is logged.
|
||||
request.user = self.user if is_user_authenticated else AnonymousUser()
|
||||
|
||||
response = AuthorizeView.as_view()(request)
|
||||
|
||||
return response
|
||||
|
||||
|
||||
def test_missing_parameters(self):
|
||||
"""
|
||||
|
@ -36,11 +61,7 @@ class AuthorizationCodeFlowTestCase(TestCase):
|
|||
|
||||
See: https://tools.ietf.org/html/rfc6749#section-4.1.2.1
|
||||
"""
|
||||
url = reverse('oidc_provider:authorize')
|
||||
|
||||
request = self.factory.get(url)
|
||||
|
||||
response = AuthorizeView.as_view()(request)
|
||||
response = self._auth_request('get')
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(bool(response.content), True)
|
||||
|
@ -53,19 +74,15 @@ class AuthorizationCodeFlowTestCase(TestCase):
|
|||
See: http://openid.net/specs/openid-connect-core-1_0.html#AuthError
|
||||
"""
|
||||
# Create an authorize request with an unsupported response_type.
|
||||
query_str = urlencode({
|
||||
params = {
|
||||
'client_id': self.client.client_id,
|
||||
'response_type': 'something_wrong',
|
||||
'redirect_uri': self.client.default_redirect_uri,
|
||||
'scope': 'openid email',
|
||||
'state': self.state,
|
||||
}).replace('+', '%20')
|
||||
}
|
||||
|
||||
url = reverse('oidc_provider:authorize') + '?' + query_str
|
||||
|
||||
request = self.factory.get(url)
|
||||
|
||||
response = AuthorizeView.as_view()(request)
|
||||
response = self._auth_request('get', params)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(response.has_header('Location'), True)
|
||||
|
@ -81,34 +98,20 @@ class AuthorizationCodeFlowTestCase(TestCase):
|
|||
|
||||
See: http://openid.net/specs/openid-connect-core-1_0.html#Authenticates
|
||||
"""
|
||||
query_str = urlencode({
|
||||
params = {
|
||||
'client_id': self.client.client_id,
|
||||
'response_type': 'code',
|
||||
'redirect_uri': self.client.default_redirect_uri,
|
||||
'scope': 'openid email',
|
||||
'state': self.state,
|
||||
}).replace('+', '%20')
|
||||
}
|
||||
|
||||
url = reverse('oidc_provider:authorize') + '?' + query_str
|
||||
|
||||
request = self.factory.get(url)
|
||||
request.user = AnonymousUser()
|
||||
|
||||
response = AuthorizeView.as_view()(request)
|
||||
response = self._auth_request('get', params)
|
||||
|
||||
# Check if user was redirected to the login view.
|
||||
login_url_exists = settings.get('LOGIN_URL') in response['Location']
|
||||
self.assertEqual(login_url_exists, True)
|
||||
|
||||
# Check if the login will redirect to a valid url.
|
||||
try:
|
||||
next_value = response['Location'].split(REDIRECT_FIELD_NAME + '=')[1]
|
||||
next_url = unquote(next_value)
|
||||
is_next_ok = next_url == url
|
||||
except:
|
||||
is_next_ok = False
|
||||
self.assertEqual(is_next_ok, True)
|
||||
|
||||
def test_user_consent_inputs(self):
|
||||
"""
|
||||
Once the End-User is authenticated, the Authorization Server MUST
|
||||
|
@ -117,7 +120,7 @@ class AuthorizationCodeFlowTestCase(TestCase):
|
|||
|
||||
See: http://openid.net/specs/openid-connect-core-1_0.html#Consent
|
||||
"""
|
||||
query_str = urlencode({
|
||||
params = {
|
||||
'client_id': self.client.client_id,
|
||||
'response_type': 'code',
|
||||
'redirect_uri': self.client.default_redirect_uri,
|
||||
|
@ -126,15 +129,9 @@ class AuthorizationCodeFlowTestCase(TestCase):
|
|||
# PKCE parameters.
|
||||
'code_challenge': FAKE_CODE_CHALLENGE,
|
||||
'code_challenge_method': 'S256',
|
||||
}).replace('+', '%20')
|
||||
}
|
||||
|
||||
url = reverse('oidc_provider:authorize') + '?' + query_str
|
||||
|
||||
request = self.factory.get(url)
|
||||
# Simulate that the user is logged.
|
||||
request.user = self.user
|
||||
|
||||
response = AuthorizeView.as_view()(request)
|
||||
response = self._auth_request('get', params, is_user_authenticated=True)
|
||||
|
||||
# Check if hidden inputs exists in the form,
|
||||
# also if their values are valid.
|
||||
|
@ -165,14 +162,10 @@ class AuthorizationCodeFlowTestCase(TestCase):
|
|||
the parameters defined in Section 4.1.2 of OAuth 2.0 [RFC6749]
|
||||
by adding them as query parameters to the redirect_uri.
|
||||
"""
|
||||
response_type = 'code'
|
||||
|
||||
url = reverse('oidc_provider:authorize')
|
||||
|
||||
post_data = {
|
||||
data = {
|
||||
'client_id': self.client.client_id,
|
||||
'redirect_uri': self.client.default_redirect_uri,
|
||||
'response_type': response_type,
|
||||
'response_type': 'code',
|
||||
'scope': 'openid email',
|
||||
'state': self.state,
|
||||
# PKCE parameters.
|
||||
|
@ -180,11 +173,7 @@ class AuthorizationCodeFlowTestCase(TestCase):
|
|||
'code_challenge_method': 'S256',
|
||||
}
|
||||
|
||||
request = self.factory.post(url, data=post_data)
|
||||
# Simulate that the user is logged.
|
||||
request.user = self.user
|
||||
|
||||
response = AuthorizeView.as_view()(request)
|
||||
response = self._auth_request('post', data, is_user_authenticated=True)
|
||||
|
||||
# Because user doesn't allow app, SHOULD exists an error parameter
|
||||
# in the query.
|
||||
|
@ -194,13 +183,9 @@ class AuthorizationCodeFlowTestCase(TestCase):
|
|||
msg='"access_denied" code is missing in query.')
|
||||
|
||||
# Simulate user authorization.
|
||||
post_data['allow'] = 'Accept' # Should be the value of the button.
|
||||
data['allow'] = 'Accept' # Will be the value of the button.
|
||||
|
||||
request = self.factory.post(url, data=post_data)
|
||||
# Simulate that the user is logged.
|
||||
request.user = self.user
|
||||
|
||||
response = AuthorizeView.as_view()(request)
|
||||
response = self._auth_request('post', data, is_user_authenticated=True)
|
||||
|
||||
is_code_ok = is_code_valid(url=response['Location'],
|
||||
user=self.user,
|
||||
|
@ -219,7 +204,7 @@ class AuthorizationCodeFlowTestCase(TestCase):
|
|||
list of scopes) and because they might be prompted for the same
|
||||
authorization multiple times, the server skip it.
|
||||
"""
|
||||
post_data = {
|
||||
data = {
|
||||
'client_id': self.client.client_id,
|
||||
'redirect_uri': self.client.default_redirect_uri,
|
||||
'response_type': 'code',
|
||||
|
@ -229,34 +214,25 @@ class AuthorizationCodeFlowTestCase(TestCase):
|
|||
}
|
||||
|
||||
request = self.factory.post(reverse('oidc_provider:authorize'),
|
||||
data=post_data)
|
||||
data=data)
|
||||
# Simulate that the user is logged.
|
||||
request.user = self.user
|
||||
|
||||
with self.settings(OIDC_SKIP_CONSENT_ALWAYS=True):
|
||||
response = AuthorizeView.as_view()(request)
|
||||
response = self._auth_request('post', data, is_user_authenticated=True)
|
||||
|
||||
self.assertEqual('code' in response['Location'], True,
|
||||
msg='Code is missing in the returned url.')
|
||||
|
||||
response = AuthorizeView.as_view()(request)
|
||||
response = self._auth_request('post', data, is_user_authenticated=True)
|
||||
|
||||
is_code_ok = is_code_valid(url=response['Location'],
|
||||
user=self.user,
|
||||
client=self.client)
|
||||
self.assertEqual(is_code_ok, True, msg='Code returned is invalid.')
|
||||
|
||||
del post_data['allow']
|
||||
query_str = urlencode(post_data).replace('+', '%20')
|
||||
|
||||
url = reverse('oidc_provider:authorize') + '?' + query_str
|
||||
|
||||
request = self.factory.get(url)
|
||||
# Simulate that the user is logged.
|
||||
request.user = self.user
|
||||
|
||||
# Ensure user consent skip is enabled.
|
||||
response = AuthorizeView.as_view()(request)
|
||||
del data['allow']
|
||||
response = self._auth_request('get', data, is_user_authenticated=True)
|
||||
|
||||
is_code_ok = is_code_valid(url=response['Location'],
|
||||
user=self.user,
|
||||
|
@ -264,10 +240,7 @@ class AuthorizationCodeFlowTestCase(TestCase):
|
|||
self.assertEqual(is_code_ok, True, msg='Code returned is invalid or missing.')
|
||||
|
||||
def test_response_uri_is_properly_constructed(self):
|
||||
"""
|
||||
TODO
|
||||
"""
|
||||
post_data = {
|
||||
data = {
|
||||
'client_id': self.client.client_id,
|
||||
'redirect_uri': self.client.default_redirect_uri + "?redirect_state=xyz",
|
||||
'response_type': 'code',
|
||||
|
@ -276,123 +249,59 @@ class AuthorizationCodeFlowTestCase(TestCase):
|
|||
'allow': 'Accept',
|
||||
}
|
||||
|
||||
request = self.factory.post(reverse('oidc_provider:authorize'),
|
||||
data=post_data)
|
||||
# Simulate that the user is logged.
|
||||
request.user = self.user
|
||||
response = self._auth_request('post', data, is_user_authenticated=True)
|
||||
|
||||
response = AuthorizeView.as_view()(request)
|
||||
|
||||
is_code_ok = is_code_valid(url=response['Location'],
|
||||
user=self.user,
|
||||
client=self.client)
|
||||
self.assertEqual(is_code_ok, True,
|
||||
msg='Code returned is invalid.')
|
||||
|
||||
def test_scope_with_plus(self):
|
||||
"""
|
||||
In query string, scope use `+` instead of the space url-encoded.
|
||||
"""
|
||||
scope_test = 'openid email profile'
|
||||
|
||||
query_str = urlencode({
|
||||
'client_id': self.client.client_id,
|
||||
'response_type': 'code',
|
||||
'redirect_uri': self.client.default_redirect_uri,
|
||||
'scope': scope_test,
|
||||
'state': self.state,
|
||||
})
|
||||
|
||||
url = reverse('oidc_provider:authorize') + '?' + query_str
|
||||
|
||||
request = self.factory.get(url)
|
||||
# Simulate that the user is logged.
|
||||
request.user = self.user
|
||||
|
||||
response = AuthorizeView.as_view()(request)
|
||||
|
||||
# Search the scopes in the html.
|
||||
self.assertEqual(scope_test in response.content.decode('utf-8'), True)
|
||||
# TODO
|
||||
|
||||
def test_public_client_auto_approval(self):
|
||||
"""
|
||||
It's recommended not auto-approving requests for non-confidential clients.
|
||||
"""
|
||||
query_str = urlencode({
|
||||
params = {
|
||||
'client_id': self.client_public.client_id,
|
||||
'response_type': 'code',
|
||||
'redirect_uri': self.client_public.default_redirect_uri,
|
||||
'scope': 'openid email',
|
||||
'state': self.state,
|
||||
})
|
||||
|
||||
url = reverse('oidc_provider:authorize') + '?' + query_str
|
||||
|
||||
request = self.factory.get(url)
|
||||
# Simulate that the user is logged.
|
||||
request.user = self.user
|
||||
}
|
||||
|
||||
with self.settings(OIDC_SKIP_CONSENT_ALWAYS=True):
|
||||
response = AuthorizeView.as_view()(request)
|
||||
response = self._auth_request('get', params, is_user_authenticated=True)
|
||||
|
||||
self.assertEqual('Request for Permission' in response.content.decode('utf-8'), True)
|
||||
|
||||
class ImplicitFlowTestCase(TestCase):
|
||||
"""
|
||||
Test cases for Authorize Endpoint using Implicit Grant Flow.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.factory = RequestFactory()
|
||||
self.user = create_fake_user()
|
||||
self.client = create_fake_client(response_type='id_token token')
|
||||
self.state = uuid.uuid4().hex
|
||||
self.nonce = uuid.uuid4().hex
|
||||
create_rsakey()
|
||||
|
||||
def test_missing_nonce(self):
|
||||
def test_implicit_missing_nonce(self):
|
||||
"""
|
||||
The `nonce` parameter is REQUIRED if you use the Implicit Flow.
|
||||
"""
|
||||
query_str = urlencode({
|
||||
'client_id': self.client.client_id,
|
||||
'response_type': self.client.response_type,
|
||||
'redirect_uri': self.client.default_redirect_uri,
|
||||
params = {
|
||||
'client_id': self.client_implicit.client_id,
|
||||
'response_type': self.client_implicit.response_type,
|
||||
'redirect_uri': self.client_implicit.default_redirect_uri,
|
||||
'scope': 'openid email',
|
||||
'state': self.state,
|
||||
}).replace('+', '%20')
|
||||
}
|
||||
|
||||
url = reverse('oidc_provider:authorize') + '?' + query_str
|
||||
|
||||
request = self.factory.get(url)
|
||||
# Simulate that the user is logged.
|
||||
request.user = self.user
|
||||
|
||||
response = AuthorizeView.as_view()(request)
|
||||
response = self._auth_request('get', params, is_user_authenticated=True)
|
||||
|
||||
self.assertEqual('#error=invalid_request' in response['Location'], True)
|
||||
|
||||
def test_access_token_response(self):
|
||||
def test_implicit_access_token_response(self):
|
||||
"""
|
||||
Unlike the Authorization Code flow, in which the client makes
|
||||
separate requests for authorization and for an access token, the client
|
||||
receives the access token as the result of the authorization request.
|
||||
"""
|
||||
post_data = {
|
||||
'client_id': self.client.client_id,
|
||||
'redirect_uri': self.client.default_redirect_uri,
|
||||
'response_type': self.client.response_type,
|
||||
data = {
|
||||
'client_id': self.client_implicit.client_id,
|
||||
'redirect_uri': self.client_implicit.default_redirect_uri,
|
||||
'response_type': self.client_implicit.response_type,
|
||||
'scope': 'openid email',
|
||||
'state': self.state,
|
||||
'nonce': self.nonce,
|
||||
'allow': 'Accept',
|
||||
}
|
||||
|
||||
request = self.factory.post(reverse('oidc_provider:authorize'),
|
||||
data=post_data)
|
||||
# Simulate that the user is logged.
|
||||
request.user = self.user
|
||||
|
||||
response = AuthorizeView.as_view()(request)
|
||||
response = self._auth_request('post', data, is_user_authenticated=True)
|
||||
|
||||
self.assertEqual('access_token' in response['Location'], True)
|
||||
|
|
|
@ -4,6 +4,7 @@ try:
|
|||
except ImportError:
|
||||
from urllib import urlencode
|
||||
|
||||
from django.core.management import call_command
|
||||
from django.test import RequestFactory, override_settings
|
||||
from django.test import TestCase
|
||||
from jwkest.jwk import KEYS
|
||||
|
@ -23,10 +24,10 @@ class TokenTestCase(TestCase):
|
|||
"""
|
||||
|
||||
def setUp(self):
|
||||
call_command('creatersakey')
|
||||
self.factory = RequestFactory()
|
||||
self.user = create_fake_user()
|
||||
self.client = create_fake_client(response_type='code')
|
||||
create_rsakey()
|
||||
|
||||
def _auth_code_post_data(self, code):
|
||||
"""
|
||||
|
|
Loading…
Reference in a new issue