NAV Navbar
kotlin

Trinity: Overview

The Trinity product is split into two parts; the Trinity backend services and the Trinity SDK. They enable the implementation of an OpenID connect service provider while respecting Self-sovereign identity principles in a novel (patent pending) privacy and user consent preserving process, while limiting the profiling possibilites of the operator and catapulting user data protection to a whole new level. It can be used to build modern single-sign on applications to initiate data verification, authentication and trust in the user on the highest level.

The protocol behind the product integrates modern cryptographic techniques to guarantee data integrity and encryption between the user and client applications end-to-end.

How does it work


  1. A client initiates an OIDC authorize request against the Trinity Backend service
    • This request also specifies the data to be verified and the authentication factors to be executed (see Claims)
  2. In the case of a web application frontend client, the Trinity backend service presents a QR-code to the user
    • The QR-code contains a session identifikator which the SDK then translates to all necessary information to resolve the authorize request
  3. The user opens the authenticator app which includes the integrated Trinity SDK
    • Along with that, the user authenticates at the device using a PIN
  4. The app scans the QR-code and passes the result to the SDK
    • QR code scanning is not part of the SDK so that you can choose the library and integration which is most suitable for your app. There are various components with different (also free) licensing models available, so you can take the most suitable. The result of the QR code has to be passed AS-IS to the SDK. All additional handling is done by the SDK.
  5. The SDK now starts the verification and authentication processes involving the required and selected issuers (IDNow, Authada, Twilio, etc. or even custom ones)
    • Along this process, there are multiple points with interactions with the user which are not displayed in the diagram. These interaction points can be tailored to fit the layout of your application.
    • The interaction points are:
    • Initial consent to start the process
    • Executing the actual verification or authentication
    • Final consent to send the requested information and proceed with the process
  6. On successful response, the Trinity backend service will perform the redirect to the redirect_url along with information according to the requested response type.

To summarize, your client should use standard OIDC following the Authorization Code Flow with PKCE, while on the mobile side (your authenticator app), you need to interact with the SDK.

Key technical features

Getting Started

When you're getting started with the Trinity software components, you are probably going to be in either of the following three positions:

  1. You want to enable your app developers to integrate the Trinity functionalities by providing the matching backend → Backend Hosting
  2. You want to extend your existing app to an Authenticator App with the Trinity functionalities → SDK Integration
  3. You want to build a client which uses the Trinity Backend as an OpenID Provider (Authorization and Ressource Server) → Client Development & Client Registration

