demand authorization
This commit is contained in:
parent
d57b3fc02c
commit
19e44cf52d
|
@ -1,2 +1,4 @@
|
|||
"ExO";"https://verify.exo.cat"
|
||||
"Somos Connexión";"https://verify.somosconexion.coop"
|
||||
"test2";"http://localhost:9000/verify"
|
||||
"test1";"http://localhost:8000/verify"
|
||||
|
|
|
|
@ -41,4 +41,4 @@ class Command(BaseCommand):
|
|||
|
||||
|
||||
def create_organizations(self, name, url):
|
||||
Organization.objects.create(name=name, url=url)
|
||||
Organization.objects.create(name=name, response_uri=url)
|
||||
|
|
|
@ -115,7 +115,7 @@
|
|||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if path == 'user_credentials_presentation' %}active2{% endif %}" href="{% url 'idhub:user_credentials_presentation' %}">
|
||||
<a class="nav-link {% if path == 'user_demand_authorization' %}active2{% endif %}" href="{% url 'idhub:user_demand_authorization' %}">
|
||||
{% trans 'Present a credential' %}
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -20,7 +20,7 @@ from django.urls import path, reverse_lazy
|
|||
from .views import LoginView
|
||||
from .admin import views as views_admin
|
||||
from .user import views as views_user
|
||||
from .verification_portal import views as views_verification_portal
|
||||
# from .verification_portal import views as views_verification_portal
|
||||
|
||||
app_name = 'idhub'
|
||||
|
||||
|
@ -85,6 +85,9 @@ urlpatterns = [
|
|||
path('user/credentials/request/',
|
||||
views_user.CredentialsRequestView.as_view(),
|
||||
name='user_credentials_request'),
|
||||
path('user/credentials_presentation/demand',
|
||||
views_user.DemandAuthorizationView.as_view(),
|
||||
name='user_demand_authorization'),
|
||||
path('user/credentials_presentation/',
|
||||
views_user.CredentialsPresentationView.as_view(),
|
||||
name='user_credentials_presentation'),
|
||||
|
@ -173,6 +176,6 @@ urlpatterns = [
|
|||
path('admin/import/new', views_admin.ImportAddView.as_view(),
|
||||
name='admin_import_add'),
|
||||
|
||||
path('verification_portal/verify/', views_verification_portal.verify,
|
||||
name="verification_portal_verify")
|
||||
# path('verification_portal/verify/', views_verification_portal.verify,
|
||||
# name="verification_portal_verify")
|
||||
]
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import requests
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from idhub_auth.models import User
|
||||
from idhub.models import DID, VerificableCredential
|
||||
from oidc4vp.models import Organization
|
||||
|
@ -56,9 +58,40 @@ class RequestCredentialForm(forms.Form):
|
|||
return
|
||||
|
||||
|
||||
class DemandAuthorizationForm(forms.Form):
|
||||
organization = forms.ChoiceField(choices=[])
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.user = kwargs.pop('user', None)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['organization'].choices = [
|
||||
(x.id, x.name) for x in Organization.objects.filter()
|
||||
if x.response_uri != settings.RESPONSE_URI
|
||||
]
|
||||
|
||||
def save(self, commit=True):
|
||||
self.org = Organization.objects.filter(
|
||||
id=self.data['organization']
|
||||
)
|
||||
if not self.org.exists():
|
||||
return
|
||||
|
||||
self.org = self.org[0]
|
||||
|
||||
if commit:
|
||||
url = self.org.demand_authorization()
|
||||
auth = (self.org.client_id, self.org.client_secret)
|
||||
# res = requests.get(url, auth=auth)
|
||||
# import pdb; pdb.set_trace()
|
||||
# if res.status == 200:
|
||||
# return res.body
|
||||
|
||||
return
|
||||
|
||||
|
||||
class CredentialPresentationForm(forms.Form):
|
||||
organization = forms.ChoiceField(choices=[])
|
||||
credential = forms.ChoiceField(choices=[])
|
||||
# credential = forms.ChoiceField(choices=[])
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.user = kwargs.pop('user', None)
|
||||
|
@ -66,12 +99,12 @@ class CredentialPresentationForm(forms.Form):
|
|||
self.fields['organization'].choices = [
|
||||
(x.id, x.name) for x in Organization.objects.filter()
|
||||
]
|
||||
self.fields['credential'].choices = [
|
||||
(x.id, x.type()) for x in VerificableCredential.objects.filter(
|
||||
user=self.user,
|
||||
status=VerificableCredential.Status.ISSUED
|
||||
)
|
||||
]
|
||||
# self.fields['credential'].choices = [
|
||||
# (x.id, x.type()) for x in VerificableCredential.objects.filter(
|
||||
# user=self.user,
|
||||
# status=VerificableCredential.Status.ISSUED
|
||||
# )
|
||||
# ]
|
||||
|
||||
def save(self, commit=True):
|
||||
self.org = Organization.objects.filter(
|
||||
|
|
|
@ -12,7 +12,12 @@ from django.shortcuts import get_object_or_404, redirect
|
|||
from django.urls import reverse_lazy
|
||||
from django.http import HttpResponse
|
||||
from django.contrib import messages
|
||||
from idhub.user.forms import ProfileForm, RequestCredentialForm, CredentialPresentationForm
|
||||
from idhub.user.forms import (
|
||||
ProfileForm,
|
||||
RequestCredentialForm,
|
||||
CredentialPresentationForm,
|
||||
DemandAuthorizationForm
|
||||
)
|
||||
from idhub.mixins import UserView
|
||||
from idhub.models import DID, VerificableCredential, Event
|
||||
|
||||
|
@ -141,6 +146,28 @@ class CredentialsRequestView(MyWallet, FormView):
|
|||
return super().form_valid(form)
|
||||
|
||||
|
||||
class DemandAuthorizationView(MyWallet, FormView):
|
||||
template_name = "idhub/user/credentials_presentation.html"
|
||||
subtitle = _('Credential presentation')
|
||||
icon = 'bi bi-patch-check-fill'
|
||||
form_class = DemandAuthorizationForm
|
||||
success_url = reverse_lazy('idhub:user_demand_authorization')
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs['user'] = self.request.user
|
||||
return kwargs
|
||||
|
||||
def form_valid(self, form):
|
||||
authorization = form.save()
|
||||
if authorization:
|
||||
if authorization.get('redirect_uri'):
|
||||
redirect(authorization.get('redirect_uri'))
|
||||
else:
|
||||
messages.error(self.request, _("Error sending credential!"))
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class CredentialsPresentationView(MyWallet, FormView):
|
||||
template_name = "idhub/user/credentials_presentation.html"
|
||||
subtitle = _('Credential presentation')
|
||||
|
@ -151,6 +178,7 @@ class CredentialsPresentationView(MyWallet, FormView):
|
|||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs['user'] = self.request.user
|
||||
kwargs['authorize'] = self.request.GET.params.get("uri")
|
||||
return kwargs
|
||||
|
||||
def form_valid(self, form):
|
||||
|
|
|
@ -54,12 +54,27 @@ class Organization(models.Model):
|
|||
"""
|
||||
Send the verificable presentation to Verifier
|
||||
"""
|
||||
org = Organization.objects.get(
|
||||
org = self.__class__.objects.get(
|
||||
response_uri=settings.RESPONSE_URI
|
||||
)
|
||||
auth = (org.client_id, org.client_secret)
|
||||
return requests.post(self.url, data=vp, auth=auth)
|
||||
|
||||
def demand_authorization(self):
|
||||
"""
|
||||
Send the a request for start a process of Verifier
|
||||
"""
|
||||
org = self.__class__.objects.get(
|
||||
response_uri=settings.RESPONSE_URI
|
||||
)
|
||||
# import pdb; pdb.set_trace()
|
||||
url = "{url}/?demand_uri={redirect_uri}".format(
|
||||
url=self.response_uri.strip("/"),
|
||||
redirect_uri=settings.RESPONSE_URI
|
||||
)
|
||||
auth = (org.client_id, org.client_secret)
|
||||
return requests.get(url, auth=auth)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
@ -75,11 +90,11 @@ class Authorization(models.Model):
|
|||
The Verifier need to do a redirection to the user to Wallet.
|
||||
The code we use as a soft foreing key between Authorization and OAuth2VPToken.
|
||||
"""
|
||||
nonce = models.CharField(max_length=50)
|
||||
expected_credentials = models.CharField(max_length=255)
|
||||
expected_contents = models.TextField()
|
||||
action = models.TextField()
|
||||
response_or_redirect = models.CharField(max_length=255)
|
||||
# nonce = models.CharField(max_length=50)
|
||||
# expected_credentials = models.CharField(max_length=255)
|
||||
# expected_contents = models.TextField()
|
||||
# action = models.TextField()
|
||||
# response_or_redirect = models.CharField(max_length=255)
|
||||
|
||||
code = models.CharField(max_length=24, default=set_code)
|
||||
created = models.DateTimeField(auto_now=True)
|
||||
|
@ -98,7 +113,7 @@ class Authorization(models.Model):
|
|||
|
||||
def authorize(self):
|
||||
response_uri = self.__class__.objects.filter(
|
||||
response_uri=settings.RESPONSE_URI
|
||||
response_uri=settings.ALLOW_CODE_URI
|
||||
)
|
||||
data = {
|
||||
"response_type": "vp_token",
|
||||
|
|
105
oidc4vp/views.py
105
oidc4vp/views.py
|
@ -6,44 +6,75 @@ from django.http import HttpResponse, HttpResponseRedirect
|
|||
from utils.idhub_ssikit import verify_presentation
|
||||
from .models import VPVerifyRequest
|
||||
from django.shortcuts import get_object_or_404
|
||||
from more_itertools import flatten, unique_everseen
|
||||
# from more_itertools import flatten, unique_everseen
|
||||
from oidc4vp.models import Authorization
|
||||
|
||||
|
||||
# class PeopleListView(People, TemplateView):
|
||||
# template_name = "idhub/admin/people.html"
|
||||
# subtitle = _('View users')
|
||||
# icon = 'bi bi-person'
|
||||
|
||||
# def get_context_data(self, **kwargs):
|
||||
# context = super().get_context_data(**kwargs)
|
||||
# context.update({
|
||||
# 'users': User.objects.filter(),
|
||||
# })
|
||||
# return context
|
||||
|
||||
|
||||
def DemandAuthorizationView(request):
|
||||
assert request.method == "GET"
|
||||
import pdb; pdb.set_trace()
|
||||
params = request.GET.params
|
||||
org = Organization.objects.filter(
|
||||
url=params.get('redirect_uri')
|
||||
)
|
||||
authorization = Authorization(
|
||||
organization=org,
|
||||
presentation_definition="MemberCredential"
|
||||
)
|
||||
# authorization.save()
|
||||
res = json.dumps({"uri": authorization.authorize()})
|
||||
return HttpResponse(res)
|
||||
|
||||
|
||||
def verify(request):
|
||||
assert request.method == "POST"
|
||||
# TODO: incorporate request.POST["presentation_submission"] as schema definition
|
||||
(presentation_valid, _) = verify_presentation(request.POST["vp_token"])
|
||||
if not presentation_valid:
|
||||
raise Exception("Failed to verify signature on the given Verifiable Presentation.")
|
||||
vp = json.loads(request.POST["vp_token"])
|
||||
nonce = vp["nonce"]
|
||||
# "vr" = verification_request
|
||||
vr = get_object_or_404(VPVerifyRequest, nonce=nonce) # TODO: return meaningful error, not 404
|
||||
# Get a list of all included verifiable credential types
|
||||
included_credential_types = unique_everseen(flatten([
|
||||
vc["type"] for vc in vp["verifiableCredential"]
|
||||
]))
|
||||
# Check that it matches what we requested
|
||||
for requested_vc_type in json.loads(vr.expected_credentials):
|
||||
if requested_vc_type not in included_credential_types:
|
||||
raise Exception("You're missing some credentials we requested!") # TODO: return meaningful error
|
||||
# Perform whatever action we have to do
|
||||
action = json.loads(vr.action)
|
||||
if action["action"] == "send_mail":
|
||||
subject = action["params"]["subject"]
|
||||
to_email = action["params"]["to"]
|
||||
from_email = "noreply@verifier-portal"
|
||||
body = request.POST["vp-token"]
|
||||
send_mail(
|
||||
subject,
|
||||
body,
|
||||
from_email,
|
||||
[to_email]
|
||||
)
|
||||
elif action["action"] == "something-else":
|
||||
pass
|
||||
else:
|
||||
raise Exception("Unknown action!")
|
||||
# OK! Your verifiable presentation was successfully presented.
|
||||
return HttpResponseRedirect(vr.response_or_redirect)
|
||||
import pdb; pdb.set_trace()
|
||||
# assert request.method == "POST"
|
||||
# # TODO: incorporate request.POST["presentation_submission"] as schema definition
|
||||
# (presentation_valid, _) = verify_presentation(request.POST["vp_token"])
|
||||
# if not presentation_valid:
|
||||
# raise Exception("Failed to verify signature on the given Verifiable Presentation.")
|
||||
# vp = json.loads(request.POST["vp_token"])
|
||||
# nonce = vp["nonce"]
|
||||
# # "vr" = verification_request
|
||||
# vr = get_object_or_404(VPVerifyRequest, nonce=nonce) # TODO: return meaningful error, not 404
|
||||
# # Get a list of all included verifiable credential types
|
||||
# included_credential_types = unique_everseen(flatten([
|
||||
# vc["type"] for vc in vp["verifiableCredential"]
|
||||
# ]))
|
||||
# # Check that it matches what we requested
|
||||
# for requested_vc_type in json.loads(vr.expected_credentials):
|
||||
# if requested_vc_type not in included_credential_types:
|
||||
# raise Exception("You're missing some credentials we requested!") # TODO: return meaningful error
|
||||
# # Perform whatever action we have to do
|
||||
# action = json.loads(vr.action)
|
||||
# if action["action"] == "send_mail":
|
||||
# subject = action["params"]["subject"]
|
||||
# to_email = action["params"]["to"]
|
||||
# from_email = "noreply@verifier-portal"
|
||||
# body = request.POST["vp-token"]
|
||||
# send_mail(
|
||||
# subject,
|
||||
# body,
|
||||
# from_email,
|
||||
# [to_email]
|
||||
# )
|
||||
# elif action["action"] == "something-else":
|
||||
# pass
|
||||
# else:
|
||||
# raise Exception("Unknown action!")
|
||||
# # OK! Your verifiable presentation was successfully presented.
|
||||
# return HttpResponseRedirect(vr.response_or_redirect)
|
||||
|
||||
|
|
|
@ -186,3 +186,4 @@ USE_L10N = True
|
|||
|
||||
AUTH_USER_MODEL = 'idhub_auth.User'
|
||||
RESPONSE_URI = config('RESPONSE_URI', default="")
|
||||
ALLOW_CODE_URI= config('ALLOW_CODE_URI', default="")
|
||||
|
|
|
@ -24,4 +24,5 @@ from django.contrib.auth import views as auth_views
|
|||
urlpatterns = [
|
||||
# path('django-admin/', admin.site.urls),
|
||||
path('', include('idhub.urls')),
|
||||
path('oidc4vp/', include('oidc4vp.urls')),
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue