The Curity Security Token Server supports OpenID Connect. This is enabled by enabling openid configuration for the token profile that should support it. This enables the use of ID Tokens which represents user-authentications. When this mode is enabled, clients can also get more information about a user via the user info endpoint. Metadata can also be exposed when this option is enabled.
Fig. 143 Disabled OpenID Connect as shown in the GUI
OpenID Connect is disabled by default, but can be enabled for any OAuth profile. To do so using the admin GUI, go to OAuth ‣ $PROFILE_NAME ‣ General and then enable the Open ID Connect option as shown in Fig. 144
Open ID Connect
Fig. 144 Enabling OpenID Connect in the admin GUI
When OpenID Connect is enabled, the following options can also be configured:
id-token-ttl
The amount of time that an ID token should be valid for
passthrough-unscoped-claims
When false, all non-standard attributes returned from the account data source will be removed unless there is a corresponding scope that the end user has authorized. Setting this value to true will cause such attributes to be included in the user info endpoint’s response.
false
true
Aside from these settings, it is also possible to configure that OpenID Connect metadata should be exposed. This is disabled by default, but can be enabled by toggling the associating setting in the GUI or setting in the CLI. In order for OpenID Connect metadata to be exposed, certain conditions have to be met. The configuration will not validate if these conditions are not met. These include:
client-credentials
code
resource-owner-password-credentials
token-exchange
oauth-authorize
oauth-token
oauth-userinfo
oauth-assisted-token
oauth-revoke
oauth-introspect
If all of these conditions are met, then the metadata can be obtained by requesting the subroute /.well-known/openid-configuration under the anonymous endpoint. For example, if the anonymous endpoint is configured to be ~, then this would be at /~/.well-known/openid-configuration on the host that is serving the OAuth profile’s anonymous endpoint. If this endpoint were hosted on a service that used the HTTPS protocol, had a hostname of localhost and was listening on port 8443, then the metadata would be accessible at https://localhost:8443/~/.well-known/openid-configuration.
/.well-known/openid-configuration
~
/~/.well-known/openid-configuration
The metadata in this response is mostly defined by the OpenID Connect and OAuth metadata standards where applicable. The included metadata and its meaning is described in the following table:
OpenID Connect Metadata
OpenID Connect metadata fields that are returned depending on various configuration
issuer-override
jwks
assisted-token
openid
The response types that the OAuth profile supports. The elements of the array will be as summarized in the following table:
code id_token
code id_token token
id_token
implicit
id_token token
token
code token
code token id_token
query
fragment
The grant types or “flows” that are supported by the OAuth profile. The elements of the array will be as summarized in the following table:
authorization_code
refresh_token
password
client_credentials
https://curity.se/grant/accesstoken
https://curity.se/grant/assisted-token
backchannel-authentication
urn:openid:params:grant-type:ciba
pairwise
public
RS256
client_secret_post
client_secret_basic
normal
$IDSVR_HOME/usr/share/messages/overrides
ui_locales_supported
S256
plain
Bearer
sid
poll
An example of the OpenID Connect metadata is shown in Listing 163.
{ "introspection_endpoint": "https://localhost:8443/introspection", "scopes_supported": [ "read", "admin_read", "openid", "profile", "admin_write", "write", "email" ], "issuer": "https://spruce:8443/dev/oauth/anonymous", "acr_values_supported": [ "urn:se:curity:authentication:google:google1", "urn:se:curity:authentication:sms:sms2fa", "urn:se:curity:authentication:sms:sms1", "urn:se:curity:authentication:html-form:html2fa", "loa1" ], "authorization_endpoint": "https://localhost:8443/dev/oauth/authorize", "introspection_endpoint_auth_methods_supported": [ "client_secret_post", "client_secret_basic" ], "service_documentation": "https://localhost/developer-documentation-url", "claim_types_supported": [ "normal" ], "token_endpoint_auth_methods_supported": [ "client_secret_post", "client_secret_basic" ], "response_modes_supported": [ "fragment", "query" ], "token_endpoint": "https://localhost:8443/dev/oauth/token", "response_types_supported": [ "code", "id_token", "token" ], "revocation_endpoint_auth_methods_supported": [ "client_secret_post", "client_secret_basic" ], "grant_types_supported": [ "refresh_token", "implicit", "client_credentials", "password", "https://curity.se/grant/accesstoken", "authorization_code", "urn:openid:params:grant-type:ciba", "https://curity.se/grant/assisted-token" ], "backchannel_authentication_endpoint": "https://localhost:8443/bc-auth", "backchannel_token_delivery_modes_supported": [ "poll" ], "backchannel_authentication_request_signing_alg_values_supported": [ "RS256" ], "ui_locales_supported": [ "sv", "en" ], "revocation_endpoint": "https://localhost:8443/revoke", "userinfo_endpoint": "https://localhost:8443/dev/oauth/userinfo", "code_challenge_methods_supported": [ "S256", "plain" ], "jwks_uri": "https://localhost:8443/dev/oauth/anonymous/jwks", "subject_types_supported": [ "public" ], "id_token_signing_alg_values_supported": [ "S256" ], "assisted_token_endpoint": "https://localhost:8443/assisted-token", "claims_locales_supported": [ "sv", "en" ] }
There are two ways to request profile data to be included in the ID-token or the response of the user info endpoint, which are by requesting scopes and by requesting individual claims through the claims request parameter. As specified by OpenID Connect, the claims parameter is a JSON document which has the option to request each claim individually, as opposed to the claim sets that are specified by the OpenID scopes.
claims
Given that OpenID Connect is enabled on the profile, claims request parameter support is enabled by default. When more fine grained control over the requested claims is needed, it is possible to do so from the different token procedures for each flow that issues an ID token or returns a user info response. By default, the claims parameter is stored with the delegation, and as such it can be found like this:
In the oauth-authorize-implicit and oauth-token-authorization-code procedures: context.getDefaultDelegationData().requestedClaims In the openid-userinfo procedure : context.presentedToken.getDelegationData().data.requestedClaims.
oauth-authorize-implicit
oauth-token-authorization-code
context.getDefaultDelegationData().requestedClaims
openid-userinfo
context.presentedToken.getDelegationData().data.requestedClaims
The parameter is the string with the JSON document. To use it, you need to parse it still. An example of how to process the parsed claims request parameter is included in the oidc/claims-parameter directory of the examples. Note that this string comes from an unverified and possible unsafe source (i.e. user input), and parsing it incorrectly could introduce a security vulnerability.
The claims request parameter is used to establish which claims from the profile data must be included in an ID token or in the user info response. If the authenticated account data contains non-standard attributes, there is no enforcement on whether these claims can be exposed. To allow these claims to be exposed, make sure to enable the Pass Through Unscoped Claims configuration option of the OpenID Connect settings on the Token Profile.
Pass Through Unscoped Claims
There is access control applied on the claims that can be requested by clients. This access control is based on the allowed scopes for the client, in particular the OpenID Connect scopes (profile, email, phone and address). These scopes represent a set of claims, and by these scopes to be requested by a client, this also allows the claims that they represent to be requested through the claims parameter. However, claims that are not OpenID Connect claims are always released when the Pass Through Unscoped Claims setting is enabled (see above).
profile
email
phone
address
For example, in case the client does not allow the profile claim to be requested, yet there is a request for the picture claim, this request will be rejected because it is not an OpenID Claim that is represented by an allowed OpenID Connect scope. If instead the request is for the big-picture (which is not an OpenID Connect claim), and Pass Through Unscoped Claims is enabled, then that account attribute would be released if it were available.
picture
big-picture
Note that requesting the acr claim with a specific value will result in requiring authentication to be performed with that particular acr.
acr
By default, when a user authenticates, the authenticated subject is passed along unmodified in tokens issued to the client. In environments where different clients should not be able to share properties that are bound to a subject amongst each other, it is possible to issue pseudonymous subject identifiers. These pseudonyms will be the same for one user to a client, but will be different for that same user to a different client. The intent is that different clients will not be able to link their databases with each other and create a bigger user profile than the user might expect.
The OpenID Connect specification describes a way to express how to issue pseudonymous subject identifiers. Pseudonyms are called Pairwise Pseudonymous Identifiers (PPIDs) because they are based on the pair of Subject Identifier and Sector Identifier. If a sector identifier is not explicitly set, it is derived for each client, based on its registered redirect URI’s: if all the redirect URI’s share the same host component, then this shared host component is used as the sector identifier. If there is no redirect URI or if there are multiple redirect URIs with different host components, then it is required to configure a sector identifier for the client explicitly.
Example A client does not configure a value for sector identifier, but it has registered redirect URI https://www.example.com/cb. In case a pairwise pseudonym is calculated, this is done by taking the host component (www.example.com) of this redirect URI and feeding it into the algorithm. When a user has authenticated as teddie, then the pseudonym to be issued is calculated like: pseudonymize("teddie", "www.example.com") In case the client has multiple redirect URIs registered, e.g. https://www.example.com/cb and https://another.example.com/cb, it is required for the client to also register a Sector Identifier. Say the Sector Identifier is registered as Sector Zort, then the pseudonym to be issued is calculated like: pseudonymize("teddie", "Sector Zort")
Example A client does not configure a value for sector identifier, but it has registered redirect URI https://www.example.com/cb. In case a pairwise pseudonym is calculated, this is done by taking the host component (www.example.com) of this redirect URI and feeding it into the algorithm. When a user has authenticated as teddie, then the pseudonym to be issued is calculated like:
https://www.example.com/cb
www.example.com
teddie
pseudonymize("teddie", "www.example.com")
In case the client has multiple redirect URIs registered, e.g. https://www.example.com/cb and https://another.example.com/cb, it is required for the client to also register a Sector Identifier. Say the Sector Identifier is registered as Sector Zort, then the pseudonym to be issued is calculated like:
https://another.example.com/cb
Sector Zort
pseudonymize("teddie", "Sector Zort")
Note
Mobile Connect requires a sector identifier to be a URL even for statically registered clients. To conform to this profile, an administrator should use a URL instead of some other value. Be aware that the configuration is not validated for such a case.
A client will always be issued a non-pseudonym, unless it is enabled to issue Pairwise Pseudonyms for that client. Once enabled, no more unprocessed subject identifiers will be issued.
Different clients will be issued different pseudonyms for the same user, unless multiple clients share the same Sector Identifier, as explained in the previous paragraph. If this is desired, you can explicitly set the Sector Identifier that is used to calculate a pseudonym for the subject.
Caution
Be careful when changing a Sector Identifier on an existing client, as the result will be that all users will be assigned a new subject identifier; the client will not be able to find out which new subject identifier referred to which old subject identifier.
There is a setting on the profile that indicates whether it is required to issue pairwise pseudonyms to clients. This setting is particularly useful in case a profile is setup for Dynamic Client Registration: when the profile requires pairwise pseudonyms, a new non-templatized client must be registered with a subject_type=pairwise parameter, or it will be rejected upon registration.
subject_type=pairwise
To calculate the issued pseudonym, the same logic applies to configured clients as well as dynamically registered clients: by default the explicitly configured Sector Identifier value will be used in the pair of Subject Identifier and Subject Identifier. In case there is no configured sector identifier, the hostname of the configured redirect URI or URI’s will be used. If that fails because none or there are more than one different host names found in the redirect URI’s, an error will occur.
When doing Dynamic Client Registration, a client can not just say which Sector Identifier it wants to use. The reason for that is to protect users from clients that want to join a sector, and thereby getting issued with the same pairwise pseudonyms as every other client in that sector, without anyone checking that! Instead, a mechanism is in place that will verify whether a sector identifier can be accepted, which is based on the sector_identifier_uri parameter.
sector_identifier_uri
Curity supports this approach, and will fetch the document from the location that is referred to in the sector_identifier_uri location. It will verify the document as specified in the OpenID Connect Dynamic Client Registration specification.
You can use the sector-identifier-lookup-http-client configuration option of Dynamic Client Registration settings to change the HTTP client that must be used to look up the sector_identifier_uri document.
sector-identifier-lookup-http-client
When the request is accepted, the hostname component of the sector_identifier_uri will be used as Sector Identifier. For example, if a client registers with the parameters subject_type=pairwise and sector_identifier_uri=https://my.example.com/sector-info, pairwise pseudonyms are calculated as pseudonymize("teddie", "my.example.com")
sector_identifier_uri=https://my.example.com/sector-info
pseudonymize("teddie", "my.example.com")
As Registration Based on a Template Client registers a client based on only a reference to the client template, it could lead to all registered clients using the same Sector Identifier, which effectively reduces a pairwise pseudonym into a regular pseudonym. In this case however, Curity will use the client’s ID of a dynamically registered template client as the sector identifier. Note that this is only the case when the client template is configured to issue pairwise pseudonyms.
Example A dynamically registered client based on a client template was issued the id 192-riw-1uc. In this case, the pairwise pseudonym for user teddie is calculated like this: pseudonymize("teddie", "192-riw-1uc")
Example A dynamically registered client based on a client template was issued the id 192-riw-1uc. In this case, the pairwise pseudonym for user teddie is calculated like this:
192-riw-1uc
pseudonymize("teddie", "192-riw-1uc")