Set up an OpenID Provider

Introduction

VII Extensions including the OIDC Bridge allow customers to augment their existing identity management infrastructure. Using the OIDC Bridge, an OIDC Credential Issuer can be configured to leverage an existing OIDC Provider in order to authenticate users and provide the information needed to generate verifiable credentials and make them available to an end-user's digital wallet. If you are unfamiliar with OpenID Connect (OIDC), there are many excellent guides available online.

In order to issue your first custom verifiable credential, you will first need to configure a standard OpenID Provider (OP) that will become a federated provider for the OIDC Bridge.

OpenID Providers

You are free to use any OpenID Provider as long is it supports the following capabilities specified by OpenID Connect Core and OpenID Connect Discovery:

  • Must publish the OpenID Provider configuration at /.well-known/openid-configuration

  • Must support Authorization Code flow

  • Must support the state parameter

These are required to allow the OIDC Bridge to federate out to your OP and accept an ID Token containing the end-users claims.

This guide will step you through:


Using an existing OpenID Provider

Follow a few steps to make sure your OpenID Provider is setup:

  1. Make sure your OpenID configuration is discoverable. Browse to https://<your-host-domain>/.well-known/openid-configuration and check the following values exist (other options may validly sit alongside):

json
Copy to clipboard.
1
2{
3  "authorization_endpoint": "https://your-auth-endpoint/auth",
4  "token_endpoint": "https://your-token-endpoint/token",
5  "jwks_uri": "https://your-jwks-endpoint/jwks",
6  "response_types_supported": ["code"],
7  "grant_types_supported": ["authorization_code"],
8  "token_endpoint_auth_methods_supported":["client_secret_basic"],
9}

This is an example OpenID configuration from Google.

2. Setup a client on your OP. At this stage you have to use an example callback URL (also known as the redirect_uri) e.g. https://example.com/callback also make note of client_id and client_secret.

The callback URL will need to be updated once the OIDC Bridge Issuer has been configured.

3. If you intend to use any additional scopes, make note which scopes are required to invoke Claims you want to retrieve from your user profile system. Common ones include openid, profile and email.

4. Try it out by running a manual test against your OP and inspecting the resulting ID token.

---

Set up a new OpenID Provider

For the purpose of this tutorial, we will utilize a cloud-based identity management solution, Auth0. You can also find the guidelines for setting up:

We'll cover the basics of OpenID Provider configuration, show how Auth0 expose the underlying user profile store, and demonstrate how data can be added to their ID token.

Prerequisites

First sign up with Auth0 or login if you already have an account.

Configure Auth0

For this exercise, skip the Auth0 onboarding tutorials and go straight to your dashboard.

Create a new application

1. Name it something meaningful

We will be connecting to a 'regular web application'.

https://www.datocms-assets.com/38428/1621224379-auth0-create-app.webp?auto=format

2. Skip the 'Quick Start' and navigate to the 'Settings' tab.

Make note of the:

- Domain

- Client ID

- Client Secret

Edit these fields:

  • Add a simple description

  • In the 'Allowed Callback URLs' section add in https://example.com/callback. This will be used later during the manual testing.

The callback URL will need to be updated once the OIDC Bridge Issuer has been configured.

All other fields can be left at their default values.

https://www.datocms-assets.com/38428/1621224547-auth0-app-settings.webp?auto=format

3. Make sure your OpenID Configuration is discoverable by browsing to https://<your-auth0-domain>.auth0.com/.well-known/openid-configuration and checking that the following values exist (other options may sit alongside):

json
Copy to clipboard.
1{
2  "authorization_endpoint": "https://your-auth-endpoint/authorize",
3  "token_endpoint": "https://your-token-endpoint/token",
4  "jwks_uri": "https://your-jwks-endpoint/jwks.json",
5  "response_types_supported": ["code"],
6  "grant_types_supported": ["authorization_code"],
7}

Set up a connection and add users

