diff --git a/oidc_auth/apps.py b/oidc_auth/apps.py new file mode 100644 index 0000000..b67feb8 --- /dev/null +++ b/oidc_auth/apps.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class OidcAuthConfig(AppConfig): + name = 'oidc_auth' diff --git a/oidc_auth/auth.py b/oidc_auth/auth.py index f81865c..f7c9020 100644 --- a/oidc_auth/auth.py +++ b/oidc_auth/auth.py @@ -24,9 +24,9 @@ def authenticate(self, **kwargs): id_token = provider.verify_id_token(credentials['id_token']) oidc_user = OpenIDUser.get_or_create(id_token, - credentials['access_token'], - credentials.get('refresh_token', ''), - provider) + credentials['access_token'], + credentials.get('refresh_token', ''), + provider) return oidc_user.user except Exception as e: diff --git a/oidc_auth/migrations/0001_initial.py b/oidc_auth/migrations/0001_initial.py index f14dc8d..2812d4b 100644 --- a/oidc_auth/migrations/0001_initial.py +++ b/oidc_auth/migrations/0001_initial.py @@ -42,8 +42,11 @@ class Migration(migrations.Migration): ('sub', models.CharField(unique=True, max_length=255)), ('access_token', models.CharField(max_length=255)), ('refresh_token', models.CharField(max_length=255)), - ('issuer', models.ForeignKey(to='oidc_auth.OpenIDProvider')), - ('user', models.OneToOneField(related_name='oidc_account', to=settings.AUTH_USER_MODEL)), + ('issuer', models.ForeignKey(to='oidc_auth.OpenIDProvider', + on_delete=models.PROTECT)), + ('user', models.OneToOneField(related_name='oidc_account', + on_delete=models.PROTECT, + to=settings.AUTH_USER_MODEL)), ], ), ] diff --git a/oidc_auth/models.py b/oidc_auth/models.py index b587352..a4780f0 100644 --- a/oidc_auth/models.py +++ b/oidc_auth/models.py @@ -1,7 +1,7 @@ import string import random import json -from urlparse import urljoin +from urllib.parse import urljoin import requests from django.db import models, IntegrityError from django.conf import settings @@ -31,7 +31,7 @@ def generate(cls, redirect_url, issuer, length=oidc_settings.NONCE_LENGTH): """This method generates and returns a nonce, an unique generated string. If the maximum of retries is exceeded, it returns None. """ - CHARS = string.letters + string.digits + CHARS = string.ascii_letters + string.digits for i in range(5): _hash = ''.join(random.choice(CHARS) for n in range(length)) @@ -147,7 +147,7 @@ def verify_id_token(self, token): id_token = JWS().verify_compact(token, self.signing_keys) log.debug('Token verified, %s' % id_token) - return json.loads(id_token) + return id_token @staticmethod def _get_issuer(token): @@ -196,9 +196,15 @@ def get_default_provider(): class OpenIDUser(models.Model): sub = models.CharField(max_length=255, unique=True) - issuer = models.ForeignKey(OpenIDProvider) - user = models.OneToOneField(getattr(settings, 'AUTH_USER_MODEL', 'auth.User'), - related_name='oidc_account') + issuer = models.ForeignKey( + OpenIDProvider, + on_delete=models.PROTECT + ) + user = models.OneToOneField( + getattr(settings, 'AUTH_USER_MODEL', 'auth.User'), + related_name='oidc_account', + on_delete=models.PROTECT + ) access_token = models.CharField(max_length=255) refresh_token = models.CharField(max_length=255) diff --git a/oidc_auth/urls.py b/oidc_auth/urls.py index bd32bbb..3d0a929 100644 --- a/oidc_auth/urls.py +++ b/oidc_auth/urls.py @@ -1,6 +1,6 @@ from django.conf.urls import url -import views +from oidc_auth import views urlpatterns = [ url(r'^login/$', views.login_begin, name='oidc-login'), diff --git a/oidc_auth/views.py b/oidc_auth/views.py index 85a036e..b29fbc1 100644 --- a/oidc_auth/views.py +++ b/oidc_auth/views.py @@ -1,13 +1,14 @@ -from urllib import urlencode +from urllib.parse import urlencode from django.conf import settings from django.http import HttpResponseBadRequest -from django.contrib.auth import REDIRECT_FIELD_NAME, authenticate, login as django_login -from django.core.urlresolvers import reverse +from django.contrib.auth import REDIRECT_FIELD_NAME, login as django_login +from django.urls import reverse from django.shortcuts import render, redirect import requests from . import errors from . import utils +from .auth import OpenIDConnectBackend from .utils import log from .settings import oidc_settings from .forms import OpenIDConnectForm @@ -91,8 +92,8 @@ def login_complete(request, login_complete_view='oidc-complete', log.debug('Token exchange done, proceeding authentication') credentials = response.json() credentials['provider'] = provider - user = authenticate(credentials=credentials) - django_login(request, user) + user = OpenIDConnectBackend().authenticate(credentials=credentials) + django_login(request, user, backend='oidc_auth.auth.OpenIDConnectBackend') return redirect(nonce.redirect_url) diff --git a/requirements.txt b/requirements.txt index 2b64734..5c14c73 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ # Production requirements -Django>1.9 -pyjwkest==0.6.2 -requests==2.2.1 +Django>=3.0,<4.2 +pyjwkest==1.1.5 +requests==2.22.0 South==1.0.2 # Test requirements diff --git a/setup.py b/setup.py index c9402e7..85c50ef 100644 --- a/setup.py +++ b/setup.py @@ -4,18 +4,19 @@ setup( name='django-oidc-auth', - version='0.0.11', + version='1.0.0', description='OpenID Connect client for Django applications', long_description='WIP', - author='Lucas S. Magalhães', - author_email='lucas.sampaio@intelie.com.br', + author='Lucas S. Magalhães, Daniel Pimentel, João Paulo de Araújo, Romero Malaquias', + author_email='lucas.sampaio@intelie.com.br, danielpimentel@lccv.ufal.br, joaopna@lccv.ufal.br, ' + 'romero.malaquias@edge.ufal.br', packages=find_packages(exclude=['*.tests']), include_package_data=True, install_requires=[ - 'Django>=1.5', + 'Django>=3.0,<4.2', 'South==1.0.2', - 'pyjwkest==0.6.2', - 'requests', + 'pyjwkest==1.1.5', + 'requests==2.22.0', ], zip_safe=True )