(If we've missed any of your interests, kindly let us know ☻)

To be capable to tryout the Trinity ecosystem in a fully fledged and logical manner, we recommend the following implementation order:

  1. (If not already, get familiar with OAuth/OIDC)
  2. Setup the Trinity Backend services
  3. Integrate the Trinity SDK into your app
  4. Build a client and play through your login flow end-to-end

If you're not interested in setting up your own Trinity Backend services, we're happy to provide you with a testing enviroment upon request at support@comuny.de.

Backend Service

You can choose to self-host our services in a Kubernetes cluster or to use our production environment.

Self-hosting (GCP & AWS)

For a fully fledged step-by-step tutorial on how to setup the Trinity backend on Google Cloud or AWS, please contact support@comuny.de.

Endpoint Documentation

The endpoints of the backend are split into the following parts, which currently are bundled into two separate Kubernetes services (OIDC service & modules service):

  1. Standardized OpenID Connect Endpoints → OIDC service
  2. REST API to communicate with the SDK → modules service
  3. Custom modules to communicate with Issuers and the SDK → modules service
  4. Management API to ease the life of the operator for Client invitations, key rotations, etc. → OIDC service

The documentation of the modules service should not be of relevance to any normal integrator, since these endpoints are all abstracted by the Trinity SDK.

Client Development


The Trinity OIDC backend service behaves as every other OIDC (or OAuth 2.0) provider and can be integrated accordingly. On your website, application or backend service, you have to initiate the authorization code flow with PKCE in order to receive an ID Token, Access Token and the UserInfo. There are various (certified and uncertified) libraries available that help you with different frameworks.

Framework Library
generic Javascript oidc-client-js
Angular2+ angular-oauth2-oidc
Angular2+ angular-auth-oidc-client
React react-oidc
Vue.js vue-oidc-client
Spring Spring security oauth
.NET OidcClient

You can find even more implementations at the OpenID homepage.

Client Registration

Before you can get started with the actual implementation of your client, you will need to register at the Trinity OIDC backend service.

The following endpoints are implemented for registration:

Endpoint Status URL / comment
registration_endpoint https://oidc.cls.comuny.de/oidc/v1/register - requires initial access token
registration_client_uri https://oidc.cls.comuny.de/oidc/v1/register - Use the value provided in the registration response - this endpoint definition is just for reference

Gaining access

In order to use the full functionality of the API, a client has to be registered using OpenID Connect Dynamic Client Registration.

Initial Access Token

Registration requires an initial access token. This token is valid for two days and can only be used for a single registration. In order to request a token, send a mail to devops@comuny.de.

For a self-hosted environment, the Client Invitation Management Endpoint (GET) /oidc/v1/management/invite_client?email=lorem@ipsum.com also provides the functionality to issue initial access tokens, protected by a Basic Authentication Header as specified in the Endpoint protection section.

You will receive the token in plaintext to your specified email. This token can then be used as a Bearer Token in the Authorization Header of your Registration Request.

curl -X POST "https://staging-gke.oidc.cls.comuny.de/oidc/v1/register" -HAuthorization: Bearer <INITIAL_ACCESS_TOKEN>" "-H "accept: application/json" -H "Content-Type: application/json" -d "{\"redirect_uris\":[\"https://your_url\"]}"
{
  "client_id": <YOUR CLIENT ID>,
  "registration_access_token": <YOUR TOKEN>,
  "registration_client_uri": <YOUR CLIENT URI>,
  "client_id_issued_at": 1592205743
}

Client Registration request

The registration endpoint is (as specified in the discovery response): https://oidc.cls.comuny.de/oidc/v1/register . The endpoint behavior matches the OIDC standard. The minimal request only requires providing redirect_uris.

If you want to ensure an end-to-end encryption on datalayer (i.e. encypted ID Token and UserInfo) as a JWE response to your client from the UserInfo and Token Endpoints, please provide a public-key as either a jwks_uri or jwks in the client registration body. For further details, see Encryption and Signing.

To test your client against a local setup, please set the application_type to native as this will allow localhost in redirect_uris.

The response contains some crucial information you need to store:

Field Content
client_id This ID has to be used for any authorization request. It is auto-generated by our backend and does not contain any information about your service in itself.
registration_access_token Use this token for updating client information. Your service information cannot be updated without this access token.
registration_client_uri URI you have to use to update your information. While the format of the URI is predefined, per standard this value has to be used to ensure consistency.

Configuration

Next to the initial registration, a client configuration can be updated at any time. The configuration URL is part of the registration response. Both configuration retrieval (GET) and updates (POST) are supported.

GET

As per OIDC standard, this endpoint has to return all information we store of the client. Thus it contains both your registration data as well as the registration response.

A side effect of this call is the creation of a new access token. Every following call has to use this new access token.

POST

This endpoint can be used to change the configuration of a client. The request matches the one for registration. There are some aspects that need to be considered when updating the client configuration:

On any kind of conflict, a user is usually redirected to a login (based on your client application), so there is always a recovery for an impacted session.

A POST requires the client access token as Bearer token for authentication purposes.

Parameter specification

Encryption and Signing

This service supports encryption and signing of both ID tokens as well as userinfo.

For both signing and encryption, the following constraints apply: - only asymmetric algorithms are supported - 'NONE' is never supported - only values of RFC 7518 are supported - claims are only submitted when encryption is specified

All supported signing and encryption values can be retrieved over the configuration endpoint.

To achieve a valid encryption, we need to know your public-key. This can be specified in the JSON body during the Client Registration request or in the Client Configuration.

curl --location --request POST 'https://oidc.cls.comuny.de/oidc/v1/register' \
--header 'Authorization: Bearer <INITIAL_ACCESS_TOKEN>' \
--header 'Content-Type: application/json' \
--data-raw '{   
    "application_type": "native",
    "client_name": "test client",
    "redirect_uris": [
        "http://localhost:5443/callback"
    ],
    "jwks": {
        "keys": [
            {
                "kty": "RSA",
                "e": "AQAB",
                "use": "enc",
                "kid": "test client",
                "n": "<RSA-PUBLIC-KEY>"
            }
        ]
    },
    "userinfo_encrypted_response_alg" : "RSA1_5",
    "userinfo_encrypted_response_enc" : "A256GCM",
    "allow_unencrypted_userinfo": false
}'

Data protection is crucial for us. We never want to be able to see any user data. To protect you, your customers but also us from ever coming into this situation, we only transmit user data when a valid encryption is specified. For the same reason, we limit algorithms to asymmetric ones.

JWKS content

The keys supplied by the jwks parameter or retrieved by the jwks_uri are validated before they are applied. The following constraints are applied:

If no JWKS/JWKS URI was provided or, after filtering and sanity checking, there is no valid key left that can support the specified encryption a registration/configuration request will be rejected.