This is where Auth0 is used to store and hold user information, including PII. Before you add details about users, make sure you understand Auth0's policies around storing this information.

In 'Connections'

  • Leave Database and Username-Password-Authentication Enabled

  • Disable the Social login

In 'Users & Roles'

Create user:

  • Provide an email address that is different to the Admin account used to sign up with Auth0

  • Add a password

  • Leave Connection as 'Username-Password-Authentication'

  • Optional: you may want to update the default `Name` field from just being the email address to something more meaningful.

In details for the new user:

This is where we can add in additional information about a user to appear in the ID token that will ultimately will appear in the issued Verifiable Credential.

⚠️ Warning
Auth0 restricts the size of the ID Token to 100Kb. Ensure that the data you inject into your token is below this limit or credential issuance will fail.

  • Scroll down to user_metadata

  • Add claims about the user that you want to see represented in the ID token.

For example:

json
Copy to clipboard.
1{
2  "educationalCredentialAwarded": "Certificate Name"
3}

In 'Auth Pipeline -> Rules'

Create a new rule:

  • Start with an empty rule

  • Give it a meaningful name

  • For each attribute in the user_metadata add a mapping to an ID token claim

N.B. Auth0 enforces a namespace for custom claims. Use the full domain of your MATTR tenant.

Example code:

javascript
Copy to clipboard.
1function (user, context, callback) {
2  const namespace = 'https://YOUR_TENANT_URL/';
3  context.idToken[namespace + 'educationalCredentialAwarded'] = user.user_metadata.educationalCredentialAwarded;
4  callback(null, user, context);
5}

https://www.datocms-assets.com/38428/1621224614-auth0-edit-rule.webp?auto=format

Try it out

Before we connect to the OIDC Bridge, let's test the OpenID Provider configuration.

In a new browser window, navigate to the /authorize endpoint for your OpenID Provider instance with the standard OIDC query parameters:

  • Use the URL of the authorization endpoint defined in the /.well-known/openid-configuration

  • The client_id which will relate to the client application setup on your OP (you will need the client_secret later)

  • Use the value you added in the allowed callback URLs https://example.com/callback and the redirect_uri

  • The values in scope, response_type, state, nonce, prompt are all required and can be used as per the example

http
Copy to clipboard.
1https://auth0-tenant.au.auth0.com/authorize
2?scope=openid%20profile
3&response_type=code
4&client_id=<your_client_id>
5&state=xqw2Lcafhx0NIoX0
6&nonce=kjfhuo34hPxksklj
7&prompt=login
8&redirect_uri=https://example.com/callback

Authenticate with the OP using a user that you have set up.

Example Auth0 login page

https://www.datocms-assets.com/38428/1621224642-auth0-login-500xauto.webp?auto=format

The redirect will terminate, however you can still retrieve the code from the query parameter:

http
Copy to clipboard.
1https://example.com/callback?code=oLxCRk2oPgfR8QU3&state=xqw2Lcafhx0NIoX0https://example.com/callback?code=oLxCRk2oPgfR8QU3&state=xqw2Lcafhx0NIoX0

Token request

Construct a request to the /token endpoint of your Auth0 tenant:

  • Use your client_id and client_secret from the Auth0 account to create an authorization header encoded with Base64 -- the string should be formatted as client_id:client_secret prior to being encoded.

  • grant_type is authorization_code

  • Use the code value captured from the above redirect -- this is time sensitive, you have about 5 mins!

  • Use the same redirect_uri as used in the request

shell
Copy to clipboard.
1curl --request POST \
2  --url https://auth0-tenant.au.auth0.com/oauth/token \
3  --header 'Content-Type: application/json' \
4  --header 'Authorization: Basic dkowU0NLY2hyNFhqQzB4SE5FOERrSDZQbWxnMmxrQ046UU53ZmE0WWk0SW05enkxdV8xNW43U3pXS3QtOUc1Y2RIMHIxYk9OUnBVUGZOLVVJUmFhWHZfOTB6OFY2LU9qSA==' \
5  --data-raw '{
6    "grant_type": "authorization_code",
7    "code": "oLxCRk2oPgfR8QU3",
8    "redirect_uri" : "https://example.com/callback"
9}'

