Skip to content

Commit

Permalink
feat: resolve entity statement endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
peppelinux committed Feb 26, 2022
1 parent 2ff0003 commit 3db5e85
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 49 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ each of these can be installed separately within a django project:

The Technical specifications of these SDKs are available here:

1. [__OIDC Federation Entity/Authority/Intermediary__](docs/technical_specifications/ENTITY.md)
1. [__OIDC Federation Authority/Intermediary__](docs/technical_specifications/ENTITY.md)
2. [__OIDC Federation Authority/Intermediary__](docs/technical_specifications/AUTHORITY.md)
3. [__OIDC Federation 1.0 onboarding service DEMO__](docs/technical_specifications/ONBOARDING.md)
4. [__Openid Connect Provider__](docs/technical_specifications/PROVIDER.md)
Expand Down
11 changes: 7 additions & 4 deletions docs/technical_specifications/AUTHORITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ and below it must have other entities for which it provides an onboarding mechan

All the endpoints are configured in the `urls.py` file of the project folder.

#### fetch
#### Fetch

All entities that are expected to publish entity statements about other entities MUST expose a Fetch endpoint.

Expand All @@ -21,7 +21,7 @@ Example of FETCH request
- `http://127.0.0.1:8000/fetch/?sub=http://127.0.0.1:8000/oidc/rp/`
- `http://127.0.0.1:8000/fetch/?sub=http://127.0.0.1:8001/&format=json`

#### listing
#### Listing

