5 from django.contrib.auth.decorators import login_required
6 from django.http import HttpResponseForbidden, HttpResponseRedirect, HttpResponseNotAllowed, JsonResponse
7 from django.utils.text import slugify
8 from django.utils.timezone import now
9 from django.views.decorators.csrf import csrf_exempt
11 from jwcrypto.jwk import JWK
12 from jwcrypto.jwt import JWT
14 from .models import OAuthClient, OAuthCode, OAuthSub, OAuthAccessToken
18 def authorize(request, *args, **kwargs):
19 state = request.GET['state']
20 client = OAuthClient.objects.get(client_id=request.GET['client_id'])
21 code = OAuthCode.objects.create(client=client, user=request.user)
22 redirect_uri = request.GET['redirect_uri']
23 return HttpResponseRedirect(redirect_uri + '?code=%s&state=%s' % (code.code, state))
27 def token(request, *args, **kwargs):
28 if request.method != 'POST':
29 return HttpResponseNotAllowed(['POST'])
31 client = OAuthClient.objects.get(client_id=request.POST.get('client_id'))
34 code = OAuthCode.objects.get(client=client, code=request.POST.get('code'))
35 except OAuthCode.DoesNotExist:
36 return HttpResponseForbidden()
39 exp = start + datetime.timedelta(seconds=30)
41 sub, created = OAuthSub.objects.get_or_create(client=client, user=code.user)
44 'iss': request.build_absolute_uri('/'),
45 'aud': client.client_id,
47 'exp': int(exp.timestamp()),
48 'iat': int(start.timestamp()),
49 'auth_time': int(start.timestamp()),
52 header = {'alg': 'HS256'}
53 k = base64.urlsafe_b64encode(client.client_secret.encode('utf-8')).strip(b'=')
54 jwk = JWK(kty='oct', k=k.decode())
55 jwt = JWT(header=header, claims=id_token)
56 jwt.make_signed_token(jwk)
58 access_token = OAuthAccessToken.objects.create(client=client, user=code.user)
61 'access_token': access_token.token,
62 'token_type': 'Bearer',
64 'id_token': jwt.serialize(),
68 def user_info(request, *args, **kwargs):
69 authorization = request.META['HTTP_AUTHORIZATION'].split()
70 if len(authorization) != 2 or authorization[0] != 'Bearer':
71 return HttpResponseForbidden('invalid authorization header')
73 access_token = OAuthAccessToken.objects.get(token=authorization[1])
74 except OAuthAccessToken.DoesNotExist:
75 return HttpResponseForbidden('missing access token')
77 # use a random string as id, as it is required for pharum not to pick
78 # an existing and wrong user.
79 'id': str(random.randint(10**6, 10**7)),
80 'email': access_token.user.email,
81 'name': str(access_token.user),
82 'username': slugify(str(access_token.user)),
84 return JsonResponse(user_info)