Response

The response from /token includes the id_token.

json
Copy to clipboard.
1 {
2    "access_token": "-vtm3ahlh9k_V2uDjnZ5r2MPbKRaHpA1",
3    "id_token":  "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlJUVXdOVEpCTXpJNFJUTTNNVGt4TURnNU5EVTJRamRETlRVNVJrWTNNamMyTTBWRU1FVkJPUSJ9.eyJodHRwczovL215dGVuYW50Lm1hdHRyLmdsb2JhbC90cmFpbmluZ0NlcnQiOiJQYXNzZWQgQSsiLCJuaWNrbmFtZSI6Im1lIiwibmFtZSI6Im1lQGVtYWlsLmNvbSIsInBpY3R1cmUiOiJodHRwczovL3MuZ3JhdmF0YXIuY29tL2F2YXRhci84ZjlkYzA0ZTZhYmRjYzlmZWE1M2U4MTk0NWM3Mjk0Yj9zPTQ4MCZyPXBnJmQ9aHR0cHMlM0ElMkYlMkZjZG4uYXV0aDAuY29tJTJGYXZhdGFycyUyRm1lLnBuZyIsInVwZGF0ZWRfYXQiOiIyMDIwLTA0LTMwVDA3OjUxOjA4Ljk0MloiLCJpc3MiOiJodHRwczovL2Rldi1yb2w0d29hby5hdS5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NWU2NmVjZjZlNWNjZjUwY2QwMDNmZjIwIiwiYXVkIjoidkowU0NLY2hyNFhqQzB4SE5FOERrSDZQbWxnMmxrQ04iLCJpYXQiOjE1ODgyMzQwNzEsImV4cCI6MTU4ODI3MDA3MX0.KLrMUoqz5mrvNQQ3K09eFijVg3qkmT17R_zOUvVhtfC8LvUWaBYpszQ7j3x3zCZ1TsS4ATS68kcxLfSbq7A71atYVzwjKvGwGce9IjH7cRKyIO8Z1RAcSCw7ncXBOzT_O20sH3BV_ZgPHEJA2PreKQERKjcKSCHJeRaPyqVbh2v2lSHYCm6e8HdB8v_Zq0looLvxS5afQ8PMn3k36COo13F4zvLuUn9is--B-SRUqUjSX6-KOvULa1HXbQVnO6RUNiijQSbN-ZLA_6TRQC8BKoT3-8v1cLSb49sZOXGSBHkkNHGBhMXeJuw4iD8IjYQWpcXlVRQHuCQwFgSHxdez9w",
4    "scope": "openid profile",
5    "expires_in": 86400,
6    "token_type": "Bearer"
7}

Copy the id_token value and paste it into a tool like jwt.io to inspect the payload of the ID token.

You should see;

  • Any default claims associated with the scopes provided and any fully name-spaced claims -- these will be important when setting up your claim mappings

  • The sub value is also an important field that will be used in credential issuance

  • The nonce value provided in the original request

json
Copy to clipboard.
1{
2    "https://YOUR_TENANT_SUBDOMAIN.vii.mattr.global/educationalCredentialAwarded": "Certificate Name",
3    "nickname": "me",
4    "name": "My Full Name",
5    "updated_at": "2020-04-30T07:51:08.942Z",
6    "iss": "https://dev-rol4woao.au.auth0.com/",
7    "sub": "auth0|5e66ecf6e5ccf50cd003ff20",
8    "aud": "vJ0SCKchr4XjC0xHNE8DkH6Pmlg2lkCN",
9    "iat": 1588234071,
10    "exp": 1588270071,
11    "auth_time": 1606723358,
12    "nonce": "kjfhuo34hPxksklj"
13}