lemoncurry/lemonauth/views/token.py

58 lines
1.9 KiB
Python

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 lemoncurry import utils
@method_decorator(csrf_exempt, name='dispatch')
class TokenView(View):
def get(self, req):
token = req.META.get('HTTP_AUTHORIZATION', '').split(' ')
if not token:
return utils.bad_req('missing Authorization header')
if token[0] != 'Bearer':
return utils.bad_req('only Bearer auth is supported')
try:
token = tokens.decode(token[1])
except Exception:
return utils.forbid('invalid token')
user = get_user_model().objects.get(pk=token['uid'])
me = urljoin(utils.origin(req), user.url)
res = {
'me': me,
'client_id': token['cid'],
'scope': token['sco'],
}
return utils.choose_type(req, res)
def post(self, req):
post = req.POST
try:
code = tokens.decode(post.get('code'))
except Exception:
return utils.forbid('invalid auth code')
if code['typ'] != 'code':
return utils.bad_req(
'this endpoint only supports response_type=code'
)
if code['cid'] != post.get('client_id'):
return utils.forbid('client id did not match')
if code['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'):
return utils.forbid('me did not match')
return utils.choose_type(req, {
'access_token': tokens.gen_token(code),
'me': me,
'scope': code['sco'],
})