OpenID Provider
In PAS 5.1, a completely new implementation of OpenID Connect Core is introduced, which significantly decreases the amount of configuration needed for functional OpenID Providers (OPs). By using the new system of protocol agnostic authenticators (also introduced in PAS 5.1), as well as setting up an OpenID Provider through simple steps in the configuration manager, you will immediately have access to a functional OIDC integration that includes the following features for the OpenID Provider:
- All OIDC flows (code / implicit / hybrid)
- Refresh tokens
- Consent
- All client authentication methods (client_secret_basic, client_secret_jwt, client_secret_body, private_key_jwt)
- Session management
- Explicit token lifetimes
- Single-sign on
- RP initiated logout
- Backchannel logout
- Proof key for code exchange (PKCE)
Additionally, the OP has been enhanced with the following OAuth 2.0 specifications required in many integrations:
- Access tokens issued as JWTs according to RFC 9068
- Token introspection according to RFC 7662
- Token revocation according to RFC 7009
- Response mode form_post according to the OpenID Specification
- Client credentials flow (opt in) according to RFC 6749.
This means that the new OIDC OP implementation now supports conformance profiles implicit and hybrid in addition to basic.
The configuration
You go through the basic configuration steps in the "OpenID Provider", enter your base url and tenant id which will be used to build the URLs of the endpoints. Then you select which OIDC scopes you would like to support in addition to the "openid" scope. Common values are "profile", "email", and "phone".
The next step is to add which claims you would like to include in which scopes. Your claims are the values which will be included in the userinfo endpoint, as well as in the issued id tokens (optionally). At this step you can really customize the data that PAS will release upon authentication, and how to mask it during the consent step if you desire. More details about the claims and id tokens is provided in the claims section. You will also select which authenticator the OpenID Provider will use. This is often an AgnosticDispatcher or AgnosticAuthSelector that can further direct the authentication flow to different authenticators, but will serve as an entrypoint to which the user is directed when authenticating.
After you finish the OpenID Provider guide in the configuration manager, you have a basic functional OIDC OP. In the edit-mode, you can access additional configuration options such as Access token lifetime, Refresh token lifetime, when to issue refresh tokens, whether to use PKCE, require consent, allow SSO, which additional audiences to include, and more.
The resulting store entity that is created is an OIDC OP that contains the values configured in the guide scenario. It will contain all the necessary data for OIDC Discovery, meaning Relying Parties (RPs) can find the correct endpoints, supported features, and claim data required for a successful integration.
The claims
Claims within OpenID Connect are values that are returned in the id token upon a successful authentication. They are also obtainable via the userinfo endpoint with a valid access token. By default, the userinfo endpoint will only return the sub claim which represents the authenticated user identity. The value of the sub claim is set automatically in the authenticator, and may be different depending on which method is used. BankID will for example use swedish personal number as its sub. The claim is of course possible to override, if the resulting item in your authentication contains a sub-attribute and the configuration parameter "allowSubOverride" is "true" in your OP configuration.
To include additional claims in your userinfo, you need to configure the different supported scopes to include the claims you want. For example, the profile claim usually includes the users name. When an RP initiates an authentication request, it will declare what scopes (and as derived from that, which claims) should be included. The userinfo will include sub, and all other claims that the authentication gave access to. The value for each claim is retrieved from the resulting item in the authentication pipe. Scopes and claims are configured when creating the OP, but can also be changed in the advanced-tab of the configuration manager. This is an example configuration:
"scope_claims" : [ {
"name" : "openid",
"claims" : [ {
"name" : "acr"
} ]
}, {
"name" : "profile",
"claims" : [ {
"name" : "givenName",
"include_in_id_token" : "true",
"type" : "string",
"consentLocalizationKey":"givenName"
}, {
"name" : "aJsonObjectProperty",
"include_in_id_token" : "false",
"type" : "object",
"item_property_name": "myItemPropertyName"
} ]
}, {
"name" : "email",
"claims" : [ {
"name" : "mail",
"include_in_id_token" : "true",
"type" : "string",
"consent_mask": "mail",
"consentLabel": "Email address"
} ]
} ]
You may configure properties for each claim included in a scope. The claim configuration properties are as follows:
- name -- The name of the claim as it will appear in the userinfo and id token. No default value.
- include_in_id_token -- Whether or not to include the claim in the id token. Default: "true".
- include_in_access_token -- Whether or not to include the claim in the access token if issued as JWT. Default: "false".
- type -- The property type. Can be "string", "boolean", "number" or "object". Default: "string".
- isArray -- Whether the claim should be represented as an array of values. Default is "true" if multiple values are present, but may also be hard-configured.
- item_property_name -- The name of the property in the resulting item from which the claim should take its value. Default is the same value as "name".
- consent_mask -- If the claim value should be masked in the consent page. Can be "lastX", "firstX" (where X is the number of characters to mask), or "mail". No default value.
- consentLabel -- What the attribute should be named in the consent display page. This should be end user friendly. Redundant if consentLocalizationKey is set. Default: The same value as "name".
- consentLocalizationKey -- Localization key for the claim's consent display name.
So all the claims included in the authorized scopes will be included in the user info, but only the ones that are configured to be included in the id token will be added there. The sub claim is always present in the id token. The id token will also always include the following, non modifiable claims:
- iss -- the issuer. This is our OIDC OP.
- aud -- the intended audience. This will be the OIDC RP that initiated request, as well as any "additional audience" configured at the OIDC OP.
- exp -- expiration time.
- iat -- issued-at timestamp.
- nbf -- not valid before timestamp.
- nonce -- the OIDC nonce.
- azp -- the authorized party. This is the OIDC RP that initiated the request.
- sid -- a unique identifier for the authenticated session
- c_hash -- hash value of the authorization code. Only present in hybrid flows.
- at_hash -- hash value of the access token. Only present in implicit or hybrid flows.
- jti -- id value of the JWT. Random uuid value.
Claims in access token, if issued as JWT
If the config property accessTokenAsJWT is set as true, access tokens will be issued as JWTs according to RFC 9068.
This means that the JWT type will be at+jwt, and the claims included will be:
- iss -- the issuer. This is our OIDC OP.
- sub -- the subject identifier.
- aud -- the intended audience. This will be the OIDC RP that initiated request, as well as any "additional audience" configured at the OIDC OP.
- exp -- expiration time.
- iat -- issued-at timestamp.
- nbf -- not valid before timestamp.
- client_id -- The client id. This is the OIDC RP that initiated the request.
- jti -- id value of the JWT. Random uuid value.
- scope -- The authorized scope for the token.
Additional claims regarding either authentication information like acr, or identity information in addition to sub can be added like normal claims as long as the claim has include_in_access_token set to true in the claim config.
Scope access
By default, all Relying Parties (RPs) that are configured to be allowed to use the OpenID Provider have access to all scopes available.
This can however be changed per RP by configuring allowed_scopes at the RP. If an RP tries to access a scope that is not allowed, the
authentication request will be denied.
Customized client authorization
In some cases you may want to fine-grain client authorization even further, for example if you want to enforce PKCE usage only during specific circumstances, or
if you want to fetch RP access rules from an external database, or something entirely different. In those cases you may
configure a clientAuthorizationPipeId on the OpenID provider. If configured, a pipe will be run where all request properties
are available for you to configure logic around. If the pipe is executed successfully, the client may proceed with their authorization request.
If the pipe fails however, the request will be denied. In such a pipe you may want to configure one or several FlowFailValves
which executes only under specific circumstances. All resulting item properties will populate the OIDC state, such that they may be used
in claims if desired.
Token lifetimes
Token lifetimes are freely configurable with the config properties accessTokenLifetimeMinutes, refreshTokenLifetimeMinutes,
and idTokenLifetimeMinutes (however id token lifetimes are recommended to leave very low -- default is 2 minutes).
Key rollover
The OpenID Provider supports key rollover. Simply add an additional id to your signStore (or encStore for encryption keys),
comma-separated (easiest is to add an additional keystore via the config GUI). All configured keys will be visible in the
discovery JWKS document, and for signatures the first non-expired certificate will be used.
If all certificates are expired, the last keystore will be used. This way, you can make sure you always use
up-to-date certificates without having any downtime or de-syncs with your integrating RPs.
A configuration example of an OP with multiple keystores is below:
{
"id" : "my_oidc_op_id",
"tenant" : "my_oidc_op_id",
"config" : {
...
"signStore" : "604fe441-37d3-4f00-8af2-c7ced13c708f,70ca112d-37ad-4a50-a10a-3851aae0f62f",
...
},
}
Token / Userinfo Encryption
Id tokens and userinfo may be encrypted according to the JSON Web Encryption (JWE) standard.
This may be controlled at the OP with the configuration parameters encryptIdTokens and encryptUserInfo. Note that for encryption to be possible,
the parameter publicKey must be configured at the RP. All of this is easily configured in the config GUI for both the OP and the RPs.
There are three different configuration values for encryptIdTokens and encryptUserInfo, they are:
always- Content will always be encrypted. If no public key is available for the RP, an error is thrown and the flow fails.onDemand(default) - Content will be encrypted if the RP configurationwantsIdTokenEncrypted/wantsUserInfoEncryptedistrue. If no public key is available for the RP, an error is thrown and the flow fails.never- Content will never be encrypted.
The supported payload encryption algorithm is A256GCM, and the supported key encryption algorithms are RSA-OAEP, RSA-OAEP-256, and ECDH-ES.
The default key encryption algorithm depends on the type of public key the RP is using. For RSA it is RSA-OAEP-256 and for EC it is ECDH-ES.
The key encryption algorithm may be overridden with the configuration parameter jweAlgorithm in the OP configuration block.
If userinfo is set to be encrypted, it will first be wrapped inside a signed JWT as specified in the OpenID specification.
The OpenID Provider can also parse encrypted tokens (id_token_hint in logout flows and client_assertion in JWT client authentication).
The keystore used to decrypt such tokens is configured as encStore in the OP config block. If left empty, the keystore will default to
the signStore configuration parameter. This default behavior can be opted out via a parameter named useDefaultEncStore. This means
if you leave encStore blank and configure useDefaultEncStore: "false" no decryption can be made by the OP. In that case, it would also
not publish any encryption public key in it's JWKS response.
JWT Signature methods
Available signature methods are RS256 and ES256, and depending on whether the configured keystore (signStore configuration parameter)
is of type RSA or EC, the appropriate method is automatically selected.
Additional feature specification
The endpoints available are the standard endpoints as defined in OpenID Connect. These include:
- Authorization endpoint -- where you log in/authenticate. No prior authentication required.
- Token endpoint -- where you fetch your tokens. Client authentication and authorization code or refresh token required (except when using OAuth client credentials flow).
- Userinfo endpoint -- where you fetch the user information. Access token required.
- Check session endpoint -- where you fetch the OP iFrame for OIDC Session management. No authentication required (but session mgmt is only relevant after prior authentication)
- End session endpoint -- where you log out and end your session. Session cookie or id token required.
These endpoints are developed to the specifications of OpenID Connect, but that includes some implementation freedom left at the discretion of the OP. Many integrations which make use of OpenID Connect also mix in some OAuth 2.0 specifications in their requirements, so these two OAuth 2.0 endpoints are also available:
- Introspection endpoint -- where you can validate an access or refresh token. Client authentication required.
- Revocation endpoint -- where you can revoke an access or refresh token. Client authentication required.
Another OAuth specific feature is the client_credentials flow. This is only available if you add the grant type client_credentials to the
OP configuration property grant_types_supported. All RPs that want to use this flow will also have to have the configuration property
allow_client_credentials_grant_type set to "true" in their configuration.
Notable additional details about OpenID Providers in PAS 5.1 are:
- The "allowSSO" configuration parameter controls if SSO will be attempted for authentication requests towards the OP (read more about SSO in protocol agnostic authenticators before using)
- The "accessTokenAsJWT" configuration parameter controls if access tokens should be issued as JWT or just an opaque string. Default is false.
- The end session endpoint will trigger backchannel logout for all RPs that have "backchannel_logout_uri" configured.
- The client authentication method "private_key_jwt" requires "publicKey" configured at the OIDC RP. The other, client secret based authentication methods require "password" configured at the OIDC RP. The client authentication method "none" is allowed only if the configuration parameter "allowNoAuthMethod" is "true" at the RP.
- When using client authentication methods
private_key_jwtorclient_secret_jwtyou may need to adjust the clock skew (default is 60 seconds.). This can be done via config parameterclockSkewSeconds. - When using client authentication methods
private_key_jwtorclient_secret_jwtit is strongly recommended that JTI replay checks are enabled (this is the default behavior, and requires the modulephenix-replay-cacheto be enabled). They can however be turned off via config parametercheckJtiReplayset to "false". - When using client authentication methods
private_key_jwtorclient_secret_jwtthe accepted audiences are the OP Token endpoint URL and OP ID. This can however be overridden with the config propertyacceptedAudiences. Example:"acceptedAudiences": ["someOverride1", "someOverride2"]. - Loopback redirect URIs do not require specific ports in the allowedRedirects configuration of the OIDC RP.
- Consent will be required if "consentRequired" is set at the config of the OP, RP or if the request prompt includes "consent"