Commit e06d7012 authored by Jean-Baptiste's avatar Jean-Baptiste

update: request access token

parent 92f2a85e
from django.contrib import admin
from .models import Account, ChatProfile
from .models import Account, ChatProfile, OPClient
admin.site.register(ChatProfile)
admin.site.register(Account)
admin.site.register(OPClient)
......@@ -5,7 +5,7 @@ from django.urls import reverse
from djangoldp_account.errors import LDPLoginError
from djangoldp_account.models import OPClient
from oic import rndstr
from oic.oic import Client
from oic.oic import Client, AuthorizationResponse
from oic.utils.authn.client import CLIENT_AUTHN_METHOD
......@@ -57,7 +57,7 @@ class RPLoginEndpoint(object):
try:
provider_info = self.client.provider_config(subject)
except:
raise LDPLoginError("cannot_get_provider_info")
raise LDPLoginError(error="cannot_get_provider_info")
existing_op_client = OPClient.objects.filter(issuer=provider_info._dict['issuer']).first()
if existing_op_client is None:
......@@ -65,7 +65,7 @@ class RPLoginEndpoint(object):
registration_endpoint = provider_info._dict["registration_endpoint"]
args = {
"client_name": settings.SITE_URL,
"response_types": ["id_token token"],
"response_types": ["id_token token", "code"],
"redirect_uris": redirect_uris,
}
......@@ -73,18 +73,21 @@ class RPLoginEndpoint(object):
registration_endpoint, **args)
OPClient.objects.create(issuer=provider_info._dict['issuer'],
client_id=self.client.client_id)
client_id=self.client.client_id)
except:
raise LDPLoginError("cannot_register")
raise LDPLoginError(error="cannot_register")
else:
self.client.client_id = existing_op_client.client_id
self.request.session['nonce'] = rndstr()
self.request.session['state'] = rndstr()
self.request.session['next'] = self.params['next']
self.request.session['client_id'] = self.client.client_id
self.request.session['issuer'] = provider_info._dict['issuer']
args = {
"client_id": self.client.client_id,
"response_type": ["id_token token"],
"response_type": ["code"],
"scope": ["openid website"],
"nonce": self.request.session['nonce'],
"redirect_uri": redirect_uris[0],
......@@ -93,3 +96,56 @@ class RPLoginEndpoint(object):
auth_req = self.client.construct_AuthorizationRequest(request_args=args)
return auth_req.request(self.client.authorization_endpoint)
class RPLoginCallBackEndpoint(object):
"""
RL login callback endpoint
"""
client_class = Client
def __init__(self, request):
self.request = request
self.params = {}
self.client = self.client_class(client_authn_method=CLIENT_AUTHN_METHOD)
op_client = OPClient.objects.filter(issuer=self.request.session['issuer']).first()
if op_client is None:
raise LDPLoginError(error="wrong_issuer")
self.client.client_id = op_client.client_id
self.client.client_secret = op_client.client_secret
try:
provider_info = self.client.provider_config(self.request.session['issuer'])
except:
raise LDPLoginError(error="cannot_get_provider_info")
self._extract_params()
def _extract_params(self):
query_string = self.request.environ["QUERY_STRING"]
aresp = self.client.parse_response(AuthorizationResponse, info=query_string, sformat='urlencoded')
self.params['state'] = aresp['state']
self.params['code'] = aresp['code']
def validate_params(self):
if not self.params["state"] == self.request.session['state']:
raise LDPLoginError(error='invalid_state')
def initial_url(self):
args = {
"code": self.params["code"],
"redirect_uri": self.request.session['next'] or settings.SITE_URL
}
resp = self.client.do_access_token_request(state=self.params["state"],
request_args=args,
authn_method="client_secret_basic")
if 'error' in resp:
raise LDPLoginError(dict=resp)
userinfo = self.client.do_user_info_request(method='GET', state=self.params["state"])
# TODO : put a session cookie
return self.request.session['next'] or settings.SITE_URL
......@@ -4,13 +4,19 @@ class LDPLoginError(Exception):
_errors = {
'invalid_request': "The request provider parameter must contains an url or an email",
'invalid_state': "Invalid state",
'wrong_issuer': "Cannot find OP client from this issuer",
'cannot_get_provider_info': "Cannot get provider informations",
'cannot_register': "Unable to register, is the provider accepting registration ? If not contact <todo : give an email> to make a manual registration"
}
def __init__(self, error):
self.error = error
self.description = self._errors.get(error)
def __init__(self, error=None, dict=None):
if dict is None:
self.error = error
self.description = self._errors.get(error)
else:
self.error = dict['error']
self.description = dict['error_description']
def create_dict(self):
dic = {
......
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2019-04-15 11:09
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('djangoldp_account', '0005_opclient'),
]
operations = [
migrations.AddField(
model_name='opclient',
name='client_secret',
field=models.CharField(default=1, max_length=255),
preserve_default=False,
),
]
......@@ -45,6 +45,10 @@ class ChatProfile(models.Model):
class OPClient(models.Model):
issuer = models.URLField()
client_id = models.CharField(max_length=255)
client_secret = models.CharField(max_length=255)
def __str__(self):
return '{} ({})'.format(self.issuer, self.client_id)
@receiver(post_save, sender=User)
......
from django.http import HttpResponse, JsonResponse, HttpResponseRedirect
from django.views import View
from oic.oic import AuthorizationResponse
from djangoldp_account.endpoints.login import RPLoginEndpoint
from djangoldp_account.endpoints.rp_login import RPLoginCallBackEndpoint, RPLoginEndpoint
from djangoldp_account.errors import LDPLoginError
from oidc_provider.views import userinfo
......@@ -26,17 +25,17 @@ class RPLoginView(View):
See https://github.com/solid/webid-oidc-spec/blob/master/example-workflow.md
Wa're using oid module : https://pyoidc.readthedocs.io/en/latest/examples/rp.html
"""
login_endpoint_class = RPLoginEndpoint
endpoint_class = RPLoginEndpoint
def get(self, request, *args, **kwargs):
return self.on_request(request)
def on_request(self, request):
login = self.login_endpoint_class(request)
endpoint = self.endpoint_class(request)
try:
login.validate_params()
endpoint.validate_params()
return HttpResponseRedirect(login.op_login_url())
return HttpResponseRedirect(endpoint.op_login_url())
except LDPLoginError as error:
return JsonResponse(error.create_dict(), status=400)
......@@ -46,17 +45,21 @@ class RPLoginView(View):
class RPLoginCallBackView(View):
endpoint_class = RPLoginCallBackEndpoint
def get(self, request, *args, **kwargs):
return self.on_request(request)
response = request.environ["QUERY_STRING"]
# aresp = client.parse_response(AuthorizationResponse, info=response,
# sformat="urlencoded")
#
# code = aresp["code"]
# assert aresp["state"] == request.session['state']
def on_request(self, request):
endpoint = self.endpoint_class(request)
try:
pass
except:
pass
endpoint.validate_params()
return HttpResponseRedirect(endpoint.initial_url())
except LDPLoginError as error:
return JsonResponse(error.create_dict(), status=400)
def post(self, request, *args, **kwargs):
return self.on_request(request)
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