feat: link local library
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
from django.contrib import admin
|
||||
from django.contrib import messages
|
||||
from django.db import IntegrityError
|
||||
|
||||
from .models import OnBoardingRegistration
|
||||
from spid_cie_oidc.authority.models import FederationDescendant, FederationDescendantContact
|
||||
|
||||
|
||||
@admin.register(OnBoardingRegistration)
|
||||
class OnBoardingRegistrationAdmin(admin.ModelAdmin):
|
||||
|
||||
@admin.action(description='enable descendant')
|
||||
def enable_as_descendant(modeladmin, request, queryset):
|
||||
for entity_onboarded in queryset:
|
||||
name = entity_onboarded.organization_name
|
||||
sub = entity_onboarded.url_entity
|
||||
jwks = entity_onboarded.public_jwks
|
||||
_type = entity_onboarded.type
|
||||
contact = entity_onboarded.contact
|
||||
|
||||
try:
|
||||
entity = FederationDescendant.objects.create(
|
||||
name = name,
|
||||
sub = sub,
|
||||
type = _type,
|
||||
jwks = jwks,
|
||||
is_active = True,
|
||||
status = "valid"
|
||||
)
|
||||
FederationDescendantContact.objects.create(
|
||||
entity = entity,
|
||||
contact = contact,
|
||||
type = "email"
|
||||
)
|
||||
entity_onboarded.status = "onboarded"
|
||||
entity_onboarded.save()
|
||||
except IntegrityError: # pragma: no cover
|
||||
messages.error(request, f"Already exists a descendant with subject: {sub}")
|
||||
|
||||
list_display = (
|
||||
"organization_name",
|
||||
"url_entity",
|
||||
"type",
|
||||
"authn_buttons_page_url",
|
||||
"public_jwks",
|
||||
)
|
||||
actions = [enable_as_descendant]
|
||||
@@ -0,0 +1,8 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class SpidCieOidcOnboardingConfig(AppConfig):
|
||||
default_auto_field = "django.db.models.BigAutoField"
|
||||
name = "spid_cie_oidc.onboarding"
|
||||
verbose_name = "SPID/CIE OIDC Federation OnBoarding"
|
||||
label = "spid_cie_oidc_onboarding"
|
||||
@@ -0,0 +1,134 @@
|
||||
import logging
|
||||
from django import forms
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from spid_cie_oidc.entity.validators import validate_public_jwks
|
||||
from spid_cie_oidc.authority.validators import validate_entity_configuration
|
||||
from .validators import unique_entity_url
|
||||
from spid_cie_oidc.entity.models import ENTITY_TYPES
|
||||
from django.conf import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
try:
|
||||
OIDCFED_TRUST_ANCHORS = getattr(
|
||||
settings, "OIDCFED_TRUST_ANCHORS"
|
||||
)
|
||||
except AttributeError: # pragma: no cover
|
||||
OIDCFED_TRUST_ANCHORS = []
|
||||
logger.warning(
|
||||
"OIDCFED_TRUST_ANCHORS not configured in your settings file."
|
||||
)
|
||||
|
||||
|
||||
class OnboardingRegistrationForm(forms.Form):
|
||||
|
||||
organization_name = forms.CharField(
|
||||
initial="",
|
||||
label=_("Organization Name"),
|
||||
error_messages={"required": _("Enter your organization name")},
|
||||
)
|
||||
|
||||
url_entity = forms.URLField(
|
||||
initial="",
|
||||
label=_("Entity URL"),
|
||||
error_messages={"required": _("Enter the entity unique identifier (HTTP URL)")},
|
||||
validators=[validate_entity_configuration, unique_entity_url],
|
||||
)
|
||||
|
||||
authn_buttons_page_url = forms.URLField(
|
||||
initial="",
|
||||
label=_("URL of the login page, if available"),
|
||||
error_messages={
|
||||
"required": _(
|
||||
"Enter the url of the page where the SPID/CIE button is available"
|
||||
)
|
||||
},
|
||||
required=False,
|
||||
)
|
||||
|
||||
auth_request_url = forms.CharField(
|
||||
initial="",
|
||||
label=_("Authentication request URL, if available"),
|
||||
required = False
|
||||
)
|
||||
|
||||
contact = forms.EmailField(
|
||||
initial="",
|
||||
label=_("Contact email"),
|
||||
error_messages={"required": _("Enter your contact email")},
|
||||
)
|
||||
|
||||
type = forms.ChoiceField(
|
||||
choices=[(i, i) for i in ENTITY_TYPES],
|
||||
label="",
|
||||
error_messages={"required": _("Select a entity type")},
|
||||
)
|
||||
|
||||
public_jwks = forms.JSONField(
|
||||
initial=list,
|
||||
label=_("Public Federation JWKs"),
|
||||
error_messages={
|
||||
"required": _(
|
||||
"Enter the public JWKs published in your Entity Configuration, "
|
||||
"as double check."
|
||||
)
|
||||
},
|
||||
validators=[validate_public_jwks],
|
||||
)
|
||||
|
||||
|
||||
class OnboardingCreateTrustChain(forms.Form):
|
||||
|
||||
sub = forms.URLField(
|
||||
initial="",
|
||||
label=_("url of subject"),
|
||||
error_messages={"required": _("Enter the subject")},
|
||||
)
|
||||
|
||||
type = forms.ChoiceField(
|
||||
choices=[(i, i) for i in ENTITY_TYPES],
|
||||
label="OpenID Connect Federation entity type",
|
||||
error_messages={"required": _("Select a entity type")},
|
||||
)
|
||||
|
||||
trust_anchor = forms.ChoiceField(
|
||||
choices=[(i, i) for i in OIDCFED_TRUST_ANCHORS],
|
||||
label=_("url of the trust anchor"),
|
||||
error_messages={"required": _("Enter the url of trust anchor")},
|
||||
)
|
||||
|
||||
|
||||
class OnboardingValidatingTrustMarkForm(forms.Form):
|
||||
|
||||
sub = forms.URLField(
|
||||
initial="",
|
||||
label=_("Url of subject"),
|
||||
required=False
|
||||
)
|
||||
|
||||
id = forms.URLField(
|
||||
initial="",
|
||||
label=_("Id"),
|
||||
required=False
|
||||
)
|
||||
|
||||
trust_mark = forms.CharField(
|
||||
initial = "",
|
||||
label=_("Enter trust mark"),
|
||||
required=False
|
||||
)
|
||||
|
||||
|
||||
class OnboardingDecodeForm(forms.Form):
|
||||
|
||||
jwt = forms.CharField(
|
||||
initial="",
|
||||
label=_("jwt"),
|
||||
error_messages={"required": _("Enter a jwt")},
|
||||
)
|
||||
|
||||
jwk = forms.JSONField(
|
||||
initial=dict,
|
||||
label=_("jwk"),
|
||||
required=False,
|
||||
)
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
# Generated by Django 4.0.2 on 2022-02-22 08:39
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import spid_cie_oidc.entity.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="OnBoardingRegistration",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"organization_name",
|
||||
models.CharField(help_text="Organization Name. ", max_length=254),
|
||||
),
|
||||
(
|
||||
"url_entity",
|
||||
models.URLField(
|
||||
help_text="URL of the Entity.", max_length=254, unique=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"authn_buttons_page_url",
|
||||
models.URLField(
|
||||
help_text="URL of the page where the SPID/CIE button is available.",
|
||||
max_length=254,
|
||||
),
|
||||
),
|
||||
(
|
||||
"public_jwks",
|
||||
models.JSONField(
|
||||
default=dict,
|
||||
help_text="Public jwks of the Entities",
|
||||
validators=[
|
||||
spid_cie_oidc.entity.validators.validate_public_jwks
|
||||
],
|
||||
),
|
||||
),
|
||||
(
|
||||
"status",
|
||||
models.CharField(
|
||||
choices=[
|
||||
("onboarded", "onboarded"),
|
||||
("failed", "failed"),
|
||||
("processing", "processing"),
|
||||
("caquired", "acquired"),
|
||||
],
|
||||
default="acquired",
|
||||
max_length=33,
|
||||
),
|
||||
),
|
||||
(
|
||||
"created_by",
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "OnBoarding Registration",
|
||||
"verbose_name_plural": "OnBoarding Registrations",
|
||||
},
|
||||
),
|
||||
]
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
# Generated by Django 4.0.2 on 2022-02-23 12:23
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("spid_cie_oidc_onboarding", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name="onboardingregistration",
|
||||
options={
|
||||
"ordering": ["created"],
|
||||
"verbose_name": "OnBoarding Registration",
|
||||
"verbose_name_plural": "OnBoarding Registrations",
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="onboardingregistration",
|
||||
name="created",
|
||||
field=models.DateTimeField(
|
||||
auto_now_add=True, default=django.utils.timezone.now
|
||||
),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="onboardingregistration",
|
||||
name="modified",
|
||||
field=models.DateTimeField(auto_now=True),
|
||||
),
|
||||
]
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
# Generated by Django 4.0.2 on 2022-02-25 16:04
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
(
|
||||
"spid_cie_oidc_onboarding",
|
||||
"0002_alter_onboardingregistration_options_and_more",
|
||||
),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name="onboardingregistration",
|
||||
options={
|
||||
"ordering": ["-created"],
|
||||
"verbose_name": "OnBoarding Registration",
|
||||
"verbose_name_plural": "OnBoarding Registrations",
|
||||
},
|
||||
),
|
||||
]
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 4.0.2 on 2022-03-11 13:16
|
||||
|
||||
from django.db import migrations, models
|
||||
import spid_cie_oidc.entity.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('spid_cie_oidc_onboarding', '0003_alter_onboardingregistration_options'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='onboardingregistration',
|
||||
name='public_jwks',
|
||||
field=models.JSONField(default=list, help_text='Public jwks of the Entities', validators=[spid_cie_oidc.entity.validators.validate_public_jwks]),
|
||||
),
|
||||
]
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.0.2 on 2022-03-16 16:08
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('spid_cie_oidc_onboarding', '0004_alter_onboardingregistration_public_jwks'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='onboardingregistration',
|
||||
name='status',
|
||||
field=models.CharField(choices=[('onboarded', 'onboarded'), ('failed', 'failed'), ('processing', 'processing'), ('acquired', 'acquired')], default='acquired', max_length=33),
|
||||
),
|
||||
]
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.0.2 on 2022-03-18 17:28
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('spid_cie_oidc_onboarding', '0005_alter_onboardingregistration_status'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='onboardingregistration',
|
||||
name='type',
|
||||
field=models.CharField(blank=True, choices=[('federation_entity', 'federation_entity'), ('openid_relying_party', 'openid_relying_party'), ('openid_provider', 'openid_provider'), ('oauth_resource', 'oauth_resource')], default='openid_relying_party', help_text='OpenID Connect Federation entity type', max_length=33),
|
||||
),
|
||||
]
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
# Generated by Django 4.0.2 on 2022-03-22 16:50
|
||||
|
||||
import datetime
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('spid_cie_oidc_onboarding', '0006_onboardingregistration_type'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='onboardingregistration',
|
||||
name='contact',
|
||||
field=models.CharField(default=datetime.date(2022, 3, 22), help_text='any kind of contact type, usually an email.', max_length=255),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.0.3 on 2022-03-28 13:18
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('spid_cie_oidc_onboarding', '0007_onboardingregistration_contact'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='onboardingregistration',
|
||||
name='auth_request_url',
|
||||
field=models.CharField(blank=True, help_text='SPID/CIE authentication request trigger url.', max_length=254, null=True),
|
||||
),
|
||||
]
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
# Generated by Django 4.2.1 on 2023-07-09 15:44
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("spid_cie_oidc_onboarding", "0008_onboardingregistration_auth_request_url"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="onboardingregistration",
|
||||
name="type",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
choices=[
|
||||
("federation_entity", "federation_entity"),
|
||||
("openid_relying_party", "openid_relying_party"),
|
||||
("openid_provider", "openid_provider"),
|
||||
("oauth_resource", "oauth_resource"),
|
||||
("wallet_provider", "wallet_provider"),
|
||||
("wallet_relying_party", "wallet_relying_party"),
|
||||
],
|
||||
default="openid_relying_party",
|
||||
help_text="OpenID Connect Federation entity type",
|
||||
max_length=33,
|
||||
),
|
||||
),
|
||||
]
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
# Generated by Django 4.2.7 on 2023-11-14 14:07
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("spid_cie_oidc_onboarding", "0009_alter_onboardingregistration_type"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="onboardingregistration",
|
||||
name="type",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
choices=[
|
||||
("federation_entity", "federation_entity"),
|
||||
("openid_relying_party", "openid_relying_party"),
|
||||
("openid_provider", "openid_provider"),
|
||||
("openid_credential_issuer", "openid_credential_issuer"),
|
||||
("oauth_resource", "oauth_resource"),
|
||||
("wallet_provider", "wallet_provider"),
|
||||
("wallet_relying_party", "wallet_relying_party"),
|
||||
],
|
||||
default="openid_relying_party",
|
||||
help_text="OpenID Connect Federation entity type",
|
||||
max_length=33,
|
||||
),
|
||||
),
|
||||
]
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.0.5 on 2026-03-23 15:42
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('spid_cie_oidc_onboarding', '0010_alter_onboardingregistration_type'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='onboardingregistration',
|
||||
name='type',
|
||||
field=models.CharField(blank=True, choices=[('federation_entity', 'federation_entity'), ('openid_relying_party', 'openid_relying_party'), ('openid_provider', 'openid_provider'), ('openid_credential_issuer', 'openid_credential_issuer'), ('oauth_resource', 'oauth_resource'), ('wallet_provider', 'wallet_provider'), ('openid_credential_verifier', 'openid_credential_verifier')], default='openid_relying_party', help_text='OpenID Connect Federation entity type', max_length=33),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,81 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from spid_cie_oidc.entity.abstract_models import TimeStampedModel
|
||||
from spid_cie_oidc.entity.validators import validate_public_jwks
|
||||
from spid_cie_oidc.entity.models import ENTITY_TYPES
|
||||
|
||||
|
||||
class OnBoardingRegistration(TimeStampedModel):
|
||||
|
||||
organization_name = models.CharField(
|
||||
max_length=254, help_text=_("Organization Name. ")
|
||||
)
|
||||
|
||||
url_entity = models.URLField(
|
||||
max_length=254,
|
||||
blank=False,
|
||||
null=False,
|
||||
unique=True,
|
||||
help_text=_("URL of the Entity."),
|
||||
)
|
||||
|
||||
authn_buttons_page_url = models.URLField(
|
||||
max_length=254,
|
||||
blank=False,
|
||||
null=False,
|
||||
help_text=_("URL of the page where the SPID/CIE button is available."),
|
||||
)
|
||||
|
||||
auth_request_url = models.CharField(
|
||||
max_length=254,
|
||||
blank=True,
|
||||
null= True,
|
||||
help_text=_("SPID/CIE authentication request trigger url."),
|
||||
)
|
||||
|
||||
public_jwks = models.JSONField(
|
||||
blank=False,
|
||||
help_text=_("Public jwks of the Entities"),
|
||||
default=list,
|
||||
validators=[validate_public_jwks],
|
||||
)
|
||||
|
||||
type = models.CharField(
|
||||
max_length=33,
|
||||
blank=True,
|
||||
default="openid_relying_party",
|
||||
choices=[(i, i) for i in ENTITY_TYPES],
|
||||
help_text=_("OpenID Connect Federation entity type"),
|
||||
)
|
||||
|
||||
contact = models.CharField(
|
||||
max_length=255,
|
||||
blank=False,
|
||||
null=False,
|
||||
help_text=_("any kind of contact type, usually an email."),
|
||||
)
|
||||
|
||||
status = models.CharField(
|
||||
max_length=33,
|
||||
choices=(
|
||||
("onboarded", "onboarded"),
|
||||
("failed", "failed"),
|
||||
("processing", "processing"),
|
||||
("acquired", "acquired"),
|
||||
),
|
||||
default="acquired",
|
||||
)
|
||||
|
||||
created_by = models.ForeignKey(
|
||||
get_user_model(), blank=True, null=True, on_delete=models.PROTECT
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "OnBoarding Registration"
|
||||
verbose_name_plural = "OnBoarding Registrations"
|
||||
ordering = ["-created"]
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.organization_name} {self.url_entity}"
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
+10
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="500px" height="500px" viewBox="0 0 500 500" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>logo-it-2021</title>
|
||||
<g id="logo-it-2021" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Group">
|
||||
<rect id="Rectangle" fill="#0066CC" x="0" y="0" width="500" height="500"/>
|
||||
<path d="M362.336089,118.811881 L362.336089,174.651845 L410.541772,174.651845 L410.541772,220.827199 L361.986773,220.827199 L361.986773,303.513298 C361.986773,311.746114 362.336089,317.115341 362.685406,320.694825 C363.034723,323.916362 364.43199,326.77995 366.877205,329.28559 C369.322421,331.791228 373.164903,332.865075 378.40465,332.865075 L408.445874,332.149178 L410.891089,375.102995 C393.425261,379.040428 379.801917,381.188119 370.719686,381.188119 C346.966162,381.188119 330.897601,375.818892 322.514004,364.722489 C313.781091,353.984035 309.589292,333.93892 309.589292,304.587145 L309.589292,118.811881 L362.336089,118.811881 Z M255.958929,178.442844 L255.958929,375.225023 L202.328566,375.225023 L202.328566,178.442844 L255.958929,178.442844 Z M121.883022,166.516652 C131.351098,166.516652 139.362548,169.707713 145.553213,176.089838 C151.743878,182.471963 154.657132,190.272338 154.657132,199.845526 C154.657132,209.418712 151.743878,216.864525 145.553213,223.24665 C139.726703,228.919649 132.079412,232.110711 122.247179,232.110711 C112.779102,232.110711 104.767652,228.919649 98.5769872,222.537524 C92.386322,216.155399 89.1089109,208.355025 89.1089109,199.1364 C89.1089109,189.917776 92.386322,182.117401 98.2128302,175.735276 C104.403495,169.353151 112.414945,166.516652 121.883022,166.516652 Z" id="Combined-Shape-Copy-2" fill="#FFFFFF"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,202 @@
|
||||
<!-- Extends default Bootstrap Unical Italia template -->
|
||||
{% extends 'bootstrap-italia-base.html' %}
|
||||
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block extra_head %}
|
||||
{{ block.super }}
|
||||
{% endblock extra_head %}
|
||||
|
||||
{% block page_title %}
|
||||
{% trans "OIDC Federation onboarding system" %}
|
||||
{% endblock page_title %}
|
||||
|
||||
<!-- URL link top left -->
|
||||
{% block header_slim_org_url %}
|
||||
https://www.spid.gov.it/
|
||||
{% endblock header_slim_org_url %}
|
||||
|
||||
<!-- Name top left -->
|
||||
{% block header_slim_org_name %}
|
||||
{% trans "OIDC Federation onboarding system" %}
|
||||
{% endblock header_slim_org_name %}
|
||||
|
||||
<!-- Mobile slim_org_name -->
|
||||
{% block header_slim_mobile_org_name %}
|
||||
{% trans "OIDC Federation onboarding system" %}
|
||||
{% endblock header_slim_mobile_org_name %}
|
||||
|
||||
<!-- Make empty areas -->
|
||||
{% block header_mobile_arrow %}{% endblock header_mobile_arrow %}
|
||||
{% block header_mobile_slim_menu %}{% endblock header_mobile_slim_menu %}
|
||||
|
||||
<!-- Logo in Header -->
|
||||
{% block header_center_logo %}
|
||||
{% endblock header_center_logo %}
|
||||
|
||||
<!-- Organization name in Header -->
|
||||
{% block header_center_org_name %}
|
||||
{% trans "OIDC Federation onboarding system" %}
|
||||
{% endblock header_center_org_name %}
|
||||
|
||||
<!-- Organization description in Header -->
|
||||
{% block header_center_org_subname %}
|
||||
{% trans "OIDC Federation onboarding system" %}
|
||||
{% endblock header_center_org_subname %}
|
||||
|
||||
|
||||
{% block menu_links %}
|
||||
|
||||
<li class="nav-item ">
|
||||
<a class="nav-link {% if request.resolver_match.view_name == 'oidc_onboarding_landing' %}active{% endif %}"
|
||||
href="{% url 'oidc_onboarding_landing' %}">
|
||||
<span>{% trans 'Home' %}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if request.resolver_match.view_name == 'oidc_onboarding_entities' %}active{% endif %}"
|
||||
href="{% url 'oidc_onboarding_entities' %}">
|
||||
<span>{% trans 'Entities onboarded' %}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if request.resolver_match.view_name == 'oidc_onboarding_registration' %}active{% endif %}"
|
||||
href="{% url 'oidc_onboarding_registration' %}">
|
||||
<span>{% trans 'Register your entity' %}</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
<li class="nav-item dropdown megamenu">
|
||||
<a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-expanded="true">
|
||||
<span>Tools</span>
|
||||
<svg class="icon icon-m">
|
||||
<use xlink:href="/static/svg/sprite.svg#it-expand"></use>
|
||||
</svg>
|
||||
</a>
|
||||
<div class="dropdown-menu">
|
||||
<div class="row">
|
||||
<div class="col-12 col-lg-4">
|
||||
<div class="link-list-wrapper">
|
||||
<ul class="link-list">
|
||||
<li>
|
||||
<h3 class="no_toc">JWK</h3>
|
||||
</li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_create_jwk'%}">
|
||||
<span>{% trans "Create a jwk" %}</span></a></li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_convert_jwk'%}?type=private">
|
||||
<span>{% trans "Convert a private JWK to PEM" %}</span></a></li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_convert_jwk'%}?type=public">
|
||||
<span>{% trans "Convert a public JWK to PEM" %}</span></a></li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_convert_pem'%}?type=private">
|
||||
<span>{% trans "Convert a private PEM to JWK" %}</span></a></li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_convert_pem'%}?type=public">
|
||||
<span>{% trans "Convert a public PEM to JWK" %}</span></a></li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_tools_decode_jwt' %}">
|
||||
<span>{% trans "JWT decode and verification" %}</span></a></li>
|
||||
<li>
|
||||
<h3 class="no_toc">Utils</h3>
|
||||
</li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_resolve_statement' %}">
|
||||
<span>{% trans "Resolve entity statement" %}</span></a></li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_tools_apply_policy' %}">
|
||||
<span>{% trans "Apply policy" %}</span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-4">
|
||||
<div class="link-list-wrapper">
|
||||
<ul class="link-list">
|
||||
<li>
|
||||
<h3 class="no_toc">VALIDATORS</h3>
|
||||
</li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_validate_md' %}?metadata_type=op_metadata&provider_profile=spid">
|
||||
<span>{% trans "Validate OP metadata spid" %}</span></a></li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_validate_md' %}?metadata_type=op_metadata&provider_profile=cie">
|
||||
<span>{% trans "Validate OP metadata cie" %}</span></a></li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_validate_md' %}?metadata_type=rp_metadata&provider_profile=spid">
|
||||
<span>{% trans "Validate RP metadata spid" %}</span></a></li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_validate_md' %}?metadata_type=rp_metadata&provider_profile=cie">
|
||||
<span>{% trans "Validate RP metadata cie" %}</span></a></li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_validate_authn_request_jwt'%}?provider_profile=spid">
|
||||
<span>{% trans "Validate Authn Request spid" %}</span></a></li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_validate_authn_request_jwt'%}?provider_profile=cie">
|
||||
<span>{% trans "Validate Authn Request cie" %}</span></a></li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_validate_ec' %}">
|
||||
<span>{% trans "Validate Entity Configuration" %}</span></a></li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_validating_trustmark' %}">
|
||||
<span>{% trans "Trust mark validation" %}</span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-4">
|
||||
<div class="link-list-wrapper">
|
||||
<ul class="link-list">
|
||||
<li>
|
||||
<h3 class="no_toc">{% trans "Schemas" %}</h3>
|
||||
</li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_schemas_federation_entity' %}">
|
||||
<span>Federation Entity Endpoint</span></a></li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_schemas_Authorization' %}">
|
||||
<span>Authorization Endpoint</span></a></li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_schemas_introspection' %}">
|
||||
<span>Introspection Endpoint</span></a></li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_schemas_metadata' %}">
|
||||
<span>Metadata</span></a></li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_schemas_token' %}">
|
||||
<span>Token Endpoint</span></a></li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_schemas_revocation' %}">
|
||||
<span>Revocation Endpoint</span></a></li>
|
||||
<li><a class="list-item" href="{% url 'oidc_onboarding_schemas_jwt_client_assertion' %}">
|
||||
<span>Jwt client Assertion</span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endblock menu_links %}
|
||||
|
||||
{% block container %}
|
||||
<div>
|
||||
<div class="container pt-2 p-3">
|
||||
<div class="row d-lg-flex">
|
||||
<div class="col-12">
|
||||
<div class="card-wrapper card-space">
|
||||
<div class="card card-bg no-after">
|
||||
<div class="card-body pl-lg-0">
|
||||
<div class="row h-100">
|
||||
{% block centered_container %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock container %}
|
||||
|
||||
<!-- Logo in Footer -->
|
||||
{% block footer_logo %}
|
||||
{% endblock footer_logo %}
|
||||
|
||||
<!-- Organization name in Footer -->
|
||||
{% block footer_org_name %}
|
||||
{% trans "OIDC Federation onboarding system" %}
|
||||
{% endblock footer_org_name %}
|
||||
|
||||
<!-- Organization name in Footer -->
|
||||
{% block footer_org_subname %}
|
||||
{% trans "OIDC Federation onboarding system" %}
|
||||
{% endblock footer_org_subname %}
|
||||
|
||||
{% block extra_scripts %}
|
||||
{% block bootstrap_italia_validation %}
|
||||
|
||||
{% endblock bootstrap_italia_validation %}
|
||||
{% endblock extra_scripts %}
|
||||
|
||||
{% block footer_menu_section %}
|
||||
{% endblock footer_menu_section %}
|
||||
Vendored
+65
@@ -0,0 +1,65 @@
|
||||
<!-- Extends default Bootstrap Unical Italia template -->
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block centered_container %}
|
||||
|
||||
<div class="col-12 pl-lg-4">
|
||||
|
||||
<h4 class="text-left">
|
||||
{% trans "Apply policy" %}
|
||||
</h4>
|
||||
|
||||
<p class="card-title">
|
||||
{% trans "Adheres a metadata policy to a metadata statement" %}
|
||||
</p>
|
||||
<form method="get" action="">
|
||||
{% csrf_token %}
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
|
||||
<div class="form-row">
|
||||
<div class="col-12 form-group my-3">
|
||||
<label for="id_md">
|
||||
<span class="form-label-content">
|
||||
metadata statement
|
||||
</span>
|
||||
</label>
|
||||
<textarea id="id_md" rows="9"
|
||||
name="md">{{ md }}</textarea>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="col-12 form-group my-3">
|
||||
<label for="id_policy">
|
||||
<span class="form-label-content">
|
||||
metadata policy
|
||||
</span>
|
||||
</label>
|
||||
<textarea id="id_policy" rows="5"
|
||||
name="policy">{{ policy }}</textarea>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
|
||||
<div class="form-row">
|
||||
<div class="col-12 form-group my-3">
|
||||
<label for="id_result">
|
||||
<span class="form-label-content">
|
||||
result
|
||||
</span>
|
||||
</label>
|
||||
<textarea id="id_result" rows="16" disabled
|
||||
name="result">{{ result }}</textarea>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input type="submit" name="decode" class="btn btn-lg btn-primary btn-block"
|
||||
value="{% trans 'apply' %}" />
|
||||
</form>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
<!-- Extends default Bootstrap Unical Italia template -->
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block centered_container %}
|
||||
|
||||
<div class="col-12 pl-lg-4">
|
||||
|
||||
<h4 class="text-left">
|
||||
{% trans "Convert jwk to pem" %}
|
||||
</h4>
|
||||
|
||||
<p class="card-title">
|
||||
{% trans "Enter a jwk in the field below to encode it in PEM format." %}
|
||||
</p>
|
||||
<form method="post" action="">
|
||||
{% csrf_token %}
|
||||
<div class="form-row">
|
||||
<div class="col-12 form-group my-3">
|
||||
<label for="id_jwk">
|
||||
<span class="form-label-content">
|
||||
Jwk
|
||||
</span>
|
||||
</label>
|
||||
<textarea id="id_jwk" rows="12" name="jwk">{{ jwk }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
{% if pem %}
|
||||
<h4 class="text-left">
|
||||
{% if jwk_type == 'private' %}
|
||||
{% trans "Private key" %}
|
||||
{% else %}
|
||||
{% trans "Public key" %}
|
||||
{% endif %}
|
||||
</h4>
|
||||
<div class="form-row">
|
||||
<div class="col-12 form-group my-3">
|
||||
<textarea id="private_pem" rows="13" name="private_pem">{{ pem }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<input type="submit" name="confirm" class="btn btn-lg btn-success btn-block"
|
||||
value="{% trans 'Convert to pem' %}" />
|
||||
</form>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
<!-- Extends default Bootstrap Unical Italia template -->
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block centered_container %}
|
||||
|
||||
<div class="col-12 pl-lg-4">
|
||||
|
||||
<h4 class="text-left">
|
||||
{% if pem_type == 'private' %}
|
||||
{% trans "Convert private pem to jwk" %}
|
||||
{% else %}
|
||||
{% trans "Convert Public pem to jwk" %}
|
||||
{% endif %}
|
||||
</h4>
|
||||
|
||||
<p class="card-title">
|
||||
{% trans "Enter a pem in the field below to decode it in jwk format." %}
|
||||
</p>
|
||||
<form method="post" action="">
|
||||
{% csrf_token %}
|
||||
<div class="form-row">
|
||||
<div class="col-12 form-group my-3">
|
||||
<label for="id_pem">
|
||||
<span class="form-label-content">
|
||||
Pem
|
||||
</span>
|
||||
</label>
|
||||
<textarea id="id_pem" rows="12" name="pem">{{ pem }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
{% if jwk %}
|
||||
<h4 class="text-left">
|
||||
{% if pem_type == 'private' %}
|
||||
{% trans "Private pem" %}
|
||||
{% else %}
|
||||
{% trans "Public pem" %}
|
||||
{% endif %}
|
||||
</h4>
|
||||
<div class="form-row">
|
||||
<div class="col-12 form-group my-3">
|
||||
<textarea id="jwk" rows="13" name="jwk">{{ jwk }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<input type="submit" name="confirm" class="btn btn-lg btn-success btn-block"
|
||||
value="{% trans 'Convert to jwk' %}" />
|
||||
</form>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
<!-- Extends default Bootstrap Unical Italia template -->
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block centered_container %}
|
||||
|
||||
<div class="col-12 pl-lg-4">
|
||||
|
||||
<h4 class="text-left">
|
||||
{% trans "JWT decode and verification" %}
|
||||
</h4>
|
||||
|
||||
<p class="card-title">
|
||||
{% trans "Submit a jwt to decode it, if you submit also a jwk you'll decrypt or verify it." %}
|
||||
</p>
|
||||
<form method="post" action="">
|
||||
{% csrf_token %}
|
||||
<div class="row">
|
||||
<div class="col-12 col-lg-7">
|
||||
{% csrf_token %}
|
||||
{% for form_field in form %}
|
||||
<div class="form-row">
|
||||
{% if form_field.name == 'jwt' %}
|
||||
<div class="col-12 form-group my-3">
|
||||
<label for="id_{{ form_field.html_name }}">
|
||||
<span class="form-label-content">
|
||||
{{ form_field.label }}
|
||||
</span>
|
||||
</label>
|
||||
<textarea id="id_{{ form_field.html_name }}" rows="14"
|
||||
name="{{ form_field.name }}">{{ form.jwt.value}}</textarea>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="col-12 form-group my-3">
|
||||
<label for="id_{{ form_field.html_name }}">
|
||||
<span class="form-label-content mt-4">
|
||||
{{ form_field.label }}
|
||||
</span>
|
||||
</label>
|
||||
<textarea id="id_{{ form_field.html_name }}" rows="6"
|
||||
name="{{ form_field.name }}">{{ form.jwk.value }}</textarea>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
<span for="id_{{ form_field.html_name }}" class="text-danger">{{ form_field.errors }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="col-12 col-lg-5">
|
||||
<div class="form-row">
|
||||
<div class="col-12 form-group my-3">
|
||||
<label for="id_head">
|
||||
<span class="form-label-content">
|
||||
Head
|
||||
</span>
|
||||
</label>
|
||||
<textarea id="id_head" rows="6" name="head">{{ head }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="col-12 form-group my-2">
|
||||
<label for="id_payload">
|
||||
Payload
|
||||
</label>
|
||||
<textarea id="id_payload" rows="12" name="payload">{{ payload }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<input type="submit" name="decode" class="btn btn-lg btn-success btn-block"
|
||||
value="{% trans 'decode or verify' %}" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
<!-- Extends default Bootstrap Unical Italia template -->
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
|
||||
{% block centered_container %}
|
||||
<div class="col-12 pl-lg-4">
|
||||
<h4 class="text-left">
|
||||
{% trans "Entities onboarded"%}
|
||||
</h4>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col">{% trans "organization name" %}</th>
|
||||
<th scope="col">{% trans "url entity" %}</th>
|
||||
<th scope="col">{% trans "status" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for entity in entities %}
|
||||
<tr>
|
||||
<th scope="row">{{ forloop.counter }}</th>
|
||||
<td>{{ entity.organization_name }}</td>
|
||||
<td>{{ entity.url_entity }}</td>
|
||||
{% if entity.status == 'processing' %}
|
||||
<td class="complementary-2-color-b1">{{ entity.status }}</td>
|
||||
{% elif entity.status == 'failed' %}
|
||||
<td class="text-danger">{{ entity.status }}</td>
|
||||
{% elif entity.status == 'onboarded' %}
|
||||
<td class="analogue-2-color-b2">{{ entity.status }}</td>
|
||||
{% else %}
|
||||
<td class="text-secondary">{{ entity.status }}</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<nav class="pagination-wrapper justify-content-center">
|
||||
<ul class="pagination">
|
||||
{% if entities.has_previous %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{entities.previous_page_number}}" tabindex="-1" aria-hidden="true">
|
||||
<svg class="icon icon-primary">
|
||||
<use href="{% static 'svg/sprite.svg' %}#it-chevron-left"></use>
|
||||
</svg>
|
||||
<span class="sr-only">{% trans "previous page" %}</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% for i in entities.paginator.page_range%}
|
||||
{% if i == entities.number %}
|
||||
<li class="page-item active">
|
||||
<a class="page-link" href="?page={{ i }}" aria-current="page">
|
||||
<span class="d-inline-block d-sm-none">{% trans "page" %}</span>{{ i }}
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="page-item"><a class="page-link" href="?page={{ i }}">{{ i }}</a></li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if entities.has_next%}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{entities.next_page_number}}">
|
||||
<span class="sr-only">{% trans "next page" %}</span>
|
||||
<svg class="icon icon-primary">
|
||||
<use href="{% static 'svg/sprite.svg' %}#it-chevron-right"></use>
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
<!-- Extends default Bootstrap Unical Italia template -->
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block centered_container %}
|
||||
<div class="col-12 pl-lg-4">
|
||||
<h4 class="text-left">
|
||||
{% trans "Create a JWK" %}
|
||||
</h4>
|
||||
|
||||
<p class="pt-4 mb-0">
|
||||
{% trans "In this page you have a brand new JWK. Refresh the page to gent another one." %}
|
||||
</p>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="col-12 form-group my-3">
|
||||
<textarea id="jwk" rows="14" name="jwk">{{ private_jwk }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="pt-4 mb-0">
|
||||
{% trans "Here the public version of the previous private JWK." %}
|
||||
</p>
|
||||
<div class="form-row">
|
||||
<div class="col-12 form-group my-3">
|
||||
<textarea id="jwk" rows="14" name="jwk">{{ public_jwk }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
<!-- Extends default Bootstrap Unical Italia template -->
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
|
||||
|
||||
{% block container %}
|
||||
<div>
|
||||
<div class="container pt-2 p-3">
|
||||
<div class="d-lg-flex">
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<div class="card-wrapper card-space col-6">
|
||||
<div class="card card-bg no-after">
|
||||
<div class="card-body pl-lg-0">
|
||||
<div class="h-100">
|
||||
<div class="col-12">
|
||||
<div class="img-responsive-wrapper d-none d-lg-block h-100">
|
||||
<div class="img-responsive img-responsive-panoramic h-100 ml-4 mt-2">
|
||||
<figure class="img-wrapper">
|
||||
<img alt="superman" class="h-100" src="{% static 'images/SPID-e-CIE-696x383.jpg' %}" title="spid-cie">
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-wrapper card-space col-6">
|
||||
<div class="card card-bg no-after">
|
||||
<div class="card-body pl-lg-0">
|
||||
<div class="row h-100">
|
||||
<div class="col-12 pl-lg-4">
|
||||
|
||||
<div class="row m-2">
|
||||
<h4 class="text-left">
|
||||
{% trans "Welcome" %}
|
||||
</h4>
|
||||
|
||||
|
||||
<p class="card-title">
|
||||
{% blocktrans %}
|
||||
The SPID/CIE onboarding demostration system wants to exemplify what
|
||||
information is required to
|
||||
register and test a leaf entity within the OIDC Federation.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
|
||||
<p class="card-title">
|
||||
{% blocktrans %}
|
||||
In this demonstration consider that you are registering your RP or OP to a Federation Authority.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="row mt-3">
|
||||
<div class="col">
|
||||
<span class="badge" style="font-size: 100%">
|
||||
<a href="{% url 'oidc_onboarding_entities' %}" class="btn btn-secondary btn-block">
|
||||
{% trans "Show accredited entities" %}
|
||||
</a>
|
||||
</span>
|
||||
<span class="badge mb-3 mr-2 ml-0 pr-10 p-2 mw-100" style="font-size: 100%">
|
||||
<a href="{% url 'oidc_onboarding_registration' %}" class="btn btn-primary btn-block">
|
||||
{% trans "Register your entity" %}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock container %}
|
||||
Vendored
+59
@@ -0,0 +1,59 @@
|
||||
<!-- Extends default Bootstrap Unical Italia template -->
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block centered_container %}
|
||||
|
||||
<div class="col-12 pl-lg-4">
|
||||
<h4 class="text-left">
|
||||
{% trans "Onboard your entity" %}
|
||||
</h4>
|
||||
|
||||
<p class="card-title">
|
||||
{% blocktrans %}
|
||||
Welcome to the example onboarding system of spid-cie-oidc-django.
|
||||
In this page you can register a OIDC Federation entity to be onboarded in the federation.
|
||||
|
||||
The form has some preliminar validations for your entity configuration,
|
||||
once submitted, validated and tested, a Federation operator will enable your entity as a Descendant of the Federation Authority.
|
||||
|
||||
{% endblocktrans%}
|
||||
</p>
|
||||
<form method="post" action="">
|
||||
{% csrf_token %}
|
||||
{% for form_field in form %}
|
||||
<div class="form-row">
|
||||
<div class="col-12 form-group my-3">
|
||||
<label for="id_{{ form_field.html_name }}">
|
||||
<span class="form-label-content">
|
||||
{{ form_field.label }}
|
||||
</span>
|
||||
</label>
|
||||
{% if form_field.field.widget.input_type == 'select'%}
|
||||
<div class="bootstrap-select-wrapper mb-4">
|
||||
<select name="{{ form_field.name }}" id="id_{{ form_field.html_name }}">
|
||||
{% for value, label in form_field.field.choices %}
|
||||
<option value="{{ value }}" {% if form_field.value == value %} selected {% endif %}>
|
||||
{{ label }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{% elif form_field.name == 'public_jwks' %}
|
||||
<textarea id="id_{{ form_field.html_name }}" rows="5"
|
||||
name="{{ form_field.name }}">{{ form.public_jwks.value}}</textarea>
|
||||
{% else %}
|
||||
<input type="{{ form_field.field.widget.input_type }}" class="form-control"
|
||||
id="id_{{ form_field.html_name }}" name="{{ form_field.name }}" value="{{form_field.value}}">
|
||||
{% endif %}
|
||||
</div>
|
||||
<span for="id_{{ form_field.html_name }}_help" class="text-info">{{ form_field.help_text }}</span>
|
||||
<span for="id_{{ form_field.html_name }}" class="text-danger">{{ form_field.errors }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<input type="submit" name="confirm" class="btn btn-lg btn-success btn-block" value="{% trans 'Submit' %}" />
|
||||
</form>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
Vendored
+59
@@ -0,0 +1,59 @@
|
||||
<!-- Extends default Bootstrap Unical Italia template -->
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block centered_container %}
|
||||
|
||||
<div class="col-12 pl-lg-4">
|
||||
|
||||
<h4 class="text-left">
|
||||
{% trans "Resolve Entity Statement" %}
|
||||
</h4>
|
||||
|
||||
<p class="card-title">
|
||||
{% trans "By inserting the sub of an entity and the trust anchor you can resolve the statement of the entity" %}
|
||||
</p>
|
||||
|
||||
<form method="get" action="">
|
||||
{% csrf_token %}
|
||||
{% for form_field in form %}
|
||||
|
||||
{% if form_field.field.widget.input_type == 'select'%}
|
||||
<div class="bootstrap-select-wrapper my-4">
|
||||
<select name="{{ form_field.name }}" id="id_{{ form_field.html_name }}">
|
||||
{% for value, label in form_field.field.choices %}
|
||||
<option value="{{ value }}" {% if form_field.value == value %} selected {% endif %}>
|
||||
{{ label }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<span for="id_{{ form_field.html_name }}" class="text-danger">{{ form_field.errors }}</span>
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
<div class="form-row">
|
||||
<div class="col-12 form-group my-2">
|
||||
<label for="id_{{ form_field.html_name }}">
|
||||
<span class="form-label-content">
|
||||
{{ form_field.label }}
|
||||
</span>
|
||||
</label>
|
||||
<input type="{{ form_field.field.widget.input_type }}" class="form-control"
|
||||
id="id_{{ form_field.html_name }}" name="{{ form_field.name }}" value="{{form_field.value}}">
|
||||
</div>
|
||||
<span for="id_{{ form_field.html_name }}" class="text-danger">{{ form_field.errors }}</span>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<div class="form-row">
|
||||
<div class="col-12 form-group">
|
||||
<textarea id="resolved_statement" rows="13" name="resolved_statement"
|
||||
disabled>{{ resolved_statement }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<input type="submit" name="confirm" class="btn btn-lg btn-success btn-block" value="{% trans 'resolve' %}" />
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<!-- Extends default Bootstrap Unical Italia template -->
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
|
||||
{% block centered_container %}
|
||||
|
||||
<div class="col-12 col-lg-12">
|
||||
<div class="ml-4 mb-4">
|
||||
<h4 class="text-left">
|
||||
{% trans title %}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="pl-lg-3">
|
||||
<div id="collapseDiv-sc" class="collapse-div collapse-background-active" role="tablist">
|
||||
{% for k, v in schemas.items %}
|
||||
<div class="collapse-header" id="heading1-sc{{ forloop.counter }}">
|
||||
<button data-toggle="collapse" data-target="#collapse{{ forloop.counter }}-sc{{ forloop.counter }}"
|
||||
aria-expanded="false" aria-controls="collapse{{ forloop.counter }}-sc{{ forloop.counter }}">
|
||||
{% trans k %}
|
||||
</button>
|
||||
</div>
|
||||
<div id="collapse{{ forloop.counter }}-sc{{ forloop.counter }}" class="collapse"
|
||||
role="tabpanel" aria-labelledby="heading{{ forloop.counter }}-sc{{ forloop.counter }}">
|
||||
<div class="collapse-body">
|
||||
<pre>{{ v | linebreaks}}</pre>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
<!-- Extends default Bootstrap Unical Italia template -->
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block centered_container %}
|
||||
<div class="col-12 pl-lg-4">
|
||||
<h4 class="text-left">
|
||||
{% trans "Validate entity configuration" %}
|
||||
</h4>
|
||||
|
||||
<p class="pt-4 mb-4">
|
||||
{% trans "enter a url of entity to check if it is compatible" %}
|
||||
</p>
|
||||
|
||||
<form method="post" action="">
|
||||
{% csrf_token %}
|
||||
<div class="form-row">
|
||||
<div class="col-12 form-group my-3">
|
||||
<label for="id_url">
|
||||
<span class="form-label-content">
|
||||
{% trans "url of the entity" %}
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<input type="url" class="form-control" id="id_url" name="url" value="{{url}}">
|
||||
|
||||
</div>
|
||||
<span for="id_url" class="text-danger"></span>
|
||||
</div>
|
||||
{% if ec %}
|
||||
<div class="form-row mt-3">
|
||||
<div class="col-12 form-group my-3">
|
||||
<label for="id_ec">
|
||||
<span class="form-label-content">
|
||||
{% trans "Here the json of entity configuration." %}
|
||||
</span>
|
||||
</label>
|
||||
<textarea id="id_ec" rows="14" disabled>{{ ec }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<input type="submit" name="confirm" class="btn btn-lg btn-primary btn-block" value="{% trans 'validate' %}" />
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
<!-- Extends default Bootstrap Unical Italia template -->
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block centered_container %}
|
||||
<div class="col-12 pl-lg-4">
|
||||
<h4 class="text-left">
|
||||
{% blocktrans %}
|
||||
{{title}}
|
||||
{% endblocktrans %}
|
||||
</h4>
|
||||
|
||||
<p class="pt-4 mb-2">
|
||||
{% trans description %}
|
||||
</p>
|
||||
|
||||
<form method="post" action="">
|
||||
{% csrf_token %}
|
||||
<div class="form-row">
|
||||
<div class="col-12 form-group my-3">
|
||||
<label for="id_md">
|
||||
<span class="form-label-content">
|
||||
{{field_name}}
|
||||
</span>
|
||||
</label>
|
||||
<textarea id="id_md" rows="14" name="md">{{ md }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<input type="submit" name="confirm" class="btn btn-lg btn-success btn-block"
|
||||
value="{% trans 'validate' %}" />
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Vendored
+41
@@ -0,0 +1,41 @@
|
||||
<!-- Extends default Bootstrap Unical Italia template -->
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block centered_container %}
|
||||
|
||||
<div class="col-12 pl-lg-4">
|
||||
<h4 class="text-left">
|
||||
{% trans 'Validating Trust Mark' %}
|
||||
</h4>
|
||||
|
||||
<p class="card-title">
|
||||
{% trans "To validate a trust mark insert the entity's sub and the id or directly the trust mark" %}
|
||||
</p>
|
||||
|
||||
<form method="get" action="">
|
||||
{% csrf_token %}
|
||||
{% for form_field in form %}
|
||||
<div class="form-row">
|
||||
<div class="col-12 form-group my-3">
|
||||
<label for="id_{{ form_field.html_name }}">
|
||||
<span class="form-label-content">
|
||||
{{ form_field.label }}
|
||||
</span>
|
||||
</label>
|
||||
{% if form_field.name == 'trust_mark'%}
|
||||
<textarea id="id_{{ form_field.html_name }}" rows="4"
|
||||
name="{{ form_field.name }}">{{ form.trust_mark.value}}</textarea>
|
||||
{% else%}
|
||||
<input type="{{ form_field.field.widget.input_type }}" class="form-control"
|
||||
id="id_{{ form_field.html_name }}" name="{{ form_field.name }}" value="{{form_field.value}}">
|
||||
{% endif %}
|
||||
</div>
|
||||
<span for="id_{{ form_field.html_name }}" class="text-danger">{{ form_field.errors }}</span>
|
||||
</div>
|
||||
|
||||
{% endfor %}
|
||||
<input type="submit" name="confirm" class="btn btn-lg btn-success btn-block" value="{% trans 'validate' %}" />
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
from django.test import Client
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class OnboardingRegistrationResponse:
|
||||
def __init__(self):
|
||||
self.status_code = 200
|
||||
self.req_counter = 0
|
||||
self.client = Client()
|
||||
self.result = None
|
||||
|
||||
@property
|
||||
def content(self):
|
||||
self.req_counter += 1
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
from django.test import TestCase, Client, override_settings
|
||||
from django.urls import reverse
|
||||
import json
|
||||
|
||||
from spid_cie_oidc.authority.tests.settings import *
|
||||
from spid_cie_oidc.entity.models import *
|
||||
from spid_cie_oidc.onboarding.urls import *
|
||||
from spid_cie_oidc.entity.jwks import serialize_key
|
||||
from spid_cie_oidc.entity.jwks import new_rsa_key
|
||||
from spid_cie_oidc.entity.tests.settings import *
|
||||
|
||||
from spid_cie_oidc.authority.models import *
|
||||
from spid_cie_oidc.authority.tests.mocked_responses import *
|
||||
from spid_cie_oidc.authority.tests.settings import *
|
||||
|
||||
from spid_cie_oidc.onboarding.tests.mocked_responses import *
|
||||
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
class OnboardingTest(TestCase):
|
||||
def setUp(self):
|
||||
|
||||
self.rp_conf = FederationEntityConfiguration.objects.create(**rp_conf)
|
||||
|
||||
self.data = {
|
||||
"organization_name": "",
|
||||
"url_entity": "",
|
||||
"authn_buttons_page_url": "",
|
||||
"type":"",
|
||||
"public_jwks": "",
|
||||
}
|
||||
|
||||
@override_settings(HTTP_CLIENT_SYNC=True)
|
||||
@patch("requests.get", return_value=OnboardingRegistrationResponse())
|
||||
def test_onboarding_registration(self, mocked):
|
||||
url = reverse("oidc_onboarding_registration")
|
||||
client = Client()
|
||||
res = client.get(url, self.data)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
res = client.post(url, self.data)
|
||||
self.assertFormError(
|
||||
res, "form", "organization_name", "Enter your organization name"
|
||||
)
|
||||
self.assertFormError(res, "form", "url_entity",
|
||||
"Enter the entity unique identifier (HTTP URL)"
|
||||
)
|
||||
self.assertFormError(
|
||||
res, "form", "public_jwks",
|
||||
"Enter the public JWKs published in your Entity Configuration, as double check."
|
||||
)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.data["organization_name"] = "test name"
|
||||
self.data["url_entity"] = "http://rp-test/oidc/rp"
|
||||
self.data["type"] = "openid_relying_party"
|
||||
self.data["authn_buttons_page_url"] = "https://authnurl.com"
|
||||
self.data["public_jwks"] = {"key": "ciao"}
|
||||
res = client.post(url, self.data)
|
||||
self.assertContains(res, "Inserisci un JSON valido.")
|
||||
self.assertEqual(res.status_code, 200)
|
||||
jwk = serialize_key(new_rsa_key().pub_key)
|
||||
self.data["public_jwks"] = json.dumps(jwk)
|
||||
# res = client.post(url, self.data)
|
||||
# self.assertEqual(res.status_code, 200)
|
||||
# res = client.get(url)
|
||||
# self.assertEqual(res.status_code, 200)
|
||||
# self.assertIn(self.data["organization_name"], res.content.decode())
|
||||
# self.assertIn("acquired", res.content.decode())
|
||||
|
||||
def test_schema_authorization(self):
|
||||
c = Client()
|
||||
url = reverse("oidc_onboarding_schemas_Authorization")
|
||||
res = c.get(url)
|
||||
self.assertTrue(res.status_code == 200)
|
||||
self.assertIn("Schemas authorization endpoint", res.content.decode())
|
||||
|
||||
def test_schema_introspection(self):
|
||||
c = Client()
|
||||
url = reverse("oidc_onboarding_schemas_introspection")
|
||||
res = c.get(url)
|
||||
self.assertTrue(res.status_code == 200)
|
||||
self.assertIn("Schemas introspection endpoint", res.content.decode())
|
||||
|
||||
def test_schema_metadata(self):
|
||||
c = Client()
|
||||
url = reverse("oidc_onboarding_schemas_metadata")
|
||||
res = c.get(url)
|
||||
self.assertTrue(res.status_code == 200)
|
||||
self.assertIn("Schemas metadata Spid/Cie", res.content.decode())
|
||||
|
||||
def test_schema_revocation(self):
|
||||
c = Client()
|
||||
url = reverse("oidc_onboarding_schemas_revocation")
|
||||
res = c.get(url)
|
||||
self.assertTrue(res.status_code == 200)
|
||||
self.assertIn("Schemas revocation endpoint", res.content.decode())
|
||||
|
||||
def test_schema_token(self):
|
||||
c = Client()
|
||||
url = reverse("oidc_onboarding_schemas_token")
|
||||
res = c.get(url)
|
||||
self.assertTrue(res.status_code == 200)
|
||||
self.assertIn("Schemas token endpoint", res.content.decode())
|
||||
|
||||
def test_schema_client_assertion(self):
|
||||
c = Client()
|
||||
url = reverse("oidc_onboarding_schemas_jwt_client_assertion")
|
||||
res = c.get(url)
|
||||
self.assertTrue(res.status_code == 200)
|
||||
self.assertIn("Schemas jwt", res.content.decode())
|
||||
@@ -0,0 +1,252 @@
|
||||
import json
|
||||
from django.test import TestCase, Client
|
||||
from django.urls import reverse
|
||||
from copy import deepcopy
|
||||
from spid_cie_oidc.entity.jwtse import create_jws
|
||||
|
||||
from spid_cie_oidc.onboarding.tests.tools_settings import jwk_priv, jwt, jwe
|
||||
from spid_cie_oidc.entity.tests.settings import ta_conf_data
|
||||
from spid_cie_oidc.authority.models import (
|
||||
FederationEntityConfiguration,
|
||||
FederationEntityProfile,
|
||||
FederationDescendant,
|
||||
FederationEntityAssignedProfile
|
||||
)
|
||||
from spid_cie_oidc.authority.tests.settings import (
|
||||
rp_conf,
|
||||
RP_PROFILE,
|
||||
rp_onboarding_data
|
||||
)
|
||||
|
||||
from spid_cie_oidc.entity.jwks import (
|
||||
private_pem_from_jwk,
|
||||
public_pem_from_jwk
|
||||
)
|
||||
|
||||
from spid_cie_oidc.entity.tests.op_metadata_settings import OP_METADATA_SPID
|
||||
from spid_cie_oidc.entity.tests.rp_metadata_settings import RP_METADATA_CIE
|
||||
from spid_cie_oidc.provider.tests.authn_request_settings import AUTHN_REQUEST_SPID
|
||||
from spid_cie_oidc.authority.tests.settings import RP_METADATA_JWK1, RP_METADATA_JWK1_pub
|
||||
|
||||
class ToolsTests(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
self.client = Client()
|
||||
self.ta_conf = FederationEntityConfiguration.objects.create(**ta_conf_data)
|
||||
self.rp_conf = FederationEntityConfiguration.objects.create(**rp_conf)
|
||||
|
||||
self.rp_profile = FederationEntityProfile.objects.create(**RP_PROFILE)
|
||||
self.rp = FederationDescendant.objects.create(**rp_onboarding_data)
|
||||
|
||||
self.rp_assigned_profile = FederationEntityAssignedProfile.objects.create(
|
||||
descendant=self.rp, profile=self.rp_profile, issuer=self.ta_conf
|
||||
)
|
||||
|
||||
|
||||
def test_create_jwk(self):
|
||||
url = reverse("oidc_onboarding_create_jwk")
|
||||
res = self.client.get(url)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIsNotNone(res.context['private_jwk'])
|
||||
|
||||
def test_convert_jwk_to_pem(self):
|
||||
url = reverse("oidc_onboarding_convert_jwk")
|
||||
res = self.client.get(url)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
|
||||
#check with jwk error
|
||||
res = self.client.post(url + '?type=private', {'kty': 'RSA'})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("alert-error", res.content.decode())
|
||||
|
||||
#check with public jwk the function jwk priv to pem
|
||||
res = self.client.post(url + '?type=private', {'jwk':json.dumps(RP_METADATA_JWK1_pub)})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("alert-error", res.content.decode())
|
||||
|
||||
#check with right jwk private
|
||||
res = self.client.post(url + '?type=private', {'jwk':json.dumps(RP_METADATA_JWK1)})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertNotIn("alert-error", res.content.decode())
|
||||
|
||||
#check with right jwk public
|
||||
res = self.client.post(url + '?type=public', {'jwk':json.dumps(RP_METADATA_JWK1_pub)})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertNotIn("alert-error", res.content.decode())
|
||||
|
||||
def test_convert_pem_to_jwk(self):
|
||||
url = reverse("oidc_onboarding_convert_pem")
|
||||
res = self.client.get(url)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
|
||||
pem_private = private_pem_from_jwk(RP_METADATA_JWK1)
|
||||
res = self.client.post(url + '?type=private', {"pem": pem_private})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertNotIn("alert-error", res.content.decode())
|
||||
|
||||
pem_public = public_pem_from_jwk(RP_METADATA_JWK1_pub)
|
||||
res = self.client.post(url + '?type=public', {"pem": pem_public})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertNotIn("alert-error", res.content.decode())
|
||||
|
||||
def test_decode_and_verify_jwt(self):
|
||||
url = reverse("oidc_onboarding_tools_decode_jwt")
|
||||
res = self.client.get(url)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
res = self.client.post(url, {"jwt":jwt})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIsNotNone(res.context['payload'])
|
||||
self.assertIsNotNone(res.context['head'])
|
||||
jwkError = {"jwkerror":"error"}
|
||||
jwk = json.dumps(jwkError)
|
||||
res = self.client.post(url, {"jwt":jwt, "jwk": jwk})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("alert-error", res.content.decode())
|
||||
jwk = json.dumps(jwk_priv)
|
||||
res = self.client.post(url, {"jwt":jwt, "jwk": jwk})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("alert-success", res.content.decode())
|
||||
|
||||
def test_decode_and_verify_jwe(self):
|
||||
|
||||
# first failed because no jwks is submitted
|
||||
url = reverse("oidc_onboarding_tools_decode_jwt")
|
||||
res = self.client.get(url)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
res = self.client.post(url, {"jwt":jwe})
|
||||
self.assertEqual(res.status_code, 400)
|
||||
|
||||
res = self.client.post(url, {"jwt": jwe, "jwk": json.dumps(jwk_priv)})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
|
||||
def test_resolve_statement(self):
|
||||
url = reverse("oidc_onboarding_resolve_statement")
|
||||
res = self.client.get(url)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
res = self.client.get(url, {
|
||||
"sub":"http://127.0.0.1:8000/oidc",
|
||||
"type": "openid_provider",
|
||||
"trust_anchor": "http://127.0.0.1:8000"
|
||||
})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("text-danger", res.content.decode())
|
||||
# self.assertIn(
|
||||
# "Failed to resolve entity statement, Please check your inserted data",
|
||||
# res.content.decode())
|
||||
|
||||
form_data= {
|
||||
"sub": "http://127.0.0.1:8000/oidc/op",
|
||||
"type": "openid_provider",
|
||||
"trust_anchor": "http://127.0.0.1:8000",
|
||||
}
|
||||
res = self.client.get(url, form_data)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIsNotNone(res.context['resolved_statement'])
|
||||
|
||||
def test_validating_trust_mark(self):
|
||||
url = reverse("oidc_onboarding_validating_trustmark")
|
||||
res = self.client.get(url)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
|
||||
res = self.client.get(url, {
|
||||
"id": "https://www.ciao.gov.it/certification/rp",
|
||||
"sub": "http://ciao.it/oidc/rp/",
|
||||
})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("alert-error", res.content.decode())
|
||||
|
||||
res = self.client.get(url, {
|
||||
"id": "https://www.spid.gov.it/certification/rp",
|
||||
"sub": "http://rp-test.it/oidc/rp/",
|
||||
})
|
||||
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("alert-success", res.content.decode())
|
||||
|
||||
trust_mark = self.rp_assigned_profile.trust_mark_as_jws
|
||||
|
||||
res = self.client.get(url, {
|
||||
"trust_mark": trust_mark,
|
||||
})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("alert-success", res.content.decode())
|
||||
|
||||
def test_validate_metadata(self):
|
||||
url = reverse("oidc_onboarding_validate_md")
|
||||
|
||||
OP_METADATA_SPID_WRONG = deepcopy(OP_METADATA_SPID)
|
||||
OP_METADATA_SPID_WRONG["issuer"] = "htps://idserver.servizicie.interno.gov.it/op/"
|
||||
res = self.client.post(url + '?metadata_type=op_metadata&provider_profile=spid',
|
||||
{'md': json.dumps(OP_METADATA_SPID_WRONG)})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("alert-error", res.content.decode())
|
||||
|
||||
res = self.client.post(url + '?metadata_type=op_metadata&provider_profile=spid',
|
||||
{'md': json.dumps(OP_METADATA_SPID)})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("alert-success", res.content.decode())
|
||||
|
||||
RP_METADATA_CIE_WRONG = deepcopy(RP_METADATA_CIE)
|
||||
RP_METADATA_CIE_WRONG["jwks_uri"] = "htps://registry.cie.gov.it/keys.json"
|
||||
res = self.client.post(url + '?metadata_type=rp_metadata&provider_profile=cie',
|
||||
{'md': json.dumps(RP_METADATA_CIE_WRONG)})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("alert-error", res.content.decode())
|
||||
|
||||
res = self.client.post(url + '?metadata_type=rp_metadata&provider_profile=cie',
|
||||
{'md': json.dumps(RP_METADATA_CIE)})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("alert-success", res.content.decode())
|
||||
|
||||
res = self.client.post(url + '?metadata_type=rp_metadata&provider_profile=cie',
|
||||
{'md': "hello world"})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("alert-error", res.content.decode())
|
||||
|
||||
def test_validating_trust_mark(self):
|
||||
url = reverse("oidc_onboarding_validating_trustmark")
|
||||
res = self.client.post(url)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
|
||||
res = self.client.post(url, data={
|
||||
"id": "https://www.ciao.gov.it/certification/rp",
|
||||
"sub": "http://ciao.it/oidc/rp/",
|
||||
})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("alert-error", res.content.decode())
|
||||
|
||||
res = self.client.post(url, data={
|
||||
"id": "https://www.spid.gov.it/certification/rp",
|
||||
"sub": "http://rp-test.it/oidc/rp/",
|
||||
})
|
||||
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("alert-success", res.content.decode())
|
||||
|
||||
trust_mark = self.rp_assigned_profile.trust_mark_as_jws
|
||||
|
||||
res = self.client.post(url, data={
|
||||
"trust_mark": trust_mark,
|
||||
})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("alert-success", res.content.decode())
|
||||
|
||||
def test_validate_authn_request(self):
|
||||
url = reverse("oidc_onboarding_validate_authn_request_jwt")
|
||||
AUTHN_REQUEST_SPID_WRONG = deepcopy(AUTHN_REQUEST_SPID)
|
||||
AUTHN_REQUEST_SPID_WRONG["client_id"] = "hps://rp.cie.it/callback1/"
|
||||
jwt = create_jws(AUTHN_REQUEST_SPID_WRONG, RP_METADATA_JWK1)
|
||||
res = self.client.post(url + '?provider_profile=spid',
|
||||
{'md': jwt})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("alert-error", res.content.decode())
|
||||
|
||||
jwt = create_jws(AUTHN_REQUEST_SPID, RP_METADATA_JWK1)
|
||||
res = self.client.post(url + '?provider_profile=spid',
|
||||
{'md': jwt})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn("alert-success", res.content.decode())
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
from django.test import TestCase
|
||||
from spid_cie_oidc.authority.models import FederationDescendant, FederationDescendantContact
|
||||
|
||||
from spid_cie_oidc.onboarding.admin import OnBoardingRegistrationAdmin
|
||||
from spid_cie_oidc.onboarding.models import OnBoardingRegistration
|
||||
|
||||
from spid_cie_oidc.authority.tests.settings import RP_METADATA_JWK1_pub, rp_conf
|
||||
class AdminTest(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.onb_regist = OnBoardingRegistration.objects.create(
|
||||
organization_name = "RP test",
|
||||
url_entity = rp_conf["sub"],
|
||||
public_jwks = RP_METADATA_JWK1_pub,
|
||||
type = "openid_relying_party",
|
||||
contact = "[email protected]"
|
||||
)
|
||||
print(self.onb_regist)
|
||||
|
||||
def test_make_published(self):
|
||||
queryset = [self.onb_regist]
|
||||
OnBoardingRegistrationAdmin.enable_as_descendant(None, request = {}, queryset = queryset)
|
||||
self.assertTrue(len(FederationDescendantContact.objects.all()) == 1)
|
||||
self.assertTrue(len(FederationDescendant.objects.all()) == 1)
|
||||
@@ -0,0 +1,15 @@
|
||||
from spid_cie_oidc.entity.jwtse import create_jwe
|
||||
|
||||
|
||||
jwk_priv = {
|
||||
'kty': 'RSA',
|
||||
'n': 'wct3JUvUxk0JYnDD0sdy0BkLfiLO_Kfy7hvRp7AC1GlvV74FrDfDnYeTTCDPoXEJN2DMiTnMvWXENaFcBkI1RMSaMqupwp6aoGniFDNCiwEh5wgrjVpaxb5Au4pj4Lq1ecbRDDktwqKDVoQsCXsAAApiTkwjq4g6liH8-PTVG-QCM0gL7VIU0jEKCGX6BuZwuKvfEeNTMboMLnn8_AqdsTtvmDommLaOiOgjU0qS7cvowdVX7fhtDeCgVYvPetAFEvimPAE0i4cQ9RAoqlgFCBpRXz9UyeGAXlaFWtLk_t59jNv4nJEP1gQ2VvAvqA4gOn0f9s7Gf1AsFSxrnmeP1Q',
|
||||
'e': 'AQAB',
|
||||
'd': 'vtW1hiyeYogJ7b5Nl4qALRv8jUGJwpNATelnE1Hn93O8CRM-UtC2-LFBA35r9_ZvtPDFeXxJeVh1VrqG_ELGYemYTr1sdhHpAn5B-tJffLKox_Drsk5_hKpM5GDq6anyevClevvza-7Mlq2hD9TnsyKGm8OufIOx7ZWany25jbPK_ksU9X_G9J5RkQ5aDUz7OiUJ-LyL2xmW4gldp_frk_lYgFTgWOp7ZilDQWKYkeLCDzuuRLbM01D7jEJR2c28huQ_vVlw7457NVh-WWyY8Kw0TBgMOU8rrfmgdicv-kbrQaAz60ip95g5FV8ALqSewQYo3v7-4FD8nWVWu01yIQ',
|
||||
'p': '5Qo4l7oom0P08IBun83TtYOEoDjFEuxsOKcWHfSMYcbMpMCog97BA7ji_0tFHVgqjUAfnEXj4U1yi-ScKZHeiusVYzo5_tQXm8f9bjylw4kOQ1UMSoloz7_sd9xT9jpnWXNxLWHXCoXXWDHUV-iXTewDnRM3McWkA1REIdGogG8',
|
||||
'q': '2JsvLNvn5O1CAm5bZesbI4WA2Lx30Y0pEfeqMgpsGYg6QSP-zHc1-jJ5D2zhl4W334NeeUx5pSFzQczg7k-jCWrgKD-nvHzjVxOrzKsG4bOUHIqMDaRbeYH9t-BFNy3b8E6O6sqHKWTbd36JFOi7OBZpmtwSVl7JRYr7sXkUDfs',
|
||||
'kid': 'yxMflR9L6k9Uf-uarpBS3OfgcO1SzbwpZEWbCeOSM3I'
|
||||
}
|
||||
|
||||
jwt = 'eyJhbGciOiJSUzI1NiIsImtpZCI6Inl4TWZsUjlMNms5VWYtdWFycEJTM09mZ2NPMVN6YndwWkVXYkNlT1NNM0kifQ.eyJjbGllbnRfaWQiOiJodHRwczovL3JwLmNpZS5pdCIsInJlc3BvbnNlX3R5cGUiOiJjb2RlIiwic2NvcGUiOiJvcGVuaWQiLCJjb2RlX2NoYWxsZW5nZSI6InFXSmxNZTB4ZGJYckt4VG03MkVwSDY1OWJVeEF4dzgwIiwiY29kZV9jaGFsbGVuZ2VfbWV0aG9kIjoiUzI1NiIsIm5vbmNlIjoiTUJ6R3F5ZjlReXREMjhldXB5V2hTcU1qNzhXTnFwYzIiLCJwcm9tcHQiOiJjb25zZW50IGxvZ2luIiwicmVkaXJlY3RfdXJpIjoiaHR0cHM6Ly9ycC5jaWUuaXQvY2FsbGJhY2sxLyIsImFjcl92YWx1ZXMiOiJDSUVfTDEgQ0lFX0wyIiwiY2xhaW1zIjp7ImlkX3Rva2VuIjp7ImZhbWlseV9uYW1lIjp7ImVzc2VudGlhbCI6dHJ1ZX0sImVtYWlsIjp7ImVzc2VudGlhbCI6dHJ1ZX19LCJ1c2VyaW5mbyI6eyJuYW1lIjpudWxsLCJmYW1pbHlfbmFtZSI6bnVsbH19LCJzdGF0ZSI6ImZ5WmlPTDlMZjJDZUt1TlQySnp4aUxSRGluazB1UGNkIn0.tJqM9mXrg35C78WkCTJQgr7cDirr5mBa22XHDKQI4Bsto5g70LnBJcBN4v85gAqTOYOvhVPcjfN5UKtS2yTnlXMMbWtIjjX3lBlPVTxze5CjdPVKaDf4EB_za2ampPmc2pZh71T9M9exUaSSi1537Sxq9Wbh3QHomtNOoCapp9IS5UheBDe7P3xkU5-pm24NtC3M9EdJHa8AS42EpdbYx5N4md2DaUg0mU1-5sBFLoESVXOj6J1qDQdOqs8Z-wFpjpBi82v4l7woWalzkdVsmeTDxkeb2TCuNAjN29rpgYiVw78WMFi2P5c7t2ZPdQADUdAqpbUvfN4k1hq3Q-WPPA'
|
||||
jwe = create_jwe(jwt, jwk_priv)
|
||||
@@ -0,0 +1,145 @@
|
||||
"""acsia_agent_proj URL Configuration
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/4.0/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.conf import settings
|
||||
from django.urls import path
|
||||
|
||||
from .views import (
|
||||
onboarding_landing,
|
||||
onboarding_registration,
|
||||
onboarding_entities,
|
||||
onboarding_create_jwk,
|
||||
onboarding_convert_jwk,
|
||||
onboarding_convert_pem,
|
||||
onboarding_resolve_statement,
|
||||
onboarding_schemas_federation_entity_endpoints,
|
||||
onboarding_validating_trustmark,
|
||||
onboarding_decode_jwt,
|
||||
onboarding_apply_policy,
|
||||
onboarding_validate_md,
|
||||
onboarding_schemas_authorization,
|
||||
onboarding_schemas_introspection,
|
||||
onboarding_schemas_metadata,
|
||||
onboarding_schemas_revocation,
|
||||
onboarding_schemas_token,
|
||||
onboarding_schemas_jwt_client_assertion,
|
||||
onboarding_validate_authn_request,
|
||||
onboarding_validate_ec,
|
||||
)
|
||||
|
||||
_PREF = getattr(settings, "OIDC_PREFIX", "")
|
||||
|
||||
urlpatterns = [
|
||||
path(
|
||||
f"{_PREF}onboarding/landing",
|
||||
onboarding_landing,
|
||||
name="oidc_onboarding_landing",
|
||||
),
|
||||
path(
|
||||
f"{_PREF}onboarding/registration",
|
||||
onboarding_registration,
|
||||
name="oidc_onboarding_registration",
|
||||
),
|
||||
path(
|
||||
f"{_PREF}onboarding/entities",
|
||||
onboarding_entities,
|
||||
name="oidc_onboarding_entities",
|
||||
),
|
||||
path(
|
||||
f"{_PREF}onboarding/tools/create-jwk",
|
||||
onboarding_create_jwk,
|
||||
name="oidc_onboarding_create_jwk",
|
||||
),
|
||||
path(
|
||||
f"{_PREF}onboarding/tools/convert-jwk",
|
||||
onboarding_convert_jwk,
|
||||
name="oidc_onboarding_convert_jwk",
|
||||
),
|
||||
path(
|
||||
f"{_PREF}onboarding/convert-pem",
|
||||
onboarding_convert_pem,
|
||||
name="oidc_onboarding_convert_pem",
|
||||
),
|
||||
path(
|
||||
f"{_PREF}onboarding/tools/resolve-statement",
|
||||
onboarding_resolve_statement,
|
||||
name="oidc_onboarding_resolve_statement",
|
||||
),
|
||||
path(
|
||||
f"{_PREF}onboarding/tools/validating-trustmark",
|
||||
onboarding_validating_trustmark,
|
||||
name="oidc_onboarding_validating_trustmark",
|
||||
),
|
||||
path(
|
||||
f"{_PREF}onboarding/tools/decode-jwt",
|
||||
onboarding_decode_jwt,
|
||||
name="oidc_onboarding_tools_decode_jwt",
|
||||
),
|
||||
path(
|
||||
f"{_PREF}onboarding/tools/apply-policy",
|
||||
onboarding_apply_policy,
|
||||
name="oidc_onboarding_tools_apply_policy",
|
||||
),
|
||||
path(
|
||||
f"{_PREF}onboarding/schemas/federation_entity",
|
||||
onboarding_schemas_federation_entity_endpoints,
|
||||
name="oidc_onboarding_schemas_federation_entity",
|
||||
),
|
||||
path(
|
||||
f"{_PREF}onboarding/schemas/authorization",
|
||||
onboarding_schemas_authorization,
|
||||
name="oidc_onboarding_schemas_Authorization",
|
||||
),
|
||||
path(
|
||||
f"{_PREF}onboarding/schemas/introspection",
|
||||
onboarding_schemas_introspection,
|
||||
name="oidc_onboarding_schemas_introspection",
|
||||
),
|
||||
path(
|
||||
f"{_PREF}onboarding/schemas/metadata",
|
||||
onboarding_schemas_metadata,
|
||||
name="oidc_onboarding_schemas_metadata",
|
||||
),
|
||||
path(
|
||||
f"{_PREF}onboarding/schemas/revocation",
|
||||
onboarding_schemas_revocation,
|
||||
name="oidc_onboarding_schemas_revocation",
|
||||
),
|
||||
path(
|
||||
f"{_PREF}onboarding/schemas/token",
|
||||
onboarding_schemas_token,
|
||||
name="oidc_onboarding_schemas_token",
|
||||
),
|
||||
path(
|
||||
f"{_PREF}onboarding/schemas/jwt/client/assertion",
|
||||
onboarding_schemas_jwt_client_assertion,
|
||||
name="oidc_onboarding_schemas_jwt_client_assertion",
|
||||
),
|
||||
path(
|
||||
f"{_PREF}onboarding/tools/validate-md",
|
||||
onboarding_validate_md,
|
||||
name="oidc_onboarding_validate_md",
|
||||
),
|
||||
path(
|
||||
f"{_PREF}onboarding/tools/validate-authn-request",
|
||||
onboarding_validate_authn_request,
|
||||
name="oidc_onboarding_validate_authn_request_jwt",
|
||||
),
|
||||
path(
|
||||
f"{_PREF}onboarding/tools/validate-ec",
|
||||
onboarding_validate_ec,
|
||||
name="oidc_onboarding_validate_ec",
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,12 @@
|
||||
from .models import OnBoardingRegistration
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
|
||||
def unique_entity_url(value): # pragma: no cover
|
||||
if OnBoardingRegistration.objects.filter(url_entity=value):
|
||||
raise ValidationError(f"{value} already onboarded")
|
||||
|
||||
|
||||
def trust_anchor_validator(value): # pragma: no cover
|
||||
pass
|
||||
# raise ValidationError(f"{value} trust anchor not exist")
|
||||
@@ -0,0 +1,458 @@
|
||||
import json
|
||||
from django.core.paginator import Paginator
|
||||
from django.shortcuts import render, redirect
|
||||
from django.contrib import messages
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from spid_cie_oidc.authority.schemas.fetch_endpoint_request import FetchRequest
|
||||
from spid_cie_oidc.authority.schemas.list_endpoint import ListRequest, ListResponse
|
||||
from spid_cie_oidc.entity.schemas.resolve_endpoint import ResolveRequest, ResolveResponse
|
||||
from spid_cie_oidc.authority.schemas.trust_mark_status_endpoint import TrustMarkRequest, TrustMarkResponse
|
||||
from spid_cie_oidc.entity.schemas.fa_metadata import FAMetadata
|
||||
|
||||
|
||||
from .forms import (
|
||||
OnboardingRegistrationForm,
|
||||
OnboardingCreateTrustChain,
|
||||
OnboardingValidatingTrustMarkForm,
|
||||
OnboardingDecodeForm
|
||||
)
|
||||
from .models import OnBoardingRegistration
|
||||
from spid_cie_oidc.entity.jwks import (
|
||||
private_pem_from_jwk,
|
||||
public_pem_from_jwk,
|
||||
new_rsa_key,
|
||||
serialize_key,
|
||||
private_jwk_from_pem,
|
||||
public_jwk_from_pem
|
||||
)
|
||||
|
||||
from spid_cie_oidc.entity.jwtse import unpad_jwt_head, unpad_jwt_payload, verify_jws, decrypt_jwe
|
||||
from spid_cie_oidc.authority.views import trust_mark_status
|
||||
from spid_cie_oidc.authority.validators import validate_entity_configuration
|
||||
from spid_cie_oidc.provider.schemas.authn_requests import AuthenticationRequestSpid
|
||||
from spid_cie_oidc.provider.schemas.authn_response import AuthenticationResponse
|
||||
from spid_cie_oidc.provider.schemas.authn_response import AuthenticationErrorResponse
|
||||
from spid_cie_oidc.provider.schemas.introspection_request import IntrospectionRequest
|
||||
from spid_cie_oidc.provider.schemas.introspection_response import IntrospectionResponse
|
||||
from spid_cie_oidc.provider.schemas.introspection_response import IntrospectionErrorResponseSpid
|
||||
from spid_cie_oidc.entity.schemas.op_metadata import OPMetadataSpid, OPMetadataCie
|
||||
from spid_cie_oidc.entity.schemas.rp_metadata import RPMetadataSpid,RPMetadataCie
|
||||
from spid_cie_oidc.provider.schemas.revocation_request import RevocationRequest
|
||||
from spid_cie_oidc.provider.schemas.token_requests import TokenAuthnCodeRequest
|
||||
from spid_cie_oidc.provider.schemas.token_response import TokenResponse
|
||||
from spid_cie_oidc.provider.schemas.token_response import TokenErrorResponse
|
||||
|
||||
from spid_cie_oidc.provider.schemas.token_requests import TokenRefreshRequest
|
||||
from spid_cie_oidc.provider.schemas.token_response import TokenRefreshResponse
|
||||
|
||||
from spid_cie_oidc.provider.schemas.jwt import JwtStructure
|
||||
from spid_cie_oidc.entity.policy import apply_policy
|
||||
|
||||
from spid_cie_oidc.relying_party.settings import RP_PROVIDER_PROFILES
|
||||
from spid_cie_oidc.provider.settings import OIDCFED_PROVIDER_PROFILES
|
||||
from spid_cie_oidc.entity.views import resolve_entity_statement
|
||||
|
||||
|
||||
def onboarding_landing(request): # pragma: no cover
|
||||
return render(request, "onboarding_landing.html")
|
||||
|
||||
|
||||
def onboarding_registration(request):
|
||||
form = OnboardingRegistrationForm()
|
||||
context = {"form": form}
|
||||
if request.method == "POST":
|
||||
form = OnboardingRegistrationForm(request.POST)
|
||||
if not form.is_valid():
|
||||
context = {"form": form}
|
||||
else:
|
||||
form_dict = {**form.cleaned_data}
|
||||
OnBoardingRegistration.objects.create(**form_dict)
|
||||
messages.success(request, _("Registration successfully"))
|
||||
return redirect("oidc_onboarding_entities")
|
||||
return render(request, "onboarding_registration.html", context)
|
||||
|
||||
|
||||
def onboarding_entities(request):
|
||||
entity_list = OnBoardingRegistration.objects.all()
|
||||
p = Paginator(entity_list, 10)
|
||||
page = request.GET.get("page")
|
||||
entities = p.get_page(page)
|
||||
return render(
|
||||
request,
|
||||
"onboarding_entities.html",
|
||||
{"entity_list": entity_list, "entities": entities},
|
||||
)
|
||||
|
||||
|
||||
def onboarding_create_jwk(request):
|
||||
_rsa_key = new_rsa_key()
|
||||
private_jwk = serialize_key(_rsa_key.priv_key, 'private')
|
||||
public_jwk = serialize_key(_rsa_key.pub_key)
|
||||
context = {
|
||||
"private_jwk": json.dumps(private_jwk, indent=4),
|
||||
"public_jwk": json.dumps(public_jwk, indent=4)
|
||||
}
|
||||
return render(request, 'onboarding_jwk.html', context)
|
||||
|
||||
|
||||
def onboarding_convert_jwk(request):
|
||||
jwk_type = request.GET.get('type')
|
||||
context = {
|
||||
"jwk": "",
|
||||
"pem": "",
|
||||
"jwk_type": jwk_type
|
||||
}
|
||||
if request.method == 'POST':
|
||||
try:
|
||||
jwk_str = request.POST.get('jwk')
|
||||
jwk_str_double_quote = jwk_str.replace("'", '"')
|
||||
jwk_dict = json.loads(jwk_str_double_quote)
|
||||
|
||||
if jwk_type == 'private':
|
||||
pem = private_pem_from_jwk(jwk_dict)
|
||||
if jwk_type == 'public':
|
||||
pem = public_pem_from_jwk(jwk_dict)
|
||||
|
||||
context = {
|
||||
"jwk": jwk_dict,
|
||||
"pem": pem,
|
||||
"jwk_type": jwk_type
|
||||
}
|
||||
except Exception as e:
|
||||
messages.error(request, _(f" {e} "))
|
||||
return render(request, 'onboarding_convert_jwk.html', context)
|
||||
|
||||
|
||||
def onboarding_convert_pem(request):
|
||||
pem_type = request.GET.get('type')
|
||||
context = {
|
||||
"pem_type": pem_type
|
||||
}
|
||||
if request.method == 'POST':
|
||||
try:
|
||||
pem = request.POST.get('pem')
|
||||
if pem_type == 'private':
|
||||
jwk = private_jwk_from_pem(pem)
|
||||
if pem_type == 'public':
|
||||
jwk = public_jwk_from_pem(pem)
|
||||
context = {
|
||||
"pem": pem,
|
||||
"pem_type": pem_type,
|
||||
"jwk": jwk
|
||||
}
|
||||
except Exception as e:
|
||||
messages.error(request, _(f" {e} "))
|
||||
return render(request, 'onboarding_convert_pem.html', context)
|
||||
|
||||
|
||||
def onboarding_resolve_statement(request):
|
||||
if "sub" in request.GET :
|
||||
form = OnboardingCreateTrustChain(request.GET)
|
||||
else:
|
||||
form = OnboardingCreateTrustChain()
|
||||
context = {'form': form}
|
||||
if form.is_valid():
|
||||
context = {
|
||||
'form': form,
|
||||
"resolved_statement": "",
|
||||
}
|
||||
try:
|
||||
res = resolve_entity_statement(request, format="json")
|
||||
resultJson = json.loads(res.content.decode())
|
||||
context["resolved_statement"] = json.dumps(resultJson, indent=4)
|
||||
except Exception:
|
||||
messages.error(request, _('Failed to resolve entity statement, Please check your inserted data'))
|
||||
|
||||
return render(request, 'onboarding_resolve_statement.html', context)
|
||||
|
||||
|
||||
def onboarding_validating_trustmark(request):
|
||||
if "id" in request.POST or "trust_mark" in request.POST:
|
||||
form = OnboardingValidatingTrustMarkForm(request.POST)
|
||||
else:
|
||||
form = OnboardingValidatingTrustMarkForm()
|
||||
|
||||
context = {"form": form}
|
||||
|
||||
if form.is_valid():
|
||||
res = trust_mark_status(request)
|
||||
body = res.content.decode()
|
||||
context = {'form': form}
|
||||
ct = res.get("Content-Type", "")
|
||||
if res.status_code == 200 and ct.startswith("application/trust-mark-status-response+jwt"):
|
||||
# Draft 48: response is a signed JWT with status claim
|
||||
from spid_cie_oidc.entity.jwtse import unpad_jwt_payload
|
||||
content = unpad_jwt_payload(body)
|
||||
active = content.get("status") == "active"
|
||||
else:
|
||||
# Error response (e.g. 404) or legacy JSON body
|
||||
try:
|
||||
content = json.loads(body)
|
||||
active = content.get("active", False)
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
active = False
|
||||
if active:
|
||||
messages.success(request, _('Validation Trust Mark Successfully'))
|
||||
else:
|
||||
messages.error(request, _('Validation Trust Mark Failed'))
|
||||
return render(request, 'onboarding_validating_tm.html', context)
|
||||
|
||||
|
||||
def onboarding_validate_md(request):
|
||||
metadata_type = request.GET.get('metadata_type')
|
||||
provider_profile = request.GET.get('provider_profile')
|
||||
md_type = metadata_type.replace("_", " ")
|
||||
title = f'Validate {md_type} {provider_profile}'
|
||||
description = f'Enter a {md_type} of {provider_profile} to verify if it is compatible'
|
||||
context = {
|
||||
"metadata_type": metadata_type,
|
||||
"provider_profile": provider_profile,
|
||||
"title": title,
|
||||
"description": description,
|
||||
"field_name":"metadata"
|
||||
}
|
||||
if request.POST.get('md'):
|
||||
md = request.POST['md']
|
||||
context["md"] = md
|
||||
try:
|
||||
md_str_double_quote = md.replace("'", '"')
|
||||
metadata = json.loads(md_str_double_quote)
|
||||
if metadata_type == 'op_metadata':
|
||||
schema = OIDCFED_PROVIDER_PROFILES[provider_profile]
|
||||
schema[metadata_type](**metadata)
|
||||
messages.success(request, _('Validation Metadata Successfully'))
|
||||
if metadata_type == 'rp_metadata':
|
||||
schema = RP_PROVIDER_PROFILES[provider_profile]
|
||||
schema[metadata_type](**metadata)
|
||||
messages.success(request, _('Validation Metadata Successfully'))
|
||||
except Exception as e:
|
||||
messages.error(request, f"Validation Failed: {e}")
|
||||
return render(request, 'onboarding_validate_md.html', context)
|
||||
|
||||
|
||||
def onboarding_validate_authn_request(request):
|
||||
provider_profile = request.GET.get('provider_profile')
|
||||
title = f'Validate authn request {provider_profile}'
|
||||
description = f'Enter a jwt of authn request for {provider_profile} to verify if it is compatible'
|
||||
context = {
|
||||
"provider_profile": provider_profile,
|
||||
"title": title,
|
||||
"description": description,
|
||||
"field_name":"jwt"
|
||||
}
|
||||
if request.POST.get('md'):
|
||||
jwt_str = request.POST['md']
|
||||
context = {
|
||||
"provider_profile": provider_profile,
|
||||
"title": title,
|
||||
"description": description,
|
||||
"field_name":"jwt",
|
||||
"md": jwt_str
|
||||
}
|
||||
payload = unpad_jwt_payload(jwt_str)
|
||||
schema = OIDCFED_PROVIDER_PROFILES[provider_profile]
|
||||
try:
|
||||
schema["authorization_request"](**payload)
|
||||
messages.success(request, _('Validation Authn Request Successfully'))
|
||||
except Exception as e:
|
||||
messages.error(request, f"Validation Failed: {e}")
|
||||
return render(request, 'onboarding_validate_md.html', context)
|
||||
|
||||
|
||||
def onboarding_validate_ec(request):
|
||||
context = {}
|
||||
if request.POST:
|
||||
url = request.POST.get("url")
|
||||
context = {"url": url}
|
||||
try:
|
||||
ec = validate_entity_configuration(url)
|
||||
context["ec"] = json.dumps(ec.payload, indent=4)
|
||||
messages.success(request, _('Validation Entity Configuration Successfully'))
|
||||
except Exception as e :
|
||||
messages.error(request, f"Validation Failed: {e}")
|
||||
return render(request, 'onboarding_validate_ec.html', context)
|
||||
return render(request, 'onboarding_validate_ec.html', context)
|
||||
|
||||
|
||||
def onboarding_decode_jwt(request):
|
||||
if request.method == "GET":
|
||||
form = OnboardingDecodeForm()
|
||||
else:
|
||||
form = OnboardingDecodeForm(request.POST)
|
||||
|
||||
context = {'form': form}
|
||||
|
||||
if form.is_valid():
|
||||
form_dict = {**form.cleaned_data}
|
||||
jwt = form_dict['jwt']
|
||||
try:
|
||||
head = unpad_jwt_head(jwt)
|
||||
except Exception as e:
|
||||
messages.error(
|
||||
request,
|
||||
f"JWS verification failed due to missing JWT header: {e}"
|
||||
)
|
||||
return render(request, "onboarding_decode_jwt.html", context)
|
||||
|
||||
if head.get('enc', None):
|
||||
if not form_dict.get('jwk'):
|
||||
messages.error(
|
||||
request,
|
||||
"JWE needs a private jwk to be decrypted"
|
||||
)
|
||||
return render(
|
||||
request, "onboarding_decode_jwt.html", context, status = 400
|
||||
)
|
||||
# JWE here
|
||||
jwk = form_dict['jwk']
|
||||
jwt = decrypt_jwe(jwt, jwk)
|
||||
|
||||
try:
|
||||
|
||||
payload = unpad_jwt_payload(jwt)
|
||||
context["head"] = json.dumps(head, indent=4)
|
||||
context["payload"] = json.dumps(payload, indent=4)
|
||||
jwk = form_dict["jwk"]
|
||||
if jwk:
|
||||
verify_jws(jwt, jwk)
|
||||
messages.success(request, _('Your jws is verified'))
|
||||
except Exception as e:
|
||||
messages.error(request, f"JWS verification failed: {e}")
|
||||
|
||||
return render(request, "onboarding_decode_jwt.html", context)
|
||||
|
||||
|
||||
def onboarding_apply_policy(request):
|
||||
context = {
|
||||
"md": "",
|
||||
"policy": "",
|
||||
"result": ""
|
||||
}
|
||||
if request.GET.get('md') and request.GET.get('policy'):
|
||||
context = {
|
||||
"md": request.GET['md'],
|
||||
"policy": request.GET['policy'],
|
||||
"result": ""
|
||||
}
|
||||
try:
|
||||
md = json.loads(request.GET['md'])
|
||||
policy = json.loads(request.GET['policy'])
|
||||
reuslt = apply_policy(md, policy)
|
||||
context["result"] = json.dumps(reuslt, indent=4)
|
||||
except Exception as e:
|
||||
messages.error(request, {e})
|
||||
return render(request, 'onboarding_apply_policy.html', context)
|
||||
|
||||
|
||||
def onboarding_schemas_authorization(request):
|
||||
auth_request = AuthenticationRequestSpid.schema_json(indent=2)
|
||||
auth_res_succ = AuthenticationResponse.schema_json(indent=2)
|
||||
auth_res_err = AuthenticationErrorResponse.schema_json(indent=2)
|
||||
content = {
|
||||
"title": "Schemas authorization endpoint",
|
||||
"schemas": {
|
||||
"authorization request": auth_request,
|
||||
"authorization successful response": auth_res_succ,
|
||||
"authorization error response": auth_res_err,
|
||||
}
|
||||
}
|
||||
return render(request, "onboarding_schemas.html", content)
|
||||
|
||||
|
||||
def onboarding_schemas_introspection(request):
|
||||
intro_request = IntrospectionRequest.schema_json(indent=2)
|
||||
intro_res_succ = IntrospectionResponse.schema_json(indent=2)
|
||||
intro_res_err = IntrospectionErrorResponseSpid.schema_json(indent=2)
|
||||
content = {
|
||||
"title": "Schemas introspection endpoint",
|
||||
"schemas": {
|
||||
"introspection request": intro_request,
|
||||
"introspection successful response": intro_res_succ,
|
||||
"introspection error response": intro_res_err,
|
||||
}
|
||||
}
|
||||
return render(request, "onboarding_schemas.html", content)
|
||||
|
||||
|
||||
def onboarding_schemas_federation_entity_endpoints(request):
|
||||
federation_entity_fetch_request = FetchRequest.schema_json(indent=2)
|
||||
federation_entity_list_request = ListRequest.schema_json(indent=2)
|
||||
federation_entity_list_response = ListResponse.schema_json(indent=2)
|
||||
federation_entity_resolve_request = ResolveRequest.schema_json(indent=2)
|
||||
federation_entity_resolve_response = ResolveResponse.schema_json(indent=2)
|
||||
federation_entity_status_request = TrustMarkRequest.schema_json(indent=2)
|
||||
federation_entity_status_response = TrustMarkResponse.schema_json(indent=2)
|
||||
content = {
|
||||
"title": "Schemas Federation entity endpoint",
|
||||
"schemas": {
|
||||
"Federation entity fetch": federation_entity_fetch_request,
|
||||
"Federation entity list request": federation_entity_list_request,
|
||||
"Federation entity list response": federation_entity_list_response,
|
||||
"Federation entity resolve request": federation_entity_resolve_request,
|
||||
"Federation entity resolve response": federation_entity_resolve_response,
|
||||
"Federation entity status request": federation_entity_status_request,
|
||||
"Federation entity status response": federation_entity_status_response
|
||||
}
|
||||
}
|
||||
return render(request, "onboarding_schemas.html", content)
|
||||
|
||||
|
||||
def onboarding_schemas_metadata(request):
|
||||
op_meta_spid = OPMetadataSpid.schema_json(indent=2)
|
||||
op_meta_cie = OPMetadataCie.schema_json(indent=2)
|
||||
rp_meta_spid = RPMetadataSpid.schema_json(indent=2)
|
||||
rp_meta_cie = RPMetadataCie.schema_json(indent=2)
|
||||
fed_entity = FAMetadata.schema_json(indent=2)
|
||||
content = {
|
||||
"title": "Schemas metadata Spid/Cie",
|
||||
"schemas": {
|
||||
"Federation entity": fed_entity,
|
||||
"OP Spid": op_meta_spid,
|
||||
"OP Cie": op_meta_cie,
|
||||
"RP Spid": rp_meta_spid,
|
||||
"RP Cie": rp_meta_cie
|
||||
}
|
||||
}
|
||||
return render(request, "onboarding_schemas.html", content)
|
||||
|
||||
|
||||
def onboarding_schemas_revocation(request):
|
||||
revoc_request = RevocationRequest.schema_json(indent=2)
|
||||
content = {
|
||||
"title": "Schemas revocation endpoint",
|
||||
"schemas": {
|
||||
"revocation request": revoc_request
|
||||
}
|
||||
}
|
||||
return render(request, "onboarding_schemas.html", content)
|
||||
|
||||
|
||||
def onboarding_schemas_token(request):
|
||||
auth_code_req = TokenAuthnCodeRequest.schema_json(indent=2)
|
||||
auth_code_res = TokenResponse.schema_json(indent=2)
|
||||
refr_req = TokenRefreshRequest.schema_json(indent=2)
|
||||
refr_res = TokenRefreshResponse.schema_json(indent=2)
|
||||
err_res = TokenErrorResponse.schema_json(indent=2)
|
||||
content = {
|
||||
"title": "Schemas token endpoint",
|
||||
"schemas": {
|
||||
"token authn code request": auth_code_req,
|
||||
"token authn code response": auth_code_res,
|
||||
"refresh token request": refr_req,
|
||||
"refresh token response": refr_res,
|
||||
"token error response": err_res
|
||||
}
|
||||
}
|
||||
return render(request, "onboarding_schemas.html", content)
|
||||
|
||||
|
||||
def onboarding_schemas_jwt_client_assertion(request):
|
||||
jwt_client_asser = JwtStructure.schema_json(indent=2)
|
||||
content = {
|
||||
"title": "Schemas jwt",
|
||||
"schemas": {
|
||||
"jwt client assertion": jwt_client_asser
|
||||
}
|
||||
}
|
||||
return render(request, "onboarding_schemas.html", content)
|
||||
Reference in New Issue
Block a user