add more details to flow
This commit is contained in:
parent
7db6d1f4e3
commit
9e8596f39d
|
@ -0,0 +1,134 @@
|
||||||
|
# Generated by Django 4.2.5 on 2023-11-24 16:53
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import oidc4vp.models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Authorization',
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
'id',
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name='ID',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'code',
|
||||||
|
models.CharField(default=oidc4vp.models.set_code, max_length=24),
|
||||||
|
),
|
||||||
|
('created', models.DateTimeField(auto_now=True)),
|
||||||
|
('presentation_definition', models.CharField(max_length=250)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Organization',
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
'id',
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name='ID',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
('name', models.CharField(max_length=250)),
|
||||||
|
(
|
||||||
|
'client_id',
|
||||||
|
models.CharField(
|
||||||
|
default=oidc4vp.models.set_client_id, max_length=24
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'client_secret',
|
||||||
|
models.CharField(
|
||||||
|
default=oidc4vp.models.set_client_secret, max_length=48
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'response_uri',
|
||||||
|
models.URLField(
|
||||||
|
help_text='Url where to send the verificable presentation',
|
||||||
|
max_length=250,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='OAuth2VPToken',
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
'id',
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name='ID',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
('created', models.DateTimeField(auto_now=True)),
|
||||||
|
('code', models.CharField(max_length=250)),
|
||||||
|
('result_verify', models.BooleanField(max_length=250)),
|
||||||
|
('presentation_definition', models.CharField(max_length=250)),
|
||||||
|
(
|
||||||
|
'authorization',
|
||||||
|
models.ForeignKey(
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to='oidc4vp.authorization',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'organization',
|
||||||
|
models.ForeignKey(
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='vp_tokens',
|
||||||
|
to='oidc4vp.organization',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'user',
|
||||||
|
models.ForeignKey(
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='vp_tokens',
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='authorization',
|
||||||
|
name='organization',
|
||||||
|
field=models.ForeignKey(
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='authorizations',
|
||||||
|
to='oidc4vp.organization',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='authorization',
|
||||||
|
name='user',
|
||||||
|
field=models.ForeignKey(
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,34 +1,80 @@
|
||||||
import requests
|
import requests
|
||||||
|
import secrets
|
||||||
|
|
||||||
from django.db import models
|
from django.conf import settings
|
||||||
from django.http import QueryDict
|
from django.http import QueryDict
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from idhub_auth.models import User
|
from idhub_auth.models import User
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
SALT_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||||
|
|
||||||
|
|
||||||
|
def gen_salt(length: int) -> str:
|
||||||
|
"""Generate a random string of SALT_CHARS with specified ``length``."""
|
||||||
|
if length <= 0:
|
||||||
|
raise ValueError("Salt length must be positive")
|
||||||
|
|
||||||
|
return "".join(secrets.choice(SALT_CHARS) for _ in range(length))
|
||||||
|
|
||||||
|
|
||||||
|
def set_client_id():
|
||||||
|
return gen_salt(24)
|
||||||
|
|
||||||
|
|
||||||
|
def set_client_secret():
|
||||||
|
return gen_salt(48)
|
||||||
|
|
||||||
|
|
||||||
|
def set_code():
|
||||||
|
return gen_salt(24)
|
||||||
|
|
||||||
|
|
||||||
class Organization(models.Model):
|
class Organization(models.Model):
|
||||||
|
"""
|
||||||
|
This class represent a member of one net trust or federated host
|
||||||
|
"""
|
||||||
name = models.CharField(max_length=250)
|
name = models.CharField(max_length=250)
|
||||||
client_id = models.CharField()
|
client_id = models.CharField(max_length=24, default=set_client_id)
|
||||||
client_secret = models.CharField()
|
client_secret = models.CharField(max_length=48, default=set_client_secret)
|
||||||
response_uri = models.URLField(
|
response_uri = models.URLField(
|
||||||
help_text=_("Url where to send the presentation"),
|
help_text=_("Url where to send the verificable presentation"),
|
||||||
max_length=250
|
max_length=250
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def send(self, vp):
|
||||||
|
"""
|
||||||
|
Send the verificable presentation to Verifier
|
||||||
|
"""
|
||||||
|
org = Organization.objects.get(
|
||||||
|
response_uri=settings.RESPONSE_URI
|
||||||
|
)
|
||||||
|
auth = (org.client_id, org.client_secret)
|
||||||
|
return requests.post(self.url, data=vp, auth=auth)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def send(self, vcred):
|
|
||||||
return requests.post(self.url, data=vcred)
|
###################
|
||||||
|
# Verifier clases #
|
||||||
|
###################
|
||||||
|
|
||||||
|
|
||||||
class Authorization(models.Model):
|
class Authorization(models.Model):
|
||||||
|
"""
|
||||||
|
This class represent a query through browser the client to the wallet.
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
code = models.CharField(max_length=24, default=set_code)
|
||||||
created = models.DateTimeField(auto_now=True)
|
created = models.DateTimeField(auto_now=True)
|
||||||
presentation_definition = models.CharField()
|
presentation_definition = models.CharField(max_length=250)
|
||||||
organization = models.ForeignKey(
|
organization = models.ForeignKey(
|
||||||
Organization,
|
Organization,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
related_name='vp_tokens',
|
related_name='authorizations',
|
||||||
null=True,
|
null=True,
|
||||||
)
|
)
|
||||||
user = models.ForeignKey(
|
user = models.ForeignKey(
|
||||||
|
@ -44,10 +90,10 @@ class Authorization(models.Model):
|
||||||
data = {
|
data = {
|
||||||
"response_type": "vp_token",
|
"response_type": "vp_token",
|
||||||
"response_mode": "direct_post",
|
"response_mode": "direct_post",
|
||||||
"client_id": "...",
|
"client_id": self.organization.client_id,
|
||||||
"response_uri": response_uri,
|
"response_uri": response_uri,
|
||||||
"presentation_definition": "...",
|
"presentation_definition": "...",
|
||||||
"nonce": ""
|
"nonce": gen_salt(5),
|
||||||
}
|
}
|
||||||
query_dict = QueryDict('', mutable=True)
|
query_dict = QueryDict('', mutable=True)
|
||||||
query_dict.update(data)
|
query_dict.update(data)
|
||||||
|
@ -56,12 +102,18 @@ class Authorization(models.Model):
|
||||||
response_uri=self.organization.response_uri,
|
response_uri=self.organization.response_uri,
|
||||||
params=query_dict.urlencode()
|
params=query_dict.urlencode()
|
||||||
)
|
)
|
||||||
|
return url
|
||||||
|
|
||||||
|
|
||||||
class OAuth2VPToken(models.Model):
|
class OAuth2VPToken(models.Model):
|
||||||
|
"""
|
||||||
|
This class represent the response of Wallet to Verifier
|
||||||
|
and the result of verify.
|
||||||
|
"""
|
||||||
created = models.DateTimeField(auto_now=True)
|
created = models.DateTimeField(auto_now=True)
|
||||||
response_code = models.CharField()
|
code = models.CharField(max_length=250)
|
||||||
result_verify = models.BooleanField()
|
result_verify = models.BooleanField(max_length=250)
|
||||||
presentation_definition = models.CharField()
|
presentation_definition = models.CharField(max_length=250)
|
||||||
organization = models.ForeignKey(
|
organization = models.ForeignKey(
|
||||||
Organization,
|
Organization,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
|
@ -74,4 +126,12 @@ class OAuth2VPToken(models.Model):
|
||||||
related_name='vp_tokens',
|
related_name='vp_tokens',
|
||||||
null=True,
|
null=True,
|
||||||
)
|
)
|
||||||
|
authorization = models.ForeignKey(
|
||||||
|
Authorization,
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
null=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
def verifing(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue