Commit 1c64600c authored by Lukas Burgey's avatar Lukas Burgey
Browse files

Update userinfo of users

parent a6ae9e38
...@@ -75,7 +75,7 @@ def _webpage_client_valid(request): ...@@ -75,7 +75,7 @@ def _webpage_client_valid(request):
): ):
return True return True
LOGGER.error('Failed to authenticate webpage client for RabbitMQ') #LOGGER.error('Failed to authenticate webpage client for RabbitMQ')
return False return False
# VIEWS: authentication and authorization for # VIEWS: authentication and authorization for
...@@ -83,14 +83,14 @@ def _webpage_client_valid(request): ...@@ -83,14 +83,14 @@ def _webpage_client_valid(request):
def user_endpoint(request): def user_endpoint(request):
if _webpage_client_valid(request): if _webpage_client_valid(request):
#LOGGER.info('Authenticated webpage client') LOGGER.info('Authenticated webpage client')
return ALLOW return ALLOW
user = authenticate( user = authenticate(
username=request.POST.get('username'), username=request.POST.get('username'),
password=request.POST.get('password'), password=request.POST.get('password'),
) )
if user: if user is not None:
LOGGER.info('Authenticated client as %s', user) LOGGER.info('Authenticated client as %s', user)
return ALLOW return ALLOW
...@@ -175,7 +175,6 @@ def resource_endpoint(request): ...@@ -175,7 +175,6 @@ def resource_endpoint(request):
) )
return DENY return DENY
def topic_endpoint(request): def topic_endpoint(request):
permission = request.POST.get('permission', []) permission = request.POST.get('permission', [])
resource = request.POST.get('resource', '') resource = request.POST.get('resource', '')
...@@ -215,8 +214,7 @@ def topic_endpoint(request): ...@@ -215,8 +214,7 @@ def topic_endpoint(request):
match = re.search('service.(.+)', routing_key) match = re.search('service.(.+)', routing_key)
if match: if match:
service_name = match.group(1) service_name = match.group(1)
for service in user.site.services.all(): if user.site.services.filter(name=service_name).exists():
if service_name == service.name:
return ALLOW return ALLOW
elif name == 'sites': elif name == 'sites':
if routing_key == user.site.name: if routing_key == user.site.name:
......
import logging import logging
import json import json
from urllib.request import Request, urlopen from urllib.request import Request, urlopen
from django.core.exceptions import ObjectDoesNotExist
from django.db import models as db_models from django.db import models as db_models
from django_mysql.models import JSONField
from oic.oic import Client from oic.oic import Client
from oic.oic.message import RegistrationResponse from oic.oic.message import RegistrationResponse
from oic.utils.authn.client import CLIENT_AUTHN_METHOD from oic.utils.authn.client import CLIENT_AUTHN_METHOD
...@@ -13,6 +13,9 @@ LOGGER = logging.getLogger(__name__) ...@@ -13,6 +13,9 @@ LOGGER = logging.getLogger(__name__)
OIDC_CLIENT = {} OIDC_CLIENT = {}
def scopes_default():
return []
class OIDCConfig(db_models.Model): class OIDCConfig(db_models.Model):
client_id = db_models.CharField(max_length=200) client_id = db_models.CharField(max_length=200)
...@@ -25,6 +28,13 @@ class OIDCConfig(db_models.Model): ...@@ -25,6 +28,13 @@ class OIDCConfig(db_models.Model):
# does this idp provide us with group informations? # does this idp provide us with group informations?
group_provider = db_models.BooleanField(default=False) group_provider = db_models.BooleanField(default=False)
# scopes as a list of strings
scopes = JSONField(
default=scopes_default,
editable=True,
)
@property @property
def registration_response(self): def registration_response(self):
info = { info = {
...@@ -55,13 +65,13 @@ class OIDCConfig(db_models.Model): ...@@ -55,13 +65,13 @@ class OIDCConfig(db_models.Model):
args = { args = {
'client_id': self.client_id, 'client_id': self.client_id,
'response_type': 'code', 'response_type': 'code',
'scope': ['openid', 'profile', 'email', 'credentials'], 'scope': self.scopes,
'redirect_uri': self.redirect_uri, 'redirect_uri': self.redirect_uri,
'state': state, 'state': state,
} }
auth_req = client.construct_AuthorizationRequest( auth_req = client.construct_AuthorizationRequest(
request_args=args request_args=args,
) )
return auth_req.request(client.authorization_endpoint) return auth_req.request(client.authorization_endpoint)
...@@ -79,12 +89,12 @@ def default_idp(): ...@@ -79,12 +89,12 @@ def default_idp():
class OIDCTokenAuthBackend(object): class OIDCTokenAuthBackend(object):
def get_userinfo(self, request, oidc_client, access_token='', state=None): def get_userinfo(self, oidc_client, access_token=None):
user_info = None user_info = None
if access_token is not None: if access_token is not None:
req = Request( req = Request(
oidc_client.provider_info['userinfo_endpoint']+'?scope=openid&scope=profile', oidc_client.provider_info['userinfo_endpoint'],
) )
auth = ('Bearer ' + access_token) auth = ('Bearer ' + access_token)
req.add_header('Authorization', auth) req.add_header('Authorization', auth)
...@@ -108,25 +118,33 @@ class OIDCTokenAuthBackend(object): ...@@ -108,25 +118,33 @@ class OIDCTokenAuthBackend(object):
# get the user info from the idp # get the user info from the idp
userinfo = self.get_userinfo( userinfo = self.get_userinfo(
request,
oidc_client, oidc_client,
access_token=token, access_token=token,
) )
try:
return models.User.get_user( return models.User.get_user(
userinfo, userinfo,
oidc_client, oidc_client,
) )
except Exception as exception:
LOGGER.error('OIDCTokenAuthBackend: error constructing user: %s', exception)
return None
def get_user(self, user_id): def get_user(self, user_id):
try: query = models.User.objects.filter(
return models.User.objects.get(
user_type='oidcuser', user_type='oidcuser',
pk=user_id pk=user_id
) )
except ObjectDoesNotExist: if query.exists():
if len(query) == 1:
return query.first()
LOGGER.error(
'OIDCTokenAuthBackend: query for user id %s: %s results',
user_id,
len(query),
)
return None
LOGGER.error(
'OIDCTokenAuthBackend: query for user id %s: no results',
user_id,
)
return None return None
...@@ -89,24 +89,6 @@ class AuthCallback(View): ...@@ -89,24 +89,6 @@ class AuthCallback(View):
}, },
) )
) )
# FIXME 'email_verified' in user info is no boolean
# but oic expects it to be
#user_info = oidc_client.do_user_info_request(
# method="GET",
# state=state,
#)
#LOGGER.debug("EXPERIMENT: %s", user_info)
# user_info = self.get_user_info(ac_token_response['access_token'])
# try:
# u = models.User.objects.get(sub=user_info['sub'])
# except:
# u = models.user_from_user_info(user_info)
# u.save()
# response = render(request, 'backend/index.html', context)
user = authenticate( user = authenticate(
request, request,
token=ac_token_response['access_token'], token=ac_token_response['access_token'],
...@@ -117,13 +99,11 @@ class AuthCallback(View): ...@@ -117,13 +99,11 @@ class AuthCallback(View):
if user is None: if user is None:
# authentication failed -> "401" # authentication failed -> "401"
LOGGER.error('User failed to log in') LOGGER.error('User failed to log in')
utils.set_session(request, 'error', 'Login failed') request.session['error'] = 'Authentication failed'
# response = HttpResponse('Unauthorized', status=401)
elif not user.is_active: elif not user.is_active:
# user is deactivated -> "403" # user is deactivated -> "403"
LOGGER.info('%s tried to log in', user) LOGGER.info('%s tried to log in', user)
utils.set_session(request, 'error', 'Account deactivated') request.session['error'] = 'Account deactivated'
# response = HttpResponse('Forbidden', status=403)
else: else:
# user authenticated -> back to frontend # user authenticated -> back to frontend
login(request, user) login(request, user)
......
import logging import logging
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.auth import logout from django.contrib.auth import logout
from rest_framework import views from rest_framework import views
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
...@@ -35,22 +34,6 @@ def _api_state_response_data(request): ...@@ -35,22 +34,6 @@ def _api_state_response_data(request):
'user_state': user_state(request.user), 'user_state': user_state(request.user),
} }
# Response for StateView, LogoutView, and all post requests
def _api_state_response(request):
if not request.user.is_authenticated:
return Response({
'user_state': None,
})
response = _api_state_response_data(request)
if 'error' in request.session:
response['error'] = request.session['error']
# we display errors only once
del request.session['error']
return Response(response)
def state_view_data(request): def state_view_data(request):
data = {} data = {}
if request.user.is_authenticated: if request.user.is_authenticated:
...@@ -66,6 +49,12 @@ def state_view_data(request): ...@@ -66,6 +49,12 @@ def state_view_data(request):
data['user'] = None data['user'] = None
data['user_state'] = None data['user_state'] = None
data['services'] = [] data['services'] = []
if 'error' in request.session:
data['error'] = request.session['error']
# we display errors only once
del request.session['error']
return data return data
...@@ -161,7 +150,7 @@ class QuestionnaireView(views.APIView): ...@@ -161,7 +150,7 @@ class QuestionnaireView(views.APIView):
else: else:
LOGGER.error('Received questionnaire answer for non existing item') LOGGER.error('Received questionnaire answer for non existing item')
return _api_state_response(request) return Response(state_view_data(request))
class UserDeletionView(views.APIView): class UserDeletionView(views.APIView):
......
...@@ -280,19 +280,22 @@ class User(AbstractUser): ...@@ -280,19 +280,22 @@ class User(AbstractUser):
if 'sub' not in userinfo: if 'sub' not in userinfo:
raise Exception('get_user needs a userinfo which contains the users subject') raise Exception('get_user needs a userinfo which contains the users subject')
query_result = cls.objects.filter( query = cls.objects.filter(
sub=userinfo['sub'], sub=userinfo['sub'],
idp=idp, idp=idp,
) )
if not query_result.exists(): if not query.exists():
return cls.construct_from_userinfo(userinfo, idp) return cls.construct_from_userinfo(userinfo, idp)
if len(query_result) > 1: if len(query) > 1:
return Exception('Two user instances with same subject from the same idp') return Exception('Two user instances with same subject from the same idp')
# TODO update the users userinfo when it changes user = query.first()
# TODO update the users groupinfo when it changes # update the users userinfo
return query_result.first() user.userinfo = userinfo
user.save()
return user
@classmethod @classmethod
def construct_from_userinfo(cls, userinfo, idp): def construct_from_userinfo(cls, userinfo, idp):
......
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