Skip to content

Commit

Permalink
Merge pull request #185 from jezdez/josepy
Browse files Browse the repository at this point in the history
Switch to using josepy. Fix #180.
  • Loading branch information
johngian committed Oct 24, 2017
2 parents ed7148b + f3e9277 commit af9603b
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 23 deletions.
26 changes: 23 additions & 3 deletions mozilla_django_oidc/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
from django.core.exceptions import SuspiciousOperation, ImproperlyConfigured
from django.core.urlresolvers import reverse

from jose import jws
from josepy.jwk import JWK
from josepy.jws import JWS

from mozilla_django_oidc.utils import absolutify, import_from_settings

Expand Down Expand Up @@ -78,6 +79,26 @@ def create_user(self, claims):

return self.UserModel.objects.create_user(username, email)

def _verify_jws(self, payload, key):
"""Verify the given JWS payload with the given key and return the payload"""

jws = JWS.from_compact(payload)
jwk = JWK.load(key)
if not jws.verify(jwk):
msg = 'JWS token verification failed.'
raise SuspiciousOperation(msg)

try:
alg = jws.signature.combined.alg.name
if alg != self.OIDC_RP_SIGN_ALGO:
msg = 'The specified alg value is not allowed'
raise SuspiciousOperation(msg)
except KeyError:
msg = 'No alg value found in header'
raise SuspiciousOperation(msg)

return jws.payload

def verify_token(self, token, **kwargs):
"""Validate the token signature."""
nonce = kwargs.get('nonce')
Expand All @@ -88,10 +109,9 @@ def verify_token(self, token, **kwargs):
key = self.OIDC_RP_CLIENT_SECRET

