Commit a2fed3ac authored by Lukas Burgey's avatar Lukas Burgey

Rework and move the authentication

parent 9e3ae5c2
......@@ -4,3 +4,4 @@ env
db.cnf
static
deployment
deploy
#!/bin/zsh
rsync -ra --exclude=__pycache__ ~/ba/src/backend/django_backend hdf-portal.data.kit.edu:/home/hdf/backend/
ssh hdf-portal.data.kit.edu systemctl restart uwsgi
from django.contrib import admin
from . import models
from .auth.models import OIDCConfig
from .auth.v1.models import OIDCConfig
admin.site.register(models.User)
......
from django.db import models as db_models
from oic.oic import Client
from oic.utils.authn.client import CLIENT_AUTHN_METHOD
from oic.oic.message import RegistrationResponse
from urllib.request import Request, urlopen
from .. import models
from ... import models
from django.core.exceptions import ObjectDoesNotExist
from django.conf import settings
import json
oidc_client = None
oidc_client = {}
class OIDCConfig(db_models.Model):
......@@ -17,6 +16,8 @@ class OIDCConfig(db_models.Model):
client_secret = db_models.CharField(max_length=200)
redirect_uri = db_models.CharField(max_length=200)
issuer_uri = db_models.CharField(max_length=200)
enabled = db_models.BooleanField(default=False)
name = db_models.CharField(max_length=200)
@property
def registration_response(self):
......@@ -27,16 +28,21 @@ class OIDCConfig(db_models.Model):
@property
def oidc_client(self):
global oidc_client
if oidc_client is None:
oidc_client = Client(client_authn_method=CLIENT_AUTHN_METHOD)
oidc_client.provider_config(self.issuer_uri)
oidc_client.store_registration_info(self.registration_response)
return oidc_client
if self.id not in oidc_client:
new_oidc_client = Client(client_authn_method=CLIENT_AUTHN_METHOD)
new_oidc_client.provider_config(self.issuer_uri)
new_oidc_client.store_registration_info(self.registration_response)
oidc_client[self.id] = new_oidc_client
return oidc_client[self.id]
@property
def provider_info(self):
return self.oidc_client.provider_info
@property
def name(self):
return self.issuer_uri
def get_auth_request(self, client, state):
args = {
'client_id': self.client_id,
......@@ -51,7 +57,7 @@ class OIDCConfig(db_models.Model):
return auth_req.request(client.authorization_endpoint)
def __str__(self):
return self.issuer_uri
return self.name
def get_oidc_client():
......
from rest_framework import serializers
from .views import OIDCConfig
class OIDCConfigSerializer(serializers.ModelSerializer):
class Meta:
model = OIDCConfig
fields = ['name', 'id']
class AuthInfoSerializer(serializers.Serializer):
idps = OIDCConfigSerializer(many=True)
default = serializers.IntegerField()
from django.conf.urls import url
from . import views
from ...frontend import views as frontend_views
urlpatterns = [
url(r'^info/', views.AuthInfo.as_view()),
url(r'^request/', views.Auth.as_view()),
url(r'^callback/', views.AuthCallback.as_view()),
url(r'^logout/', frontend_views.LogoutView.as_view()),
]
from .models import OIDCConfig
from django.contrib.auth import authenticate, login
from django.db.utils import OperationalError
from django.shortcuts import redirect, render
from django.views import View
from oic import rndstr
from oic.oic.message import AuthorizationResponse
from rest_framework.permissions import AllowAny
from rest_framework import generics
import json
from .models import OIDCConfig
from .serializers import AuthInfoSerializer
def oidc_config_for_request(request):
idp_id = request.GET.get('idp', None)
if idp_id is not None:
try:
return OIDCConfig.objects.get(id=idp_id)
except Exception:
print('No OIDCConfig with id {}'.format(idp_id))
raise
else:
return OIDCConfig.objects.first()
class AuthInfo(generics.RetrieveAPIView):
permission_classes = (AllowAny,)
serializer_class = AuthInfoSerializer
def get_object(self):
idps = OIDCConfig.objects.filter(enabled=True)
return {
'idps': idps,
'default': idps.first().id,
}
class Auth(View):
......@@ -15,15 +43,17 @@ class Auth(View):
request.session['state'] = state
# request.session['nonce'] = rndstr()
except OperationalError:
return redirect('/?error=not_operational')
return redirect('/')
oidc_config = OIDCConfig.objects.all()[0]
oidc_client = oidc_config.oidc_client
oidc_config = oidc_config_for_request(request)
login_url = oidc_config.get_auth_request(
oidc_client,
state)
return redirect(login_url)
try:
return redirect(oidc_config.get_auth_request(
oidc_config.oidc_client,
state))
except Exception:
print('Malformed oidc config: {}'.format(oidc_config))
return redirect('/')
class AuthCallback(View):
......@@ -32,7 +62,7 @@ class AuthCallback(View):
try:
state = request.session['state']
except OperationalError:
return redirect('/?error=not_operational')
return redirect('/')
oidc_config = OIDCConfig.objects.all()[0]
oidc_client = oidc_config.oidc_client
......@@ -71,7 +101,7 @@ class AuthCallback(View):
else:
# redirect back to the frontend
login(request, user)
response = redirect('https://hdf-portal.data.kit.edu/')
response = redirect('/')
response.set_cookie('sessionid', request.COOKIES['sessionid'])
return response
......@@ -2,15 +2,13 @@ from django.conf.urls import include, url
from django.contrib import admin
from .clientapi import urls as clientapi_urls
from .frontend import urls as frontend_urls, views as frontend_views
from .auth import views as auth_views
from .frontend import urls as frontend_urls
from .auth.v1 import urls as auth_urls
urlpatterns = [
url(r'^clientapi/', include(clientapi_urls.urlpatterns)),
url(r'^api/', include(frontend_urls.urlpatterns)),
url(r'^auth/', auth_views.Auth.as_view()),
url(r'^auth_callback/', auth_views.AuthCallback.as_view()),
url(r'^auth_logout', frontend_views.LogoutView.as_view()),
url(r'^auth/v1/', include(auth_urls.urlpatterns)),
url(r'^admin', admin.site.urls),
]
......@@ -103,7 +103,7 @@ DATABASES = {
CORS_ORIGIN_ALLOW_ALL = True
AUTHENTICATION_BACKENDS = [
'django_backend.backend.auth.models.OIDCTokenAuthBackend',
'django_backend.backend.auth.v1.models.OIDCTokenAuthBackend',
'django.contrib.auth.backends.ModelBackend',
]
......@@ -148,7 +148,7 @@ STATIC_ROOT = 'static'
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'django_backend.backend.auth.auth_class.CsrfExemptSessionAuthentication',
'django_backend.backend.auth.v1.auth_class.CsrfExemptSessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment