Commit 174c5e1b authored by Lukas Burgey's avatar Lukas Burgey
Browse files

Merge branch 'issuer-detection' into dev

parents 592cd99f cc87afa9
import logging
import json
import jwt
from urllib.error import HTTPError
from urllib.request import Request, urlopen
......@@ -29,16 +30,51 @@ class OIDCTokenAuthBackend:
return user_info
# no issuer -> try all idps :/
def get_userinfo_bruteforce(self, access_token):
for oidc_client in OIDCConfig.objects.filter(enabled=True):
try:
return oidc_client, self.get_userinfo(
oidc_client,
access_token,
)
except HTTPError as exception:
pass
raise OIDCConfig.DoesNotExist('Unable to determine IdP')
# raises OIDCConfig.DoesNotExist if no idp can be determined
def get_idp(self, request):
# OPTION 1: issuer set in the 'X-Issuer' header
if 'HTTP_X_ISSUER' in request.META:
return OIDCConfig.objects.get(issuer_uri=request.META['HTTP_X_ISSUER'])
return OIDCConfig.objects.get(
issuer_uri=request.META['HTTP_X_ISSUER'],
enabled=True,
)
# OPTION 2: issuer set in users session (before redirecting to IdP)
idp_id = utils.get_session(request, 'idp_id', None)
if idp_id is not None:
return OIDCConfig.objects.get(id=idp_id)
return OIDCConfig.objects.get(
id=idp_id,
enabled=True,
)
# OPTION 3: read 'iss' JWT
access_token = request.META['HTTP_AUTHORIZATION']
try:
data = jwt.decode(access_token)
if 'iss' in data:
return OIDCConfig.objects.get(
issuer_uri=data['iss'],
enabled=True,
)
LOGGER.debug("JWT access token does not contain iss field")
except jwt.exceptions.InvalidTokenError as exception: # base exception for jwt.decode
pass
raise OIDCConfig.DoesNotExist('Unable to determine IdP')
......@@ -74,22 +110,33 @@ class OIDCTokenAuthBackend:
from feudal.backend.models.users import User
idp = None
userinfo = None
# DETERMINE idp AND userinfo
try:
idp = self.get_idp(request)
except OIDCConfig.DoesNotExist:
request.session['auth_error'] = 'Unable to determine IdP'
return None
# get the user info from the idp
try:
userinfo = self.get_userinfo(
idp,
access_token,
)
except HTTPError as exception:
except OIDCConfig.DoesNotExist: # from get_idp
# Idp was not provided in param / session / JWT -> just try all of them
try:
idp, userinfo = self.get_userinfo_bruteforce(access_token)
except OIDCConfig.DoesNotExist:
request.session['auth_error'] = 'Unable to determine IdP'
return None
except HTTPError as exception: # from get_userinfo
request.session['auth_error'] = 'HTTP when retrieving user info: {}'.format(exception)
return None
# idp and userinfo are set correctly below this point
try:
user = User.get_user(
userinfo,
......
......@@ -9,3 +9,4 @@ django-nose==1.4.6
django_polymorphic==2.1.2
django-rest-polymorphic==0.1.8
mysqlclient==1.4.5
PyJWT==1.7.1
Supports Markdown
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