This guide assumes that you have established a Service Provider (SP) relationship with Signicat. The first step to integrating using OpenID Connect (OIDC) is to request the configuration of an OIDC Client on your SP account. We ask that you provide the following as a bare minimum to get started:
- Client name: A human-readable name for your Client. End-users will be shown this name when the Client needs to be referred to in writing.
- Application type: Where will the client credentials be stored? In the source code of an app, or server-side? Please note that for security reasons, we highly recommend server-side integrations. Native app client implementations may be limited in the information returned after user authentication.
- One or multiple “redirect URIs”: This URI will be the endpoint where users are redirected after authentication, and should therefore point to the server where the client integration(s) are done. No wildcards are permitted. The URI should either use the “HTTPS” scheme or a custom one for app deep linking.
- Scope values: Your client may not have need of all the information an identity method can deliver. Best practice is to only request only the information that is needed at any given time. Please let us know what you need to know about your users when logging in.
Once this is done, Signicat will send you a Client ID and Client Secret pair. In addition, we will provide you with the “Authentication Context Class Reference (ACR) values” you can use to decide what authentication method your users should perform.
What about Client middleware/libraries?
Signicat does not recommend any particular library or midleware. A good starting point to find a library for a particular programming language is the official list of certified OIDC Relying Party libraries.
If you want to use an OAuth 2.0 or OpenID Connect Client library, most of the integration work ends here. Simply supply the client ID and client secret to the library, in addition to the redirect URI, scope values and ACR values you need. Lastly, the library needs to know where the Signicat OIDC server is. The library might prompt you for this in one of three ways, depending on its implementation:
- By requesting the “issuer ID”: The Signicat OIDC server has the Issuer ID “https://preprod.signicat.com/oidc” or “https://id.signicat.com/oidc” for preproduction and production respectively.
- By requesting the “authorization, token and userinfo: endpoints to use: These endpoints are on the same hostnames as mentioned above. For brevity, the three endpoints for preproduction only are noted below:
- By requesting the OIDC Discovery URI: This URI is “https://preprod.signicat.com/oidc/.well-known/openid-configuration” or “https://id.signicat.com/oidc/.well-known/openid-configuration” for preproduction and production respectively. Inputting this URI into the address bar of a browser yields a quantity of useful information about the OIDC server that is useful for advanced users as well.
This section will only mention URIs towards the preproduction infrastructure at Signicat, for brevity.
A basic OIDC Client implementation is a HTTP server capable of doing four things:
- Crafting an “authorization URI” to send end-users to for login.
- Receiving the “authorization response” when end-users are redirected to the “redirect URI” configured in the Set-Up phase.
- Doing a HTTP POST to the “token” endpoint to retreive access tokens
- Doing a HTTP GET to fetch the end-user info using the access token towards the “userinfo” endpoint
Crafting the Authorization URI
The authorization URI is a link provided to an end-user on a web page or similar to click on to start the OIDC authorization flow. It represents a request from your client to perform actions on the end-user’s behalf. In the most basic case, the action we want to perform is to fetch the user’s personal data.
Here is a sample authorization URI containing only mandatory parameters:
- response_type=code: This tells the OIDC server that it should get back to us with an authorization code when the user finishes this flow. The particulars of why is not important at this point.
- scope=openid+profile: The “scope” represents the access we want. The “openid” scope is mandatory in the Signicat infrastructure. It simply means that we are using the OpenID Connect protocol, and not the older OAuth 2.0 protocol. The “profile” scope represents access to the end-users basic personal information, like his full name.
- client_id=demo-preprod: This is the client ID as received from Signicat.
- redirect_uri=https://example.com/redirect: This is one of the redirect URIs supplied in the set-up stage. If multiple URIs were supplied, this is how one is specified. The OIDC server will redirect the user to this URI once the user has finished authenticating and authorizing the access for your client.
- state=123abc: The state will be stored and provided to your client when redirecting the user back to the redirect URI. It can be used for anything, but should contain a component whose validity is checked to ensure this client initiated the flow (for instance by setting a cookie in the user’s browser which is compared to the state at the redirect URI endpoint). This is very important to prevent XSRF attacks.
- acr_values=urn:signicat:oidc:method:idin: This acr_value indicates that the user should be authenticated through method iDIN, a dutch identity scheme. For other methods (or portals of methods) simply modify the acr_value with the desired method name.
Once the URI is crafted, you should get your users to access that URI, for instance by attaching it to a login button on your website. You may try the sample URI above now in your web browser. Select “success” from the dropdown menu and click “OK”. You should get redirected to the URI set in the “redirect_uri” parameter. Take note of the URI in the address bar. It has the state supplied in the authorization request and a “code”, which brings us to the next step.
Receiving the Authorization Response
If the request above had a redirect URI pointing at an endpoint controlled by your client, this client would now have received this request from the user, with the “code” and “state” as query parameters. For now, we do the server-side activities by hand to demonstrate how it works.
Doing a “token” request
We will use cURL to make HTTP requests from the command line:
curl -XPOST "https://preprod.signicat.com/oidc/token" -H "Authorization: Basic ZGVtby1wcmVwcm9kOm1xWi1fNzUtZjJ3TnNpUVRPTmI3T240YUFaN3pjMjE4bXJSVmsxb3VmYTg=" -d "client_id=demo-preprod&redirect_uri=https://example.com/redirect&grant_type=authorization_code&code=CODE GOES HERE"
Breaking it down:
- The request is a HTTP POST towards the “token” endpoint.
- The request has the “Authorization” header set. The value of the header is “Basic ” + base64(clientID + “:” + clientSecret)
- The request has the following URI-encoded parameters in the body of the request:
- client_id: Your client ID
- redirect_uri: Must equal the URI the flow started with
- grant_type=authorization_code: We are using an authorization code for this flow, hence the value of this parameter.
- code: This should equal the code received in the authorization response just now
If all goes well, you will receive a JSON response like the following:
The access token in the JSON is what is of interest at this point. Extract it. We will use it in the next step:
Doing a “userinfo” request
It is time to put the access token to use. We will use our newfound authorization in the form of an access token to fetch the user data we have been granted access to:
curl -XGET "https://preprod.signicat.com/oidc/userinfo" -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Breaking it down:
- The request is a HTTP GET towards the “userinfo” endpoint.
- The request has the “Authorization” header set. The value of the header is “Bearer ” + accessToken
You are done! After all these steps have been implemented into a server-side client, the basic integration is complete.
Now, customization can be done to improve data yield, security and UX. For instance:
- Replacing the Basic Authorization header with a more secure authentication method in the Token endpoint (Signicat supports all standard OIDC Client authentication schemes)
- Refreshing the access token on expiry
- Using and validating the ID token to get metadata about the user authentication
- Requesting specific claims and scopes
- Customizing the UX using a graphical profile
- Encrypting and/or signing the authorization request
- Enabling and implementing Single-Sign-On/Off
- Automatically configuring your OIDC Client through fetching current OIDC endpoints and signature keys using the OIDC Discovery endpoint
You can find an example implementation of OIDC authentication with Signicat here.