Skip to main content

Sources

Sources are the starting point of a connector. They contain the configuration for the source.

Sources can be of different types:

Authentication on sources

In order to authenticate on other sources there are possibilities based upon the way the source expects autentication parameters. These parameters can be set in the source configuration. For example, if the source expects an API key in the headers, we can set the parameter headers.Authorization with the API key as value.

[!TIP] Prefer brokered credentials. Instead of embedding a key or secret in the source, set configuration.authentication to {"credentialRef": {"credentialId": "<uuid>"}} (or {"credentialName": "<name>"}) and let the OpenRegister credential broker hold the secret and perform the call — Integriq never sees the secret. When credentialRef is present, any sibling authentication field is a hard 409 config error, and there is no fallback to embedded secrets. See Sources — Brokered Credentials for the full contract and operator recipe.

Usually, sources tend to use dynamic authorization parameters in order to prevent the same authentication parameter from being used by adversaries that catch a call and deduce the parameter.

At the moment, Integriq supports two dynamic authentication methods, OAuth and JWT Bearers.

OAuth

To use OAuth we put in our Authorization header the following value:

Bearer {{ oauthToken(source) }}

This will impose an OAuth 2.0 access token after Bearer if the source's configuration.authentication object contains correct values. Integriq supports the OAuth 2.0 protocol with client credentials and password credentials as grant_types.

[!WARNING] These parameters go in configuration.authentication, NOT in the top-level authenticationConfig field. oauthToken(source) reads source.configuration.authentication — it has done so since November 2024, when AuthenticationRuntime stopped reading authenticationConfig. This page previously said otherwise. Nothing reads authenticationConfig, so a credential placed there is inert and the call goes out unauthenticated.

Audit any leftover data (key names only, never values) with occ integriq:authentication-config, then remove it with occ integriq:authentication-config --remove-authentication-config. See ocon#232.

When using OAuth, Integriq supports the following parameters:

Standard parameters

  • grant_type: The type of grant we have to use at the source. Supported are client_credentials and password
  • scope: The scope(s) needed to perform the requests we want to do in the API.
  • tokenUrl: The URL used to fetch the actual access token. Usually this url can be recognised by its path ending on /oauth/token
  • authentication: Location of the credentials, either body for credentials included in the request body, or basic_auth when the credentials have to be sent as a basic_auth header.

    Only used when grant_type is client_credentials

  • client_id: The client id of the OAuth client

    Only used when grant_type is client_credentials

  • client_secret: The secret for the OAuth client

    Only used when grant_type is client_credentials

  • username: The username for the OAuth client

    Only used when grant_type is password

  • password: The password for the OAuth client

    Only used when grant_type is password

This results in the following example:

{
"grant_type": "client_credentials",
"scope": "api",
"authentication": "body",
"tokenUrl": "https://example.com/oauth/token",
"client_id": "test-client",
"client_secret": "some secret value"
}

Custom parameters

[!WARNING] Custom parameters are currently in beta, it is not recommended to use them in production environments.

At the moment, Integriq is tested with the following custom parameters:

  • client_assertion_type, only meaningful at the moment when value is set to urn:ietf:params:oauth:client-assertion-type:jwt-bearer. When this is set (for Microsoft authentications) the following fields are needed to generate the client-assertion-field

    • private_key: The base64 encoded private key of the certificate uploaded to Microsoft.
    • x5t: The base64 encoded sha1 fingerprint of the uploaded certificate, generated by running the following command:
    echo $(openssl x509 -in certificate.crt -fingerprint -noout) | sed 's/SHA1 Fingerprint=//g' | sed 's/://g' | xxd -r -ps | base64`)
    • payload: The payload of the JWT generated as client_assertion, this can contain Twig variables to render, for example to set timestamps in the JWT payload.

JWT Bearer

A second supported way of using dynamic authentication is setting a JWT Bearer. This means setting a header or query parameter with a JWT token.

This can for example be used by setting an Authorization header with the following value:

Bearer {{ jwtToken(source) }}

This will impose a JWT token after the bearer. For this, the source's configuration.authentication object (NOT the vestigial top-level authenticationConfig field — nothing reads that; see the warning above) needs to contain the following fields:

  • algorithm: The algorithm that should be used to generate the JWT. Supported are HS256, HS384 and HS512 for HMAC algorithms, RS256, RS384, RS512 and PS256 for RSA algorithms.
  • secret: The secret used for the JWT. This can either be a HMAC shared secret, or a RSA private key in base64 encoding.
  • payload: The payload of your JWT, json_encoded.

This results in the following example for the configuration.authentication object in i.e. an OpenZaak source.

{
"algorithm": "HS256",
"secret": "YOUR_256BIT_(32BYTE)_HMAC_SECRET",
"payload": "{\"iss\":\"my_zgw_client\",\"iat\":{{ 'now'|date('U') }},\"client_id\":\"my_zgw_client\",\"user_id\":\"my_zgw_client\",\"user_representation\":\"me@company.com\",\"aud\":\"my_zgw_client\"}"
}

Digital post on a source

A source of type digitalPost sends letters. Which service it sends them through is one field: configuration.provider.

Pick it on the source form. The picker lists what this instance actually carries, because it reads GET /apps/integriq/api/digital-post/providers rather than a list written beside it. A binding added to the registry shows up without anybody editing the form, and a binding that is gone stops being offered.

Three bindings ship today:

  • log writes the letter to the log and delivers nothing. Use it to try a flow without posting anything to a citizen.
  • berichtenbox posts to the recipient's Berichtenbox through Logius. It needs an OIN and a certificate reference, and refuses to activate without both, naming the one that is missing.
  • postex posts through Postex, over the shared gateway transport.

Each binding describes the settings it needs through its own config schema, so the fields under the picker change with your choice.

If the picker says no binding is installed, none is: the instance carries no digital post provider and a letter cannot be sent from it. Install one, or point the source at an instance that has one.

Set configuration.provider to log first and send one letter. The log line tells you the source is wired before any credential is involved.