Switch from stateless JOSE tokens to stateful tokens in the DB, since they can then be much smaller and we're using a DB anyway

This commit is contained in:
Danielle McLean 2018-06-12 14:57:53 +10:00
parent 9c843ee145
commit 741c2eb234
Signed by: 00dani
GPG key ID: 8EB789DDF3ABD240
7 changed files with 160 additions and 117 deletions

View file

@ -1,5 +1,4 @@
from annoying.decorators import render_to
from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.shortcuts import redirect
@ -11,6 +10,7 @@ from lemoncurry import breadcrumbs, requests, utils
from urllib.parse import urlencode, urljoin, urlunparse, urlparse
from .. import tokens
from ..models import IndieAuthCode
breadcrumbs.add('lemonauth:indie', parent='home:index')
@ -90,25 +90,26 @@ class IndieView(TemplateView):
def post(self, request):
post = request.POST.dict()
try:
code = tokens.decode(post.get('code'))
except Exception:
code = IndieAuthCode.objects.get(pk=post.get('code'))
except IndieAuthCode.DoesNotExist:
# if anything at all goes wrong when decoding the auth code, bail
# out immediately.
return utils.forbid('invalid auth code')
code.delete()
if code.expired:
return utils.forbid('invalid auth code')
if code['typ'] != 'id':
if code.response_type != 'id':
return utils.bad_req(
'this endpoint only supports response_type=id'
)
if code['cid'] != post.get('client_id'):
if code.client_id != post.get('client_id'):
return utils.forbid('client id did not match')
if code['uri'] != post.get('redirect_uri'):
if code.redirect_uri != post.get('redirect_uri'):
return utils.forbid('redirect uri did not match')
user = get_user_model().objects.get(pk=code['uid'])
me = urljoin(utils.origin(request), user.url)
# If we got here, it's valid! Yay!
return utils.choose_type(request, {'me': me}, {
return utils.choose_type(request, {'me': code.me}, {
'application/x-www-form-urlencoded': utils.form_encoded_response,
'application/json': JsonResponse,
})

View file

@ -1,10 +1,9 @@
from django.contrib.auth import get_user_model
from django.views import View
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from urllib.parse import urljoin
from .. import tokens
from ..models import IndieAuthCode
from lemoncurry import utils
@ -16,7 +15,7 @@ class TokenView(View):
return token
res = {
'me': token.me,
'client_id': token.client,
'client_id': token.client_id,
'scope': token.scope,
}
return utils.choose_type(req, res)
@ -24,26 +23,27 @@ class TokenView(View):
def post(self, req):
post = req.POST
try:
code = tokens.decode(post.get('code'))
except Exception:
code = IndieAuthCode.objects.get(pk=post.get('code'))
except IndieAuthCode.DoesNotExist:
return utils.forbid('invalid auth code')
code.delete()
if code.expired:
return utils.forbid('invalid auth code')
if code['typ'] != 'code':
if code.response_type != 'code':
return utils.bad_req(
'this endpoint only supports response_type=code'
)
if code['cid'] != post.get('client_id'):
if code.client_id != post.get('client_id'):
return utils.forbid('client id did not match')
if code['uri'] != post.get('redirect_uri'):
if code.redirect_uri != post.get('redirect_uri'):
return utils.forbid('redirect uri did not match')
user = get_user_model().objects.get(pk=code['uid'])
me = urljoin(utils.origin(req), user.url)
if me != post.get('me'):
if code.me != post.get('me'):
return utils.forbid('me did not match')
return utils.choose_type(req, {
'access_token': tokens.gen_token(code),
'me': me,
'scope': code['sco'],
'me': code.me,
'scope': code.scope,
})