Skip to content

Commit

Permalink
✨ [#1902/1903] DigiD/eHerkenning via OIDC
Browse files Browse the repository at this point in the history
  • Loading branch information
stevenbal committed Dec 5, 2023
1 parent e7c6db5 commit 3b63168
Show file tree
Hide file tree
Showing 22 changed files with 947 additions and 18 deletions.
Empty file.
55 changes: 55 additions & 0 deletions src/digid_eherkenning_oidc_generics/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from django.contrib import admin
from django.utils.translation import gettext_lazy as _

from django_better_admin_arrayfield.admin.mixins import DynamicArrayMixin
from solo.admin import SingletonModelAdmin

from .forms import OpenIDConnectEHerkenningConfigForm, OpenIDConnectPublicConfigForm
from .models import OpenIDConnectEHerkenningConfig, OpenIDConnectPublicConfig


class OpenIDConnectConfigBaseAdmin(DynamicArrayMixin, SingletonModelAdmin):
fieldsets = (
(
_("Activation"),
{"fields": ("enabled",)},
),
(
_("Common settings"),
{
"fields": (
"identifier_claim_name",
"oidc_rp_client_id",
"oidc_rp_client_secret",
"oidc_rp_scopes_list",
"oidc_rp_sign_algo",
"oidc_rp_idp_sign_key",
"userinfo_claims_source",
)
},
),
(
_("Endpoints"),
{
"fields": (
"oidc_op_discovery_endpoint",
"oidc_op_jwks_endpoint",
"oidc_op_authorization_endpoint",
"oidc_op_token_endpoint",
"oidc_op_user_endpoint",
"oidc_op_logout_endpoint",
)
},
),
(_("Keycloak specific settings"), {"fields": ("oidc_keycloak_idp_hint",)}),
)


@admin.register(OpenIDConnectPublicConfig)
class OpenIDConnectConfigDigiDAdmin(OpenIDConnectConfigBaseAdmin):
form = OpenIDConnectPublicConfigForm


@admin.register(OpenIDConnectEHerkenningConfig)
class OpenIDConnectConfigEHerkenningAdmin(OpenIDConnectConfigBaseAdmin):
form = OpenIDConnectEHerkenningConfigForm
7 changes: 7 additions & 0 deletions src/digid_eherkenning_oidc_generics/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _


class DigiDeHerkenningOIDCAppConfig(AppConfig):
name = "digid_eherkenning_oidc_generics"
verbose_name = _("DigiD & eHerkenning via OpenID Connect")
72 changes: 72 additions & 0 deletions src/digid_eherkenning_oidc_generics/backends.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import logging

from django.contrib.auth.models import AnonymousUser
from django.core.exceptions import SuspiciousOperation

from mozilla_django_oidc_db.backends import (
OIDCAuthenticationBackend as _OIDCAuthenticationBackend,
)
from requests.exceptions import RequestException

from open_inwoner.accounts.choices import LoginTypeChoices

from .constants import DIGID_OIDC_AUTH_SESSION_KEY, EHERKENNING_OIDC_AUTH_SESSION_KEY
from .mixins import SoloConfigDigiDMixin, SoloConfigEHerkenningMixin

logger = logging.getLogger(__name__)


class OIDCAuthenticationBackend(_OIDCAuthenticationBackend):
config_identifier_field = "identifier_claim_name"

def filter_users_by_claims(self, claims):
"""Return all users matching the specified subject."""
identifier_claim_name = getattr(self.config, self.config_identifier_field)
unique_id = self.retrieve_identifier_claim(claims)

if not unique_id:
return self.UserModel.objects.none()
return self.UserModel.objects.filter(
**{f"{identifier_claim_name}__iexact": unique_id}
)

def create_user(self, claims):
"""Return object for a newly created user account."""
identifier_claim_name = getattr(self.config, self.config_identifier_field)
unique_id = self.retrieve_identifier_claim(claims)

logger.debug("Creating OIDC user: %s", unique_id)

user = self.UserModel.objects.create_user(
**{
self.UserModel.USERNAME_FIELD: "user-{}@localhost".format(unique_id),
identifier_claim_name: unique_id,
"login_type": self.login_type,
}
)

return user

def update_user(self, user, claims):
# TODO should we do anything here? or do we only fetch data from HaalCentraal
return user


class OIDCAuthenticationDigiDBackend(SoloConfigDigiDMixin, OIDCAuthenticationBackend):
"""
Allows logging in via OIDC with DigiD
"""

session_key = DIGID_OIDC_AUTH_SESSION_KEY
login_type = LoginTypeChoices.digid


class OIDCAuthenticationEHerkenningBackend(
SoloConfigEHerkenningMixin, OIDCAuthenticationBackend
):
"""
Allows logging in via OIDC with DigiD
"""

session_key = EHERKENNING_OIDC_AUTH_SESSION_KEY
login_type = LoginTypeChoices.eherkenning
2 changes: 2 additions & 0 deletions src/digid_eherkenning_oidc_generics/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
DIGID_OIDC_AUTH_SESSION_KEY = "digid_oidc:bsn"
EHERKENNING_OIDC_AUTH_SESSION_KEY = "eherkenning_oidc:kvk"
2 changes: 2 additions & 0 deletions src/digid_eherkenning_oidc_generics/digid_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
DIGID_CUSTOM_OIDC_DB_PREFIX = "digid_oidc"
OIDC_AUTHENTICATION_CALLBACK_URL = "digid_oidc:callback"
24 changes: 24 additions & 0 deletions src/digid_eherkenning_oidc_generics/digid_urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from django.urls import path

from mozilla_django_oidc.urls import urlpatterns

from .views import (
DigiDOIDCAuthenticationCallbackView,
DigiDOIDCAuthenticationRequestView,
)

app_name = "digid_oidc"


urlpatterns = [
path(
"callback/",
DigiDOIDCAuthenticationCallbackView.as_view(),
name="callback",
),
path(
"authenticate/",
DigiDOIDCAuthenticationRequestView.as_view(),
name="init",
),
] + urlpatterns
2 changes: 2 additions & 0 deletions src/digid_eherkenning_oidc_generics/eherkenning_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
EHERKENNING_CUSTOM_OIDC_DB_PREFIX = "eherkenning_oidc"
OIDC_AUTHENTICATION_CALLBACK_URL = "eherkenning_oidc:callback"
24 changes: 24 additions & 0 deletions src/digid_eherkenning_oidc_generics/eherkenning_urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from django.urls import path

from mozilla_django_oidc.urls import urlpatterns

from .views import (
eHerkenningOIDCAuthenticationCallbackView,
eHerkenningOIDCAuthenticationRequestView,
)

app_name = "eherkenning_oidc"


urlpatterns = [
path(
"callback/",
eHerkenningOIDCAuthenticationCallbackView.as_view(),
name="callback",
),
path(
"authenticate/",
eHerkenningOIDCAuthenticationRequestView.as_view(),
name="init",
),
] + urlpatterns
39 changes: 39 additions & 0 deletions src/digid_eherkenning_oidc_generics/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from copy import deepcopy

from django.utils.translation import gettext_lazy as _

from mozilla_django_oidc_db.constants import OIDC_MAPPING as _OIDC_MAPPING
from mozilla_django_oidc_db.forms import OpenIDConnectConfigForm

from .models import OpenIDConnectEHerkenningConfig, OpenIDConnectPublicConfig

OIDC_MAPPING = deepcopy(_OIDC_MAPPING)

OIDC_MAPPING["oidc_op_logout_endpoint"] = "end_session_endpoint"


class OpenIDConnectBaseConfigForm(OpenIDConnectConfigForm):
required_endpoints = [
"oidc_op_authorization_endpoint",
"oidc_op_token_endpoint",
"oidc_op_user_endpoint",
"oidc_op_logout_endpoint",
]
oidc_mapping = OIDC_MAPPING
plugin_identifier = ""


class OpenIDConnectPublicConfigForm(OpenIDConnectBaseConfigForm):
plugin_identifier = "digid_oidc"

class Meta:
model = OpenIDConnectPublicConfig
fields = "__all__"


class OpenIDConnectEHerkenningConfigForm(OpenIDConnectBaseConfigForm):
plugin_identifier = "eherkenning_oidc"

class Meta:
model = OpenIDConnectEHerkenningConfig
fields = "__all__"
Loading

0 comments on commit 3b63168

Please sign in to comment.