As described in the official specification
[here](https://openid.net/specs/openid-connect-federation-1_0.html#rfc.section.7.3.1).
Expand All @@ -33,9 +33,12 @@ Lists all the descendant entities.
- `http://127.0.0.1:8000/list/?is_leaf=false`
- `http://127.0.0.1:8000/list/?is_leaf=true`

#### resolve entity statement
#### Resolve entity statement

WiP
An entity MAY use the resolve endpoint to fetch resolved metadata and trust marks for an entity as seen/trusted by the resolver.

- `http://127.0.0.1:8000/resolve/?sub=http://127.0.0.1:8000/oidc/op/&anchor=http://127.0.0.1:8000/&format=json`
- `http://127.0.0.1:8000/resolve/?sub=http://127.0.0.1:8000/oidc/op/&anchor=http://127.0.0.1:8000/`

#### trust mark status

Expand Down
24 changes: 24 additions & 0 deletions spid_cie_oidc/authority/tests/test_02_trust_anchor_intermediary.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,3 +257,27 @@ def test_trust_chain_valid_helpers(self, mocked):

self.assertFalse(gctc.is_expired)
self.assertTrue(gctc.is_valid)

@override_settings(HTTP_CLIENT_SYNC=True)
@patch("requests.get", return_value=EntityResponseNoIntermediate())
def test_resolve_endpoint(self, mocked):
gctc = get_or_create_trust_chain(
subject = rp_conf["sub"],
trust_anchor = self.ta_conf.sub,
# TODO
#required_trust_marks: list = [],
metadata_type = "openid_relying_party"
)

url = reverse("oidcfed_resolve")

c = Client()
res = c.get(
url,
data={
"sub": self.rp.sub,
"anchor": self.ta_conf.sub
}
)
self.assertTrue(res.status_code == 200)
verify_jws(res.content.decode(), self.ta_conf.jwks[0])
3 changes: 2 additions & 1 deletion spid_cie_oidc/authority/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
from django.conf import settings
from django.urls import path

from .views import fetch, entity_list
from .views import fetch, entity_list, resolve_entity_statement

_PREF = getattr(settings, "OIDC_PREFIX", "")

urlpatterns = [
path(f"{_PREF}fetch/", fetch, name="oidcfed_fetch"),
path(f"{_PREF}list/", entity_list, name="oidcfed_list"),
path(f"{_PREF}resolve/", resolve_entity_statement, name="oidcfed_resolve"),
]
53 changes: 39 additions & 14 deletions spid_cie_oidc/authority/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
from django.http import HttpResponse
from django.http import JsonResponse


from spid_cie_oidc.authority.models import (
FederationDescendant,
FederationEntityAssignedProfile,
get_first_self_trust_anchor,
)
from spid_cie_oidc.entity.jwtse import create_jws
from spid_cie_oidc.entity.models import TrustChain


def fetch(request):
Expand Down Expand Up @@ -64,21 +65,45 @@ def resolve_entity_statement(request):
resolves the final metadata of its descendants
"""
if not all(
request.GET.get("sub"),
request.GET.get("anchor"),
(
request.GET.get("sub", None),
request.GET.get("anchor", None)
)
):
raise Http404("sub and anchor parameters are REQUIRED.")

# TODO: resolve also other entities in a federation
# TODO: release a metadata on top of a resolved trust chain
# if request.GET.get('iss'):
# iss = get_first_self_trust_anchor(sub = request.GET['iss'])
# else:
# iss = get_first_self_trust_anchor()
if request.GET.get('iss'):
iss = get_first_self_trust_anchor(sub = request.GET['iss'])
else:
iss = get_first_self_trust_anchor()

_q = dict(
sub=request.GET["sub"],
trust_anchor__sub=request.GET["anchor"],
is_active=True
)
if request.GET.get("type", None):
_q['type'] = request.GET["type"]

entity = TrustChain.objects.filter(**_q).first()
if not entity:
raise Http404("entity not found.")

entity = FederationDescendant.objects.filter(sub=request.GET["sub"], is_active=True)
res = {
"iss": iss.sub,
"sub": request.GET["sub"],
"aud": [],
"iat": entity.iat_as_timestamp,
"exp": entity.exp_as_timestamp,
"trust_marks": [],
"metadata": entity.metadata
}

# filter by type
if request.GET.get("type"):
entity.metadata_policy.get(request.GET["type"])
# metadata =
if request.GET.get("format") == "json":
return JsonResponse(res, safe=False)
else:
return HttpResponse(
create_jws(res, iss.jwks[0]),
content_type="application/jose",
)

18 changes: 3 additions & 15 deletions spid_cie_oidc/entity/jwtse.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,9 @@
from cryptojwt.jws.jws import JWS
from django.conf import settings

from . import settings as local_settings

DEFAULT_JWS_ALG = getattr(settings, "DEFAULT_JWS_ALG", local_settings.DEFAULT_JWS_ALG)
DEFAULT_JWE_ALG = getattr(settings, "DEFAULT_JWE_ALG", local_settings.DEFAULT_JWE_ALG)
DEFAULT_JWE_ENC = getattr(settings, "DEFAULT_JWE_ENC", local_settings.DEFAULT_JWE_ENC)
SIGNING_ALG_VALUES_SUPPORTED = getattr(
settings,
"SIGNING_ALG_VALUES_SUPPORTED",
local_settings.SIGNING_ALG_VALUES_SUPPORTED,
)
ENCRYPTION_ALG_VALUES_SUPPORTED = getattr(
settings,
"ENCRYPTION_ALG_VALUES_SUPPORTED",
local_settings.ENCRYPTION_ALG_VALUES_SUPPORTED,
)
from . settings import *



logger = logging.getLogger(__name__)

Expand Down
8 changes: 8 additions & 0 deletions spid_cie_oidc/entity/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,14 @@ def is_expired(self):
self.exp <= timezone.localtime()
)

@property
def iat_as_timestamp(self):
return int(self.iat.timestamp())

@property
def exp_as_timestamp(self):
return int(self.exp.timestamp())

@property
def is_valid(self):
return self.is_active and ENTITY_STATUS[self.status]
Expand Down
35 changes: 21 additions & 14 deletions spid_cie_oidc/entity/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import aiohttp


DEFAULT_JWE_ENC = "A256CBC-HS512"
ENCRYPTION_ENC_SUPPORTED = [
"A128CBC-HS256",
"A192CBC-HS384",
Expand All @@ -13,21 +12,29 @@
"A256GCM",
]

DEFAULT_JWS_ALG = "RS256"
SIGNING_ALG_VALUES_SUPPORTED = ["RS256", "RS384", "RS512", "ES256", "ES384", "ES512"]

DEFAULT_JWE_ALG = "RSA-OAEP"
ENCRYPTION_ALG_VALUES_SUPPORTED = [
"RSA-OAEP",
"RSA-OAEP-256",
"ECDH-ES",
"ECDH-ES+A128KW",
"ECDH-ES+A192KW",
"ECDH-ES+A256KW",
]

DEFAULT_HASH_FUNC = "SHA-256"

DEFAULT_JWS_ALG = getattr(settings, "DEFAULT_JWS_ALG", "RS256")
DEFAULT_JWE_ALG = getattr(settings, "DEFAULT_JWE_ALG", "RSA-OAEP")
DEFAULT_JWE_ENC = getattr(settings, "DEFAULT_JWE_ENC", "A256CBC-HS512")
SIGNING_ALG_VALUES_SUPPORTED = getattr(
settings,
"SIGNING_ALG_VALUES_SUPPORTED",
["RS256", "RS384", "RS512", "ES256", "ES384", "ES512"],
)
ENCRYPTION_ALG_VALUES_SUPPORTED = getattr(
settings,
"ENCRYPTION_ALG_VALUES_SUPPORTED",
[
"RSA-OAEP",
"RSA-OAEP-256",
"ECDH-ES",
"ECDH-ES+A128KW",
"ECDH-ES+A192KW",
"ECDH-ES+A256KW",
]
)

# This is required in general project settings
# OIDCFED_FEDERATION_TRUST_ANCHORS = [https://..., ]

Expand Down

0 comments on commit 3db5e85

Please sign in to comment.