Identity Federation by OpenID Connect

Takahiko Kawasaki
8 min readFeb 2, 2022

(If you are looking for information about “OpenID Connect Federation 1.0”, please read the article “OpenID Connect Federation 1.0” instead.)

Flow of Identity Federation

Step 1

A user accesses the login page of a web service with a web browser.

Step 2

The web service generates the login page and returns it to the web browser. If the web service supports identity federation with external identity providers (IdP), the login page will include links that initiate identity federation.

Step 3

The user clicks a link to initiate identity federation.

Step 4

The web service receives the request for initiation of identity federation and prepares an authentication request (OpenID Connect Core 1.0 Section 3.1.2.1. Authentication Request) for the IdP.

The format of an authentication request is a URL that points to the authorization endpoint (RFC 6749 Section 3.1. Authorization Endpoint) of the IdP with request parameters. Therefore, the web service has to know the URL of the authorization endpoint when it prepares an authentication request.

Developers can find the URL of the authorization endpoint in technical documents of the IdP, but if the IdP supports OpenID Connect Discovery 1.0, the information can be programmatically retrieved from the discovery document which is published at the discovery endpoint of the IdP.

By the specification (OpenID Connect Discovery 1.0 Section 4. Obtaining OpenID Provider Configuration Information), the location of the discovery endpoint is defined as “{identifier of the IdP}/.well-known/openid-configuration”. Therefore, you can locate the discovery endpoint if you know the identifier of the IdP.

It is at this timing that the web service generates a value of the state parameter which is to be included in the authentication request. The value is also stored in the HTTP session for later use. In addition, if the code_challenge parameter (RFC 7636) is required, it is also at this timing that the web service generates a code verifier. See “Proof Key for Code Exchange (RFC 7636)” for details about the code_challenge parameter.

Step 5

After preparing an authentication request, the web service returns the HTTP status code 302 Found (or whatever can trigger redirection) in order to redirect the web browser to the authorization endpoint of the IdP. The value of the Location header in the response holds the authentication request.

HTTP/1.1 302 Found
Location: {authorization endpoint}?parameters...

Step 6

When a web browser receives 302 Found, it accesses the location written in the Location header. As a result, the web browser sends the authentication request to the authorization endpoint of the IdP.

Step 7

The authorization endpoint receives the authentication request and generates an authorization page whereby to (a) authenticate the user and (b) obtain consent from the user about granting permissions to the web service. The authorization page is returned to the web browser.

The authorization page in the image above has input fields and buttons for both user authentication and consent confirmation, but implementations don’t necessarily have to have the same structure. Because in recent years it has been considered preferable to perform user identification and user authentication in separate steps, it may be rather the mainstream to perform page transition with multiple pages (or multiple JavaScript-based UI components) to separate the steps.

Step 8

The user inputs information necessary for user authentication and authorizes the request from the web service.

The authorization page in the image above requires a pair of login ID and password, but it is completely up to IdP how to authenticate users. There are a wide variety of user authentication methods these days.

Step 9

After user authentication and consent confirmation, the IdP generates an authorization code. Here it is assumed that the flow of the authentication request was the OpenID Connect authorization code flow. (See “1. response_type=code” in “Diagrams of All The OpenID Connect Flows” for details.)

Then, in order to deliver the authorization code to the redirection endpoint (RFC 6749 Section 3.1.2. Redirection Endpoint) of the web service, the IdP constructs a URL by appending the authorization code as a parameter to the redirection URI which the web service has previously registered at the IdP.

A state parameter is also added to the URL, which has the same value as the state parameter had in the authentication request. In addition, if the IdP supports OAuth 2.0 Authorization Server Issuer Identification, an iss parameter is added, too.

To redirect the web browser to the URL which was constructed by the steps above, the IdP returns the HTTP status code 302 Found (or whatever can trigger redirection) to the web browser with a Location header whose value is the URL.

HTTP/1.1 302 Found
Location: {redirection endpoint}?code=...&state=...&iss=...

Step 10

When a web browser receives 302 Found, it accesses the location written in the Location header. As a result, the web service receives the authorization code.

In addition to the authorization code, the redirection endpoint receives a state parameter. The implementation of the redirection endpoint must confirm that the value of the state parameter is equal to the value which is stored in the HTTP session. This is a countermeasure for CSRF. See RFC 6749 Section 10.12. Cross-Site Request Forgery for details.

Also, if the authorization_response_iss_parameter_supported server metadata of the IdP is true, the implementation of the redirection endpoint must confirm that an iss parameter is included in the request to the endpoint and that the value of the parameter matches the identifier of the IdP. See OAuth 2.0 Authorization Server Issuer Identification for details about the iss parameter.

Step 11

The web service sends a token request with the authorization code to the token endpoint (RFC 6749 Section 3.2. Token Endpoint) of the IdP.

Step 12

The token endpoint generates an access token (RFC 6749 Section 1.4. Access Token) and an ID token (OpenID Connect Core 1.0 Section 2. ID Token) and returns them to the web service.

Step 13

The web service validates the ID token it received. Among the various validation steps (OpenID Connect Core 1.0 Section 3.1.3.7. ID Token Validation), the most important is to verify the signature of the ID token.

To verify the signature, the web service must obtain the key for verification. When the signing algorithm of the signature is symmetric, the key is the client secret. On the other hand, when the algorithm is asymmetric, the key is a public key. (OpenID Connect Core 1.0 Section 10.1. Signing)

If the verification key is a public key, the IdP has made the public key available somewhere. In a typical case, the public key can be found in the JWK Set document which is published at the JWK Set endpoint of the IdP. The location of the JWK Set endpoint is written in the discovery document which is published at the discovery endpoint.

If the web service finishes validation of the ID token, it means that the web service could confirm that the user had been authenticated by the IdP.

Step 14

The payload part of the ID token includes information about the user. If the information is not enough, the userinfo endpoint (OpenID Connect Core 1.0 Section 5.3 UserInfo Endpoint) can be utilized. Note that the userinfo endpoint requires an access token which covers at least the openid scope.

You may be surprised to know that claims requested by special scopes such as profile (OpenID Connect Core 1.0 Section 5.4. Requesting Claims using Scope Values) are NOT included in an ID token when an access token is also issued in the same flow. Therefore, in most cases, information in an ID token is less than you may expect. (cf. isClaimShortcutRestrictive())

Step 15

The userinfo endpoint returns information about the user.

It is up to implementations of web services how to deal with the information returned from the userinfo endpoint. For example, some web services may create a new user account and copy the information into the database record of the user account. Others may avoid copying the information duplicately and instead remember the access token in order to obtain the latest information about the user from the userinfo endpoint at any time later they like.

Step 16

The web service changes the status of the HTTP session of the user to “logged in” and redirects the web browser to the top page (or wherever appropriate) of the web service.

Step 17

The web browser accesses the top page.

Step 18

The web service returns the top page. At this time, the user is considered logged in.

Complete

The flow of identity federation was completed.

Tutorial of Identity Federation

Integration with External IdPs”, a technical tutorial published on Authlete’s website, shows an example of identity federation where Okta works as an IdP and java-oauth-server (an open-source sample implementation of authorization server) does as a web service. The flow in the tutorial looks complicated because an authorization server is used as a web service (identity federation is initiated from the authorization page of the authorization server), but the part of identity federation is the same as that explained in this article.

The example in the tutorial actually runs, so please give it a try. If you are interested in details of the implementation, Federation.java and FederationEndpoint.java in java-oauth-server are starting points for code reading.

NOTE: A certain famous IDaaS requires a custom parameter at its token endpoint as a mandatory parameter, so identity federation between the generic code in java-oauth-server and the IDaaS will not work, probably.

--

--

Takahiko Kawasaki

Co-founder and representative director of Authlete, Inc., working as a software engineer since 1997. https://www.authlete.com/