Commit effd19d7 authored by Lukas Burgey's avatar Lukas Burgey

Add direct auth redirect using query parameters

This resolves #2
parent e9dddd00
......@@ -5,7 +5,7 @@ map $http_upgrade $connection_upgrade {
upstream django {
server unix://home/feudal/backend/feudal.sock;
server unix://home/feudal/feudalBackend/feudal.sock;
upstream websocket {
......@@ -23,37 +23,37 @@ server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
charset utf-8;
client_max_body_size 75M;
ssl on;
ssl_certificate /etc/ssl/;
ssl_trusted_certificate /etc/ssl/;
ssl_certificate_key /etc/ssl/;
ssl_certificate /etc/ssl/;
ssl_trusted_certificate /etc/ssl/;
ssl_certificate_key /etc/ssl/;
ssl_dhparam /etc/nginx/cert/dhparam.pem;
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 180m;
ssl_prefer_server_ciphers on;
#ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_protocols TLSv1.1 TLSv1.2;
ssl_dhparam /etc/nginx/cert/dhparam.pem;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
root /home/feudal/webpage/dist;
root /home/feudal/feudalWebpage/dist;
index index.html;
location /backend/static {
alias /home/feudal/backend/static;
alias /home/feudal/feudalBackend/static;
location /backend {
uwsgi_pass django;
include /home/feudal/backend/example-config/uwsgi_params;
include /home/feudal/config/uwsgi_params;
location /frontend {
......@@ -68,6 +68,9 @@ server {
location / {
if ($arg_idp) {
return 301 /backend/auth/v1/request$is_args$args;
rewrite "^$" /frontend;
import json
import logging
import urllib
from django.contrib.auth import authenticate, login, logout
from django.core.exceptions import ImproperlyConfigured
from django.shortcuts import redirect
from django.views import View
from oic import rndstr
......@@ -21,39 +23,63 @@ LOGGER = logging.getLogger(__name__)
IDP_COOKIE_NAME = 'idp_id'
def idp_id_from_request(request):
class AuthException(Exception):
def select_oidc_config(request):
issuer_uri_urlenc = request.GET.get('idp', None)
idp_id = request.COOKIES.get(IDP_COOKIE_NAME, None)
if idp_id is not None:
return idp_id'idp_id cookie was not set on request %s', request)
return default_idp().id
# IdP selection using the 'idp' url parameter
if issuer_uri_urlenc is not None:
issuer_uri = urllib.parse.unquote(issuer_uri_urlenc)
return OIDCConfig.objects.get(issuer_uri=issuer_uri)
class AuthException(Exception):
# IdP selection using a cookie
elif idp_id is not None:
return OIDCConfig.objects.get(id=idp_id)
return default_idp()
except OIDCConfig.DoesNotExist:
LOGGER.error("Failed to select IdP. Serving default IdP")
return default_idp()
class Auth(View):
def get(self, request):
state = rndstr()
idp_id = idp_id_from_request(request)
oidc_config = OIDCConfig.objects.get(id=idp_id)
utils.set_session(request, 'state', state)
utils.set_session(request, 'idp_id', idp_id)
# select an idp according to query parameters / cookies
oidc_config = select_oidc_config(request)
# store the idp used for the authentication in the users session
utils.set_session(request, 'idp_id',
# construct the auth redirect
auth_redirect = oidc_config.get_auth_request(
LOGGER.debug('Auth: redirecting %s to IdP %s', state, oidc_config)
# include query parameters in the redirect to the idp
if request.GET.items().length > 1:
urlparams = request.GET.copy()
if 'idp' in urlparams:
del urlparams['idp']
return redirect(auth_redirect+'&'+urlparams.urlencode())
return redirect(auth_redirect)
except OIDCConfig.DoesNotExist:
LOGGER.error('OIDCConfig is not available')
except ImproperlyConfigured:
LOGGER.error('No OIDCConfig is not available')
# the error is deleted from the session when the state is delivered
request.session['error'] = 'Server Error'
......@@ -64,7 +90,9 @@ class AuthCallback(View):
def get(self, request):
state = utils.get_session(request, 'state', None)
idp_id = utils.get_session(request, 'idp_id', default_idp().id)
idp_id = utils.get_session(request, 'idp_id', None)
if idp_id is None:
LOGGER.error("Session for %s does not contain an idp_id. Hence we don't now which idp authenticated the user", state)
oidc_config = OIDCConfig.objects.get(id=idp_id)
oidc_client = oidc_config.oidc_client
......@@ -79,8 +107,7 @@ class AuthCallback(View):
raise AuthException('Erroneous callback from IdP {}'.format(oidc_config))
if not state == aresp['state']:
LOGGER.error('AuthCallback: states do not match')
raise AuthException('AuthCallbackStates do not match')
raise AuthException('AuthCallback: States do not match')
ac_token_response = (
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment