Authentication

The authentication module provides plugins to establish the identity of end-users filling out a form. Identifying attributes can then be used by Prefill plugins to retrieve additional details of the citizen or company. Depending on the authentication plugin used, a certain level of assurance regarding the authentication strength can be obtained as well, increasing trust for higher levels.

Python API

The public API serves as an abstraction over the various plugins.

Reference

class openforms.authentication.service.AuthAttribute(*values)

core identifying attributes retrieved from the authentication plugins

class openforms.authentication.service.BaseAuth

The base structure of authentication data.

plugin: str

The unique identifier of the plugin that inititiated the authentication data.

openforms.authentication.service.check_user_is_submission_initiator(request: HttpRequest, submission: Submission) bool

Test if the logged in user matches the user who started the submission.

The logged in user is not to be confused with a Django user, but the user stored in the session under FORM_AUTH_SESSION_KEY after logging in for a particular form.

The session details are compared against submission.auth_info. A match happens when the same auth plugin and identifier are present on both.

Callers must verify that:

Returns True if there’s a match, and False otherwise.

Plugin developer reference

See the Python API.

Available implementations

The following plugins are available in Open Forms core.

Demo, DigiD Mock, Outage

Demo plugins, available only to admin users and when demo plugins are enabled in the configuration. They allow simulating various login mechanisms without requiring a real integration.

DigiD

Provides DigiD integration via the SAMLv2 standards. Implemented throught the library django-digid-eherkenning.

eHerkenning and eIDAS

Provides eHerkenning and eIDAS integration via the SAMLv2 standards. Implemented through the library django-digid-eherkenning.

DigiD and eHerkenning/eIDAS via OpenID Connect

DigiD, eHerkenning and eIDAS support through the OIDC protocol rather than SAML. Depends on an OpenID Connect provider that implements the SAML flows under the hood. Implemented throught the oidc flavour of the django-digid-eherkenning library.

Organisation (OIDC)

Provides authentication for staff users through their organisation single-sign on. Shares the OpenID Connect configuration for the admin login option, but is exposed to form authentication as well.

Yivi (OIDC)

Yivi authenticates based on attributes (which could be a bsn or kvk-number) disclosed by the end users. As a consequence, we cannot know beforehand which specific claims will be received after authentication.

Configuration is done in the admin via Configuratie > OIDC Clients and then yivi-oidc.

Note

End-users must have the Yivi app installed on their phone.

Warning

Due to technical reasons, Yivi support is currently only available through Signicat.

Form specific configuration

When configuring the Yivi plugin, in the form builder, you can specify which authentication options are available during login (bsn, kvk and/or pseudo) and which additional attributes should be requested from the user. See openforms.authentication.contrib.yivi_oidc.config.YiviOptionsSerializer for details.

Requesting attributes using the condiscon system

Condiscon is a Yivi-specific way of defining the authentication attributes to request from users. With condiscon you define a multi-layer conditional data structure, which provides users more control over which attributes they do and don’t provide.

openforms.authentication.contrib.yivi_oidc.config.YiviOptionsSerializer.authentication_options and openforms.authentication.contrib.yivi_oidc.config.YiviOptionsSerializer.additional_attributes_groups determine which attributes to include in the condiscon parameter.

openforms.authentication.contrib.yivi_oidc.oidc_plugins.YiviPlugin.get_extra_params() retrieves the authentication backend options and adds the attributes to the authentication request.

As the condiscon scope is form-specific, we need to modify the authentication request scopes dynamically. The scope is shaped following the Signicat parameters scope standard.

Note

Important notes about the Yivi attributes and condiscon!

  • For the Yivi authentication to be successful, at least one attribute needs to be disclosed.

  • The order of optional disjunction matters. Make sure that the “empty” option is the last item in the disjunction list.

    Example of a valid optional disjunction:

    [
      [
        ["pbdf.pbdf.diploma.degree"],
        [],
      ]
    ]
    

Authentication result

Which authentication value (bsn, kvk or pseudo) is returned by the plugin depends on the form-specific configuration, and the data provided by the user.

To determine which authentication option was used you have to check the returned claims. This is done by the _get_user_chosen_authentication_attribute() function; it checks the returned claims against the configuration for bsn and kvk claims. If they match, then we know if the user logged in using bsn, kvk or anonymous/pseudo.

Generic OIDC support

The current Yivi setup is limited to Signicat condiscon. For generic OIDC support we need to investigate how other identity providers work with Yivi.

In this context, “generic OIDC” means the normal way of working with OIDC, similar to how DigiD and eHerkenning via OIDC work. Instead of one gigantic bundled scope, you provide individual scopes for the claims you want to be fulfilled.

(This way of working might result into losing the major strength of Yivi; that the user can choose what data they provide.)

Generic OIDC authentication with Signicat

One piece of the puzzle: generic OIDC authentication via Signicat.

Besides the condiscon scope, Signicat also supports generic OIDC authentication. With the generic OIDC authentication you don’t provide a single scope that results in multiple claims; rather, you pass each Yivi attribute as an individual scope item.

For example, the following scope will request the bsn and fullname of a user:

scope: "openid irma-demo.gemeente.personalData.bsn irma-demo.gemeente.personalData.fullname"

Whether other identity providers work similarly is yet to determine.

Reference

Plugin for Yivi authentication

Website: https://yivi.nl/

For development, we can use the Yivi demo attribute sets: https://attribute-index.yivi.app/en/irma-demo.html.

See the project documentation for more information about Yivi authentication.

class openforms.authentication.contrib.yivi_oidc.config.YiviOptionsSerializer(*args, **kwargs)
class openforms.authentication.contrib.yivi_oidc.plugin.YiviOIDCAuthentication(identifier: str)
auth_info_to_auth_context(auth_info: AuthInfo) YiviContext

Plugin custom auth info to auth context handling.

This will be executed during the AuthInfo to_auth_context_data when manage_auth_context is set to True.

check_requirements(request: AnyRequest, options: YiviOptions) bool

Check if the request meets requirements

configuration_options

alias of YiviOptionsSerializer

verbose_name: StrOrPromise = 'Yivi via OpenID Connect'

Specify the human-readable label for the plugin.

class openforms.authentication.contrib.yivi_oidc.oidc_plugins.plugins.YiviPlugin(identifier: str)
get_extra_params(request: HttpRequest, extra_params: GetParams) GetParams

Return (additional) GET parameters for the redirect to the identity provider.

By default, the passed in extra_params are returned unmodified.

Parameters:

extra_params – A mapping of query parameters already produced by mozilla_django_oidc_db.views.OIDCAuthenticationRequestInitView.

get_or_create_user(access_token: str, id_token: str, payload: JSONObject, request: HttpRequest) AnonymousUser

Return a “fake” Django user.

If the claims are valid, we only process them and do not create or update an actual Django user.

get_schema() JSONObject

Return the JSON Schema definition for the client configuration options.

Each plugin provides certain behaviour that may have configuration parameters. The configuration parameters are stored in the options JSONField of the OIDCClient model.

The admin integration needs a JSON Schema definitions to be able to configure and validate the options when editing the client configuration.

handle_callback(request: HttpRequest) HttpResponseBase

Return an HttpResponse using a specific callback view.

Typed as HttpResponseBase because that’s the annotation for View.as_view() in django-stubs.

For example:

def handle_callback(self, request: HttpRequest) -> HttpResponseBase:
    return admin_callback_view(request)
validate_settings() None

Check the validity of the settings in the provider and client configuration.

Raises:

ImproperlyConfigured – if invalid configuration is detected.