Merge branch 'improve-oauth' into 'master'

Improve oauth

See merge request bestuur/kers!1
This commit is contained in:
fk 2020-07-22 22:30:21 +02:00
commit 01db89727e
2 changed files with 54 additions and 33 deletions

View file

@ -0,0 +1,11 @@
{% extends "base.html" %}
{% block title %}Login Failed{% endblock %}
{% block content %}
<h2>Login Failed</h2>
{% if error %}
<h3>{{ error }}</h3>
{% endif %}
{% endblock %}

View file

@ -4,7 +4,7 @@ import requests
from django.conf import settings from django.conf import settings
from django.contrib.auth import login from django.contrib.auth import login
from django.http.request import HttpRequest from django.http.request import HttpRequest
from django.shortcuts import redirect from django.shortcuts import redirect, render
import users import users
from users.models import CustomUser from users.models import CustomUser
@ -25,37 +25,26 @@ def register(_):
def register_callback(req: HttpRequest): def register_callback(req: HttpRequest):
code = req.GET['code'] if 'code' not in req.GET or 'error' in req.GET:
csrftoken = req.COOKIES.get('csrftoken') error = req.GET['error'] if 'error' in req.GET else None
print(csrftoken) return login_fail(req, error)
response = requests.post(settings.OAUTH["ACCESS_TOKEN_URI"],
data={'code': code,
'grant_type': 'authorization_code',
'client_id': settings.OAUTH["CLIENT_ID"],
'client_secret': settings.OAUTH["CLIENT_SECRET"],
'redirect_uri': settings.OAUTH["REDIRECT_URI"]},
cookies=None,
headers={'Referer': f'{settings.SERVER_URL}/login/zeus/register'})
try: try:
if response.status_code == 200: access_token = get_access_token(req.GET['code'])
json: dict = response.json() user_info = get_user_info(access_token)
print(response.cookies)
# TODO: maybe later do something with the refresh token. logger.debug(f'Succesfully authenticated user: {user_info["username"]} with id: {user_info["id"]}')
user: dict = user_info(json['access_token'], csrftoken)
if 'username' not in user.keys() or 'id' not in user.keys(): validated_user = validate_user(user_info['id'], user_info['username'])
raise OAuthException(f'username and id are expected values: {user}') login(req, validated_user)
else: return redirect('/')
logger.debug(f'Succesfully authenticated user: {user["username"]} with id: {user["id"]}')
validated_user = validate_user(user['id'], user['username'])
login(req, validated_user)
redirect('/')
else:
print(response.request)
raise OAuthException(f'Status code not 200, response: {response}: {response.text}')
except OAuthException as e: except OAuthException as e:
logger.error(e) logger.error(e)
return login_fail(req, str(e))
return redirect('/')
def login_fail(request, error: str = None):
return render(request, "oauth/failed.html", {'error': error})
def validate_user(zeus_id, username) -> CustomUser: def validate_user(zeus_id, username) -> CustomUser:
@ -64,14 +53,35 @@ def validate_user(zeus_id, username) -> CustomUser:
user.username = username user.username = username
user.save() user.save()
return user return user
except users.models.CustomUser.DoesNotExist as e: except users.models.CustomUser.DoesNotExist:
return CustomUser.objects.create_user(zeus_id, username) return CustomUser.objects.create_user(zeus_id, username)
def user_info(access_token, csrftoken): def get_access_token(code):
r = requests.get( response = requests.post(
settings.OAUTH["ACCESS_TOKEN_URI"],
data={'code': code,
'grant_type': 'authorization_code',
'client_id': settings.OAUTH["CLIENT_ID"],
'client_secret': settings.OAUTH["CLIENT_SECRET"],
'redirect_uri': settings.OAUTH["REDIRECT_URI"]},
headers={'Referer': f'{settings.SERVER_URL}/login/zeus/register'})
if response.status_code is not 200:
raise OAuthException(
f'Status code {response.status_code} when requesting access token.\nresponse: {response.text}')
if 'access_token' not in response.json():
raise OAuthException('Got status code 200 but no access_token')
return response.json()['access_token']
def get_user_info(access_token):
response = requests.get(
settings.OAUTH["USER_API_URI"], settings.OAUTH["USER_API_URI"],
headers={'Authorization': f'Bearer {access_token}'}, headers={'Authorization': f'Bearer {access_token}'},
cookies={'csrftoken': csrftoken}
) )
return r.json() if response.status_code is not 200:
raise OAuthException(
f'Status code {response.status_code} when requesting user info.\nresponse: {response.text}')
if 'username' not in response.json() or 'id' not in response.json():
raise OAuthException(f'username and id are expected values: {response.json()}')
return response.json()