OpenID Connect extends the OAuth 2.0 protocol to add a simple authentication and
identity layer that sits on top of OAuth 2.0.
Use OpenID Connect when you want your cloud-based applications to get identity
information, retrieve details about the authentication event (such as when, where, and
how the authentication occurred), and to allow federated single sign-on (SSO).
OAuth 2.0 provides security tokens for use when calling backend resources on behalf of a
user. OAuth provides a grant or license the ability to access resources rather than
provide information about the authentication itself. Using OAuth for authentication is
like an apartment manager giving someone who wants to know your identity a temporary key
to your apartment. The key only implies a right to enter the apartment for a specific
length of time. It doesn't imply that the individual is the owner.
Using OpenID Connect completes the picture by providing applications with information
about the user, the context of their authentication, and access to their profile
information. OpenID Connect allows clients of all types, including web-based, mobile,
and JavaScript clients to request and receive information about authenticated sessions
and end users. See OpenID Connect for more information.
Two concepts are introduced:
OpenID Connect ID Token: This token contains
information about the user's authenticated session.
UserInfo
endpoint: This endpoint provides a way for the client to retrieve additional
attributes about the user.
Implementing OpenID Connect
There are three main actions required to implement OpenID Connect:
Get an OpenID Connect ID Token: Use an OAuth2 grant type to request an OpenID
Connect ID Token by including the openid scope in the
authorization request.
The following use cases provide example requests and responses for obtaining
the ID Token.
Validate the ID Token: Validate the ID Token to ensure that it originated
from a trusted issuer and that the contents weren't tampered with during
transit.
The following use case provides information on how and what to validate.
Retrieve profile information from the UserInfo endpoint:
Using the OAuth2 Access Token, access the UserInfo endpoint
to retrieve profile information about the authenticated user.
The following use case provides example requests and responses for retrieving
profile information from the UserInfo endpoint.
An Identity Token is an integrity-secured, self-contained token (in JSON Web Token (JWT) format) that's defined in the OpenID Connect standard containing claims about the end user. The Identity Token is the primary extension that OpenID Connect makes to OAuth 2.0 to enable authentication in an identity domain.
The Identity Token JWT consists of three components, a header, a payload, and the
digital signature. Following the JWT standard, these three sections are Base64URL
encoded and separated by periods.
Note
OpenID Connect requests must contain the openid scope value.
OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It allows an IAM identity domain client application (registered as an OAuth 2 client with client ID and client secret) to verify the identity of the end user based on the authentication performed by an Authorization Server (AS), and to obtain basic profile information about the end user in an interoperable, REST-like manner. OpenID Connect allows clients of all types, including web-based, mobile, and JavaScript clients to request and receive information about authenticated sessions and end users. See OpenID Connect for more information.
Name
Value
amr
Authentication Methods References. JSON array of strings that are identifiers for authentication methods used in the authentication. For example, values might indicate that both password and OTP authentication methods were used.
at_hash
OAuth 2 Access Token hash value.
aud
Identifies recipients for which this ID Token is intended. Must be the OAuth 2.0 client_id (per the OpenID Connect specification). This is the OAuth client name (app.name) that's making the request. Aud also contains the IAM identity domain Issuer, thereby turning the token type (IT) into an IAM identity domain User Assertion.
authn_strength*
The value returned by Cloud SSO indicating Authentication Strength
from AuthN Context.
auth_time
The time (UNIX epoch time) when Cloud SSO actually authenticated the
user (in seconds, coming from AuthN Context).
azp
Authorized party. The party to which the ID Token was issued. If present, it MUST contain the OAuth 2.0 Client ID of this party. This claim is only needed when the ID Token has a single audience value and that audience is different than the authorized party. It may be included even when the authorized party is the same as the sole audience. The azp value is a case-sensitive string that contains a StringOrURI value.
exp
The expiration time (UNIX epoch time) on or after which the ID Token
must not be accepted for processing. This value must be same as the
session_exp.
iat
The time (UNIX epoch time) when the JWT was created (in seconds).
UNIX Epoch Time is a JSON number representing the number of seconds from
1970-01-01T0:0:0Z as measured in Coordinated Universal Time (UTC) until
the date/time.
iss
The principal that issued the token:
https://<domainURL>
jti
The server-generated unique identifier for the JWT ID.
nonce
The string value used to associate a client session with an ID Token
and to mitigate replay attacks. This value is provided by Cloud
Gate.
session_exp*
The time (UNIX epoch time) when the Cloud SSO session expires
(seconds, must be the same SSO's session expiration in AuthN
context).
sid
The session ID from Cloud SSO (255 maximum ASCII characters) from
AuthN Context.
sub
Identifies the user. The subject identifier is locally unique, never
reassigned, and is intended to be consumed by the client: User Login ID
(255 maximum ASCII characters). This is the user's login ID from AuthN
Context.
sub_mappingattr*
The attribute used to find the sub in the ID store.
tok_type*
Identifies the token type: IT
user_displayname*
The User Display Name (255 maximum ASCII characters) from AuthN
Context.
user_csr*
Indicates (true) that the user is a Customer Service
Representative (CSR).
user_id*
The user's IAM identity domain GUID from AuthN Context.
user_lang*
The user's preferred language.
user_locale*
The user's locale.
user_tenantname*
The User Tenant Name (255 maximum ASCII characters). Tenant's GUID is
specifically not saved in the token
user_tz*
The user's time zone.
Identity Token Validation 🔗
Why do we validate tokens? When your web application checks credentials directly, it verifies that the username and password that are presented correspond to what you maintain. When using claims-based identity, you're outsourcing that job to an identity provider.
The responsibility shifts from verifying raw credentials to verifying that the requester went through your preferred identity provider and successfully authenticated. The identity provider represents successful authentication by issuing a token. Before you can use the information or rely on it as an assertion that the user has authenticated, you must validate it.
OpenID Discovery Document
The OpenID Connect 1.0 protocol is a simple identity layer on top of the OAuth 2.0 protocol that requires the use of multiple endpoints for authenticating users and for requesting resources that include user information, tokens, and public keys. To help with discovering what these endpoints are that you need to use, OpenID Connect allows you to use a discovery document, which is a JSON document found at a well-known location. This discovery document contains key/value pairs that provide details about the OpenID Connect provider's configuration, including the URIs of the authorization, token, userinfo, and public keys endpoints. You can retrieve the discovery document for the IAM identity domain OpenID Connect service from: https://<domainURL>/.well-known/openid-configuration.
Validating Identity Tokens
An Identity (ID) Token is an integrity-secured, self-contained token (in JSON Web
Token format) that contains claims about the end user. It represents an
authenticated user's session. Therefore, the token must be validated before an
application can trust the contents of the ID Token. For example, if a malicious
attacker replayed a user's ID Token that they had captured earlier, the application
should detect that the token has been replayed or was used after it had expired and
deny the authentication.
The ID Token is defined in the OpenID Connect standard and is the primary extension that OpenID Connect makes to OAuth 2.0 to enable authentication. ID Tokens are sensitive and can be misused if intercepted. Ensure that these tokens are handled securely by transmitting them only over HTTPS and only using POST data or within request headers. If you store them on your server, you must also store them securely.
Verify that the value of the audience (aud) claim contains the application's client_id value. The aud (audience) claim may contain an array with more than one element. The ID Token must be rejected if the ID token doesn't list the client as a valid audience, or if it contains additional audiences that aren't trusted by the client.
Verify that the current time is before the time represented by the expiry time (exp) claim.
Verify that the ID Token is properly signed by the issuer. Identity domain issued tokens are signed using one of the certificates found at the URI specified in the jwks_uri field of the discovery document.
Retrieve the tenant's public certificate from the SigningCert/jwk endpoint (for example, https://acme.identity.oraclecloud.com/admin/v1/SigningCert/jwk).
Note
Since identity domains change public keys infrequently, you can cache the public keys and, in the vast majority of cases, efficiently perform local validation. This requires retrieving and parsing certificates and making the appropriate crypto calls to check the signature:
Use any JWT libraries available to validate, for example, Connect2id's Nimbus JWT Library for Java. See JWT for a list of available libraries.
Note
In case of signature validation failure, to prevent constant refetches in case of attacks with bogus tokens, the re-fetching/re-caching of the public key should be based on a time interval, such as 60 minutes, so that refetches only happen every 60 minutes.
Example
package sample;
import java.net.MalformedURLException;
import java.net.URL;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.jwk.source.RemoteJWKSet;
import com.nimbusds.jose.proc.JWSKeySelector;
import com.nimbusds.jose.proc.JWSVerificationKeySelector;
import com.nimbusds.jose.proc.SecurityContext;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.proc.ConfigurableJWTProcessor;
import com.nimbusds.jwt.proc.DefaultJWTProcessor;
public class TokenValidation {
public static void main(String[] args) {
try {
String tokenValue = "eyJ4NXQjUzI1....W9J4oQ";
ConfigurableJWTProcessor jwtProcessor = new DefaultJWTProcessor();
// change t
JWKSource keySource = new RemoteJWKSet(new URL("https://<domainURL>/admin/v1/SigningCert/jwk"));
// The expected JWS algorithm of the token (agreed out-of-band)
JWSAlgorithm expectedJWSAlg = JWSAlgorithm.RS256;
// Configure the JWT processor with a key selector to feed matching public
// RSA keys sourced from the JWK set URL
JWSKeySelector keySelector = new JWSVerificationKeySelector(expectedJWSAlg, keySource);
jwtProcessor.setJWSKeySelector(keySelector);
// Process the token
SecurityContext ctx = null; // optional context parameter, not required here
JWTClaimsSet claimsSet = jwtProcessor.process(tokenValue, ctx);
// Print out the token claims set
System.out.println(claimsSet.toJSONObject());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Verify that the value of the Issuer Identifier (iss) claim exactly matches the value of the iss (issuer) claim: https://<domainURL>/
Querying the UserInfo Endpoint 🔗
The OpenID Connect UserInfo endpoint is used by an application to
retrieve profile information about the identity that authenticated. Applications can use
this endpoint to retrieve profile information, preferences, and other user-specific
information.
The OpenID Connect profile consists of two components:
Claims describing the user
UserInfo endpoint providing a mechanism to retrieve these claims
Note
User claims can also be presented inside the ID Token to eliminate a callback during authentication time.
User Profile Claims
The UserInfo endpoint provides a set of claims based on the OAuth2
scopes presented in the authentication request. OpenID Connect defines five scope values
that map to a specific set of default claims:
OpenID Connect Scope
Returned Claims
openid
None - Indicates this is an OpenID Connect request
The client needs to present its credentials and an access token. The access token
presented needs to contain the openid scope.
If a scope is omitted (for example, the email scope isn't used), the
claim (email) won't be present in the returned claims.
Sample UserInfo Endpoint Request Example
After the client application has authenticated a user and has the access token, the
client can then make a request to the UserInfo endpoint to retrieve the
requested attributes about a user. The following example shows a request example.
Before the client application can trust the values returned from the
UserInfo endpoint (for example, as a check for token substitution
attack), the client must verify that the sub claim returned from the
UserInfo endpoint request matches the subject from the ID
Token.
Using the Authorization Code Flow with
OpenID Connect 🔗
Use the Authorization Code flow when you have clients that can securely maintain a
client secret between themselves and the Authorization Server. The Authorization Code flow
returns an Authorization Code to the client, which can then exchange the code for an ID
Token and an Access Token directly.
This provides you with the benefit of not exposing any tokens to the user agent (such as
a web browser) and possibly other malicious applications with access to the user agent.
The Authorization Server can also authenticate the client before exchanging the
Authorization Code for an Access Token. The Authorization Code flow works with both
Confidential Clients and Public Clients.
Confidential Clients
There are two steps in the Authorization Code flow:
Request the Authorization
Code. In this request, the scope parameter value is openid.
This is an OpenID Connect specification value.
Request
the Token. The client extracts the code parameter from the response and
makes the token request. Also, the client provides its client id and secret
as part of the Basic Authentication header.
Public clients don't have credentials, rather they have a client identifier. There are
two steps in the Authorization Code flow. The requests involve a browser-based GET
request, and then a back-channel POST request to get the Access Token.
Request the Authorization Code.
Request Example
GET https://<domainURL>/oauth2/v1/authorize?client_id=<client-id>&response_type=code&redirect_uri=<client-redirect-uri>&scope=openid&nonce=<nonce-value>&state=1234
Response Example
Note
These request and response examples are similar to the Confidential Client
request and responses discussed previously.
https://<domainURL>/?code=AQIDBAXv9lZQ....F9NCA=
Request the Token.
Request Example
Note
This request is different from the Confidential Client request where the
client id and client secret are specified in the Basic Authentication
header. In the public client flow, there's no Basic Authentication header.
The client id is specified as part of the request payload.
curl -i
-H 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8'
--request POST https://<domainURL>/oauth2/v1/token
-d 'grant_type=authorization_code&code=<authz-code>&reidrect_uri=<client-redirect-uri>&client_id=<client-id>'
Use the Implicit flow when you have implemented a browser-based client using a scripting language such as JavaScript. The Access Token and the ID Token are returned directly to the Client, which may expose these tokens to the user and applications that have access to the user's user agent (such as a web browser).
There's no programmatic/back-channel token request involved in this flow (like the
Public Client request in the Authorization Code flow example). All tokens are
returned from the Authorization endpoint, and the
token endpoint isn't used. The Implicit flow works with
confidential, trusted, and public clients.
Note
Public clients don't have credentials,
just a client identifier.
The following response_type values are supported with the Implicit
flow:
id_token (ID Token)
token (Access Token)
id_token token (both the ID Token and the Access Token)
Obtaining an ID Token
There are three steps in the Implicit flow to obtain an ID Token:
Use the Hybrid flow when you want to obtain tokens separately from both the front
channel and the back channel. For example, you have a browser component like JavaScript and
a backend server component such as Node.js. The browser component obtains the Authorization
Code and the ID Token and can then personalize the UI content. The backend component obtains
the Access Token to perform business API calls.
Clients need to support both browser-based requests and responses and
programmatic/back-channel requests and responses to use the Hybrid flow. The Hybrid flow
works with both Confidential Clients and Public Clients. The following
response_type values are supported with the Hybrid flow:
code id_token (ID Token)
code token (Access Token)
code id_token token (Authorization Code, ID Token, and
Access Token)
Obtaining an ID Token
There are four steps in the Hybrid flow to obtain both the Authorization Code and the ID
Token:
You can use OpenID Connect for browser-based logout requests.
There are two ways that you can request a logout using OpenID Connect:
Redirect to the client who initiated the logout.
Note
Be sure that you define the post logout redirect URI for the OAuth Client
app and that the ID Token is sent in the request. The ID Token contains the
client ID. That client id's corresponding post logout URL is fetched and
validated.