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:
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):
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'.
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.
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):
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:
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:
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}
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 theclient_secret
later)Use the value you added in the allowed callback URLs
https://example.com/callback
and theredirect_uri
The values in
scope
,response_type
,state
,nonce
,prompt
are all required and can be used as per the example
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
The redirect will terminate, however you can still retrieve the code
from the query parameter:
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
andclient_secret
from the Auth0 account to create anauthorization
header encoded with Base64 -- the string should be formatted asclient_id
:client_secret
prior to being encoded.grant_type
isauthorization_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
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
.
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 mappingsThe
sub
value is also an important field that will be used in credential issuanceThe
nonce
value provided in the original request
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}