You can add certificate-related claims to your JWKs (x5c, x5u, x5t, x5t#S256). Adding these will result in a basic validation of the certificate:

As specified above, only asymmetric algorithms are supported. When a symmetric algorithm is specified, this will be rejected. The supported algorithms can be retrieved via the service's discovery.

If you want to allow for an unencrypted UserInfo, please specify the allow_unencrypted_userinfo as true during client registration or configuration.

Management Endpoint

This endpoint contains useful management functionalities for self-hosted Trinity backend instances.

Endpoint protection

The endpoint is secured by basic authentication with a username and password. The credentials can be set in the application.properties file found in the root-folder by changing the comuny.management.user and comuny.management.password properties. This user will automatically be assigned the MANAGEMENT role.

Client Invitation

As already mentioned in the Initial Access Token section, the Client Invitation Management Endpoint (GET) /oidc/v1/management/invite_client?email=lorem@ipsum.com can also be used to deliver an Initial Access Token to an email address. This requires the basic authentication specified above. The Initial Access Token will be delivered to the email in plaintext and can subsequently be used for the Client Registration request.

curl --location --request GET 'https://oidc.cls.comuny.de/oidc/v1/management/invite_client?email=<EMAIL-TO-BE-INVITED>' \
--header 'Authorization: Basic bWFuYWdldjpzdXAxcnNzY3IzdA=='

Requesting Claims

curl 'https://oidc.cls.comuny.de/oidc/v1/authorize?response_type=id_token%20token&client_id=<YOUR_CLIENT_ID>&state=<STATE>&redirect_uri=http%3A%2F%2Fihr-dienst.de%2Findex.html&scope=openid%20oidc&nonce=<NONCE>&claims=%7B%22userinfo%22%3A%7B%22comuny.ver.mobile.l2%22%3A%7B%22essential%22%3Atrue%7D%7D%7D'

Verified data or authentication factors are requested as member of the userinfo top-level member of claim request parameter (see OIDC specification). The parameter has to be a valid JSON and must be URL-encoded in order to send it as part of the request URL.

Authentication claims which facilitate verified data, e.g. an OTP, do not include the actual data but a proof of execution.

Claim syntax

Beside the supported OIDC standard claims, every other custom claim for TBS starts with comuny, followed by whether it's a verification of authentication claim, so:

Every claim has to be followed by an object. The options are:

{
  "userinfo": {
    "comuny.ver.mobile.l2": { "essential": true },
    "comuny.ver.idcard.l3": null
  }
}

If multiple claims are specified with essential: true , all of them have to be provided by the user.

Specifying alternatives

You can specify alternatives on all hierarchies of the claim below ver and auth using an array syntax. This syntax can be nested.

{
  "userinfo": {
    "comuny.ver.[mobile,email].l2": { "essential": true },
    "comuny.ver.idcard.l2.[video,nfc]": { "essential": true },
    "comuny.ver.[driverslicense.l2.nfc,idcard.l2.[video,nfc]]": { 
      "essential": true
    }
  }
}

You can specify that you want to have alternative data sets, but all with verification level 2, by setting an array on the data set hierarchy, e.g. requesting either email or mobile.

Within a data set and level, you can specify alternative procedures to verify the data set, so e.g. use Video Identification (video) or NFC (nfc)for verifying an ID card. The user now can choose which procedure they want.

Alternatives can be encapsulated within each other. So you can specify that you either want to have a driver's license with NFC (driverslicense.l2.nfc)or an idcard with NFC (idcard.l2.nfc)or Video (idcard.l2.video).

Client Endpoints

The Client Endpoints adheres to the OIDC standard. The exact specification can be taken from the swagger documentation. It includes parameter descriptions and examples.

TBS implements OpenID connect discovery on https://oidc.cls.comuny.de/oidc/v1/.well-known/openid-configuration. See the examples and sample response in the Swagger documentation for this endpoint .

The result of the discovery endpoint is the most accurate representation of the current state. This state is verified before every release of the service. If in doubt, the discovery endpoint reflects the truth.

Implemented OIDC endpoints:

Endpoint URL
discovery https://oidc.cls.comuny.de/oidc/v1/.well-known/openid-configuration
JWK Set https://oidc.cls.comuny.de/oidc/v1/jwks.json
authorize https://oidc.cls.comuny.de/oidc/v1/authorize
userinfo https://oidc.cls.comuny.de/oidc/v1/userinfo
token https://oidc.cls.comuny.de/oidc/v1/token
end_session https://oidc.cls.comuny.de/oidc/v1/end_session
registration_endpoint https://oidc.cls.comuny.de/oidc/v1/register

The API documentation contains a more detailed description of the endpoints.

IAM integration


You can also extend and integrate existing IAM solutions to delegate parts of the process to TBS. As TBS is full OIDC compliant, this usually works without any custom code but with plain configuration. A high-level architecture, using keycloak as example, is in the right column. Here's a list of some IAM solutions and their configuration for external identity providers:

IAM Documentation for connecting an external identity provider
Keycloak identity brokers
okta external identity providers

Mobile Integration

The Trinity SDK is a native component which can be integrated into your app. Repositories are hosted on GitLab and are access protected. To receive access to the code you need a signed License agreement. Contact support@comuny.de to receive the licensing terms. Once the license was approved, send a mail to devops@comuny.de including the GitLab accounts of engineers which require access to receive access.

Native Documentation

Under the following links you find the collection of native functions for iOS & Android to integrate the Trinity SDK into your iOS or Android Application(s).