OpenID Connect Basics

Hasini Witharana
Identity Beyond Borders
8 min readJul 19, 2017

In OAuth 2.0 resource owner (user) gives permission to access some protected resources for third party applications without providing valuable information like password. As an example think Bob (who already has a Google account) wants to use Google to login to Medium. Then Medium (client) will send a request to Google(Authorization server) to identify Bob. Bob will accept the request from Medium. Then Medium will know that Bob is a valid user. Now Medium needs some details about Bob which are in Google. But how can Medium have Bob’s details?

Here comes OpenID Connect.

OpenID Connect (OIDC) is an interoperable authentication protocol based on the OAuth 2.0 family of specifications. — From OIDC core specification

In simple terms OpenID connect is used to do the authentication part and to get Bob’s details. Then Medium can identify who Bob is.

Now let's see how OIDC achieves this.

The flow is very much the same as the OAuth 2.0. But the difference is an ID_Token is issued other than the access token to identify the user. To understand this we will go through some basic concepts of OIDC.

  1. Participants

End-user is the same as the OAuth2.0 resource owner who is requested for identity information.

Eg : Bob

Relying Party is the same as the OAuth2.0 client requiring End-User Authentication and Claims from an OpenID Provider.

Eg : Medium

OpenID Provider (OP)

OpenID provider is the same as the OAuth2.0 Authorization Server that is capable of authenticating the End-User and providing claims to a Relying Party about the Authentication event and the End-User.

Eg : WSO2 identity server

2. ID_Token

ID_Token is like an identity card. Using this token, the client can get some claims about the end-user. This token has three parts and is represented as a JSON web token (JWT)

ID_Token = <Header><Body><Signature>

ID_Token contains;

  • iss — Issuing authority.
  • sub — A unique identifier for the end-user issued by the issuer.
  • aud — Audience this ID_Token is intended for. This must contain the client_ID of the RP.
  • exp — After what time the ID_Token should not be accepted.
  • iat — Time that token is issued.
  • auth_time — Time when the end-user authentication occurred.

iss, sub, aud, exp and iat are required parameters in the id_token. Other than these parameters there can be other optional parameters as well.

3. Claims

Claims are some information about the end-user.

Eg : Bob’s name, address, birth date, gender and etc.

4. Endpoints

There are three main endpoints.

  • Authorization Endpoint

This is the endpoint in OP where the user is authenticated. This is where Bob is asked to authenticate and grant permission for Medium to access his resources.

  • Token Endpoint

This is the endpoint used to generate an ID_Token and access token from the code generated at authorization endpoint for the client.

  • Userinfo Endpoint

This is where the user information or claims are sent to the client. For this, a valid access token must be provided to the OP.

Now you have some basic idea about the terminologies used in OIDC.

So let’s move to the authentication process. In OIDC there are three flows where RP can request the authentication of a user from the OP.

  1. Authorization Code Flow
  2. Implicit Flow
  3. Hybrid Flow

Authorization Code Flow

  • response_type=code

In the Authorization code flow, first, a code is issued from the OP and then access token and id_token is generated. In authentication request, the response_type should be “code” to gain an authentication type Authorization Code Flow. Below are the steps to obtain an access token and an id_token.

1. Client prepares an Authentication Request containing the desired request parameters.

The OpenID authentication request is essentially an OAuth 2.0 authorization request to access the user’s identity, indicated by an ‘openid’ value in the scope parameter.

Example for Authentication request

HTTP/1.1 302 Found
Location: https://server.example.com/authorize?
response_type=code
&scope=openid%20profile%20email
&client_id=s6BhdRkqt3
&state=af0ifjsldkj
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
  • response_type: Set to “code” to indicate an authorization code flow.
  • scope: Used to specify the scope of the requested authorization in OAuth. The scope value openid signals a request for OpenID authentication and ID token.
  • client_id: The client identifier of the RP at the OP. This identifier is typically obtained when the RP is registered with the OP, via the client registration API, developer console, or some other method.
  • state: Opaque value set by the RP to maintain state between request and callback.
  • redirect_uri: The RP callback URI for the authentication response.

Scope, response_type, client_id and redirect_uri are mandatory parameters in authorization request. The state is not mandatory but it is recommended.

2. The Client sends the request to the Authorization Server.

The authorization server must validate the request.

  • The Authorization Server must validate all the OAuth 2.0 parameters according to the OAuth 2.0 specification.
  • Verify that a scope parameter is present and contains the openid scope value.
  • The Authorization Server must verify that all the required parameters are present and their usage conforms to this specification.

3. Authorization Server Authenticates the End-User.

If the request is valid, authorization server tries to authenticate the end-users. But there are some cases where the authorization server must not try to authenticate users.