# Verify the token
verified_token = jws.verify(
verified_token = self._verify_jws(
token,
key,
algorithms=[self.OIDC_RP_SIGN_ALGO]
)
# The 'verified_token' will always be a byte string since it's
# the result of base64.urlsafe_b64decode().
Expand Down
22 changes: 14 additions & 8 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@
readme = open('README.rst').read()
history = open('HISTORY.rst').read().replace('.. :changelog:', '')

install_requirements = [
'Django>1.7',
'josepy',
'requests'
]
# cryptography dropped supporting Python 3.2/3.3 at some point
if sys.version_info[:2] > (2, 7) and sys.version_info[:2] < (3, 4):
install_requirements.append('cryptography<1.9')
else:
install_requirements.append('cryptography>1.9')


setup(
name='mozilla-django-oidc',
version=VERSION,
Expand All @@ -40,15 +52,9 @@
author='Tasos Katsoulas, John Giannelos',
author_email='akatsoulas@mozilla.com, jgiannelos@mozilla.com',
url='https://github.com/mozilla/mozilla-django-oidc',
packages=[
'mozilla_django_oidc',
],
packages=['mozilla_django_oidc'],
include_package_data=True,
install_requires=[
'Django>1.7',
'python-jose',
'requests'
],
install_requires=install_requirements,
license='MPL 2.0',
zip_safe=False,
keywords='mozilla-django-oidc',
Expand Down
24 changes: 12 additions & 12 deletions tests/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ def test_authenticate_no_code_no_state(self):
self.backend.authenticate(request=request)

@override_settings(OIDC_USE_NONCE=False)
@patch('mozilla_django_oidc.auth.jws.verify')
@patch('mozilla_django_oidc.auth.OIDCAuthenticationBackend._verify_jws')
@patch('mozilla_django_oidc.auth.requests')
def test_jwt_decode_params(self, request_mock, jws_mock):
"""Test jwt verification signature."""
Expand All @@ -255,13 +255,13 @@ def test_jwt_decode_params(self, request_mock, jws_mock):
request_mock.post.return_value = post_json_mock
self.backend.authenticate(request=auth_request)
calls = [
call('token', 'client_secret', algorithms=['HS256'])
call('token', 'client_secret')
]
jws_mock.assert_has_calls(calls)

@override_settings(OIDC_VERIFY_JWT=False)
@override_settings(OIDC_USE_NONCE=False)
@patch('mozilla_django_oidc.auth.jws.verify')
@patch('mozilla_django_oidc.auth.OIDCAuthenticationBackend._verify_jws')
@patch('mozilla_django_oidc.auth.requests')
def test_jwt_decode_params_verify_false(self, request_mock, jws_mock):
"""Test jwt verification signature with verify False"""
Expand All @@ -285,18 +285,18 @@ def test_jwt_decode_params_verify_false(self, request_mock, jws_mock):
}
request_mock.post.return_value = post_json_mock
calls = [
call('token', 'client_secret', algorithms=['HS256'])
call('token', 'client_secret')
]

self.backend.authenticate(request=auth_request)
jws_mock.assert_has_calls(calls)

@override_settings(OIDC_USE_NONCE=True)
@patch('mozilla_django_oidc.auth.jws')
def test_jwt_failed_nonce(self, jwt_mock):
@patch('mozilla_django_oidc.auth.OIDCAuthenticationBackend._verify_jws')
def test_jwt_failed_nonce(self, jws_mock):
"""Test Nonce verification."""

jwt_mock.verify.return_value = json.dumps({
jws_mock.return_value = json.dumps({
'nonce': 'foobar',
'aud': 'aud'
}).encode('utf-8')
Expand All @@ -306,7 +306,7 @@ def test_jwt_failed_nonce(self, jwt_mock):

@override_settings(OIDC_CREATE_USER=False)
@override_settings(OIDC_USE_NONCE=False)
@patch('mozilla_django_oidc.auth.jws.verify')
@patch('mozilla_django_oidc.auth.OIDCAuthenticationBackend._verify_jws')
@patch('mozilla_django_oidc.auth.requests')
def test_create_user_disabled(self, request_mock, jws_mock):
"""Test with user creation disabled and no user found."""
Expand All @@ -331,7 +331,7 @@ def test_create_user_disabled(self, request_mock, jws_mock):
request_mock.post.return_value = post_json_mock
self.assertEqual(self.backend.authenticate(request=auth_request), None)

@patch('mozilla_django_oidc.auth.jws.verify')
@patch('mozilla_django_oidc.auth.OIDCAuthenticationBackend._verify_jws')
@patch('mozilla_django_oidc.auth.requests')
@override_settings(OIDC_USE_NONCE=False)
def test_create_user_enabled(self, request_mock, jws_mock):
Expand Down Expand Up @@ -361,7 +361,7 @@ def test_create_user_enabled(self, request_mock, jws_mock):

@patch.object(settings, 'OIDC_USERNAME_ALGO')
@override_settings(OIDC_USE_NONCE=False)
@patch('mozilla_django_oidc.auth.jws.verify')
@patch('mozilla_django_oidc.auth.OIDCAuthenticationBackend._verify_jws')
@patch('mozilla_django_oidc.auth.requests')
def test_custom_username_algo(self, request_mock, jws_mock, algo_mock):
"""Test user creation with custom username algorithm."""
Expand Down Expand Up @@ -390,7 +390,7 @@ def test_custom_username_algo(self, request_mock, jws_mock, algo_mock):
User.objects.get(username='username_algo'))

@override_settings(OIDC_USE_NONCE=False)
@patch('mozilla_django_oidc.auth.jws.verify')
@patch('mozilla_django_oidc.auth.OIDCAuthenticationBackend._verify_jws')
@patch('mozilla_django_oidc.auth.requests')
def test_duplicate_emails_exact(self, request_mock, jws_mock):
"""Test auth with two users having the same email."""
Expand Down Expand Up @@ -418,7 +418,7 @@ def test_duplicate_emails_exact(self, request_mock, jws_mock):
self.assertEqual(self.backend.authenticate(request=auth_request), None)

@override_settings(OIDC_USE_NONCE=False)
@patch('mozilla_django_oidc.auth.jws.verify')
@patch('mozilla_django_oidc.auth.OIDCAuthenticationBackend._verify_jws')
@patch('mozilla_django_oidc.auth.requests')
def test_duplicate_emails_case_mismatch(self, request_mock, jws_mock):
"""Test auth with two users having the same email, with different case."""
Expand Down

0 comments on commit af9603b

Please sign in to comment.