demand authorization

This commit is contained in:
Cayo Puigdefabregas 2023-11-28 09:39:02 +01:00
parent d57b3fc02c
commit 19e44cf52d
11 changed files with 171 additions and 57 deletions

View File

@ -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"

1 ExO https://verify.exo.cat
2 Somos Connexión https://verify.somosconexion.coop
3 test2 http://localhost:9000/verify
4 test1 http://localhost:8000/verify

View File

@ -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)

View File

@ -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>

View File

@ -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")
]

View File

@ -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(

View File

@ -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):

View File

@ -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",

View File

@ -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)

View File

@ -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="")

View File

@ -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')),
]