Must try to authenticate:

  1. If the user is not already authenticated.

2. If the prompt value is logged in. In this case, an end-user must be re-authenticated even if the end-user is already authenticated.

Must not try to authenticate :

  1. If the prompt value is none. In this case, if an end-user is not already authenticated or cannot be silently authenticated, an error should be thrown.

Prompt is an optional parameter in the request that specifies whether the authorization server prompts end user for re-authentication and consents.

4. Authorization Server obtains End-User Consent/Authorization.

After the end-user is authenticated, the authorization server must obtain an authorization decision. This can be done through an interactive dialog with the end-user.

5. Authorization Server redirects the End-User back to the Client with an Authorization Code.

Authorization server will send an authentication response from authorization endpoint to the RP. Client should validate this response.

This is an example of successful authentication response.

HTTP/1.1 302 Found
Location: https://client.example.org/cb?
code=SplxlOBeZQQYbYS6WxSbIA
&state=af0ifjsldkj

6. Client requests a response using the Authorization Code at the Token Endpoint.

Client will send the authorization code to the token endpoint and request ID_token, access token and optionally refresh token.

This is an example of token request.

POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb

7. Client receives a response that contains an ID Token and Access Token in the response body.

Authorization server must validate the token request and send ID_Token and access token to RP.

This is an example of successful token response.

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
"access_token": "SlAV32hkKG",
"token_type": "Bearer",
"refresh_token": "8xLOxBtZp8",
"expires_in": 3600,
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzc
yI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5
NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZ
fV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5Nz
AKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6q
Jp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJ
NqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7Tpd
QyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoS
K5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4
XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg"
}

8. Client validates the ID token and retrieves the End-User’s Subject Identifier.

Implicit Flow

  • response_type=id_token
  • response_type=id_token token

In Implicit authentication type, tokens are issued at Authorization endpoint not in token endpoint. No authorization code is generated, only tokens are generated. Below are the steps to obtain tokens in this type.

  • Client prepares an Authentication Request containing the desired request parameters.

This is an example for authentication request

GET /authorize?
response_type=id_token%20token
&client_id=s6BhdRkqt3
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
&scope=openid%20profile
&state=af0ifjsldkj
&nonce=n-0S6_WzA2Mj HTTP/1.1
Host: server.example.com
  • Client sends the request to the Authorization Server.
  • Authorization Server Authenticates the End-User.
  • Authorization Server obtains End-User Consent/Authorization.
  • Authorization Server sends the End-User back to the Client with an ID Token and, if requested, an Access Token.
  • Client validates the ID token and retrieves the End-User’s Subject Identifier.
Difference between response_types in implicit flow

nonce — String value used to associate a Client session with an ID Token, and to mitigate replay attacks.
at_hash Access Token hash value.

Which flow to use ?

Hybrid

  • response_type=code token
  • response_type=code id_token
  • response_type=code id_token token

This is a combination of both Authorization code and implicit flows.In this flow a code is generated at Authorization endpoint and id_token and access token as required. Below are the steps for this flow.

  • Client prepares an Authentication Request containing the desired request parameters.
  • Client sends the request to the Authorization Server.
  • Authorization Server Authenticates the End-User.
  • Authorization Server obtains End-User Consent/Authorization.
  • Authorization Server sends the End-User back to the Client with an Authorization Code and, one or more additional parameters, depending on the Response Type.
  • Client requests a response using the Authorization Code at the Token Endpoint.
  • Client receives a response that contains an ID Token and Access Token in the response body.
  • Client validates the ID Token and retrieves the End-User’s Subject Identifier.
Difference between response_types in hybrid flow

If an ID Token is issued both from authorization endpoint and token endpoint (response_type = code id_token and code id_token token)

  • The iss and sub values must be identical.
  • All Claims about the Authentication event present in either should be present in both.
  • OP may choose to return fewer Claims about the End-User from the Authorization Endpoint, for instance, for privacy reasons.

If an Access Token is issued both from authorization endpoint and token endpoint (response_type = code token and code id_token token)

  • Their values may be same or may be different
  • This depends on security characteristic of two endpoints

Now you might wonder why we need this hybrid flows ? Here is the answer

  • Allow applications to receive front-end and back-end separate tokens.

In response_type code token you might think that the same thing is happening what is the use of it. That is not true. Authorization code gives more than an access token. By using the Authorization code we can ask for refresh tokens.

Summary

Hope this helped you understand the basics of OpenID Connect.

--

--

Hasini Witharana
Identity Beyond Borders

PhD Candidate @ University of Florida. Security Research Intern @ Intel. Software Engineer @ WSO2.