Id Token Authentication

The OpenID Connect authentication is very similar to its authorization counterpart in OAuth 2.0, the single difference being that the token generation can include the generation of an ID token, alongside the access token.

Who is it for

When the Relying party requires a secure token with claims about the authentication of the end-user.

How to enable it

plugin :rodauth do
  enable :oidc

  oauth_jwt_keys("RS256" => OpenSSL::PKey::RSA.new("/path/to/privkey.pem"))
  oauth_jwt_public_keys("RS256" => OpenSSL::PKey::RSA.new("/path/to/pubkey.pem"))

  # you should define all scopes relevant for your use case, openid and non-openid.
  # An OpenID provider is first-and-foremost an OAuth Authorization Server, and can
  # can authorize other realms beyond what OpenID defines
  oauth_application_scopes %w[openid email profile some_other_non_openid_scope]

  # callback to retrieve normal claims.
  # https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims P. 5.4
  get_oidc_param do |account, oidc_claim|
    case oidc_claim
    when :email
      # return the email
    when :email_verified
      # returns true or false
      # ... and so on
    end
  end
end

URLs

GET /authorize

The URI under which the journey begins is (by default, like in OAuth 2.0) /authorize. It supports the same parameters as the OAuth 2.0 authorization endpoint, along with extra parameters (read the ID Token RFC 3.1.2.1 for a more detailed description):

  • client_id: used to select the relying party, or client application;
  • redirect_uri: used to validate and indicate where the user agent should redirect the authenticated user;
  • scope: whitespace-separated permission scopes to set on the tokens (if not passed, the grant will be generated from the client application scopes; if passed, they need to be all or a subset of the client application scopes). For OpenID, the “openid” scope is mandatory (extra OpenID scopes: profile, email, address, or the special offline_access, if a refresh token is to be generated); other non-OpenID scopes can be passed;
  • state: (optional) opaque string value, can be used by the relying party to maintain state between the request and callback for redirection validation;
  • response_type: identifies the type of authentication flow;
  • nonce: (optional) opaque value which will be associated with the ID token as an extra claim, and can be used by the relying party to verify whether an ID token was generated from a particular authentication session.
  • prompt: (optional) one of none, login, consent or select-account, signals what the authorization server should do before allowing the user to submit authorization, such as (respectively) relogin, grant consent, or explicitly select an account (NOTE: in order to use the select-account option, make sure you install and enable the select_account feature)
  • display (optional): specifies how the authentication session is displayed (rodauth-oauth does not use it, but the integrator can use it to pick up a different (i.e. embed or mobile friendly) layout.
  • max_age (optional): when passed, is used as a threshold which, if surpassed by the existing authenticated session lifetime, forces the user to relogin (it can be verified by the relying party using the "auth_time" claim available in the ID Token).
  • ui_locales (optional): whitespace-separated list of language codes (ordered by preference); if the i18n feature is installed and enabled, it’ll pick up the language for which translations are available, by order of preference.
  • claims_locales (optional): whitespace-separated list of language codes, for which ID token claims can be translated (if get_oid_param or get_additional_param are defined with a 3rd argument, it’ll be passed the locale code, for which you can provide a translation);
  • acr_values (optional): whitespace-separated list of Authentication Context references, which the OpenID provider can use in the processing of the Authentication request (the used acr values will be set as extra claims in the ID Token). rodauth-oauth provides support for the EAP defined ACR values "phr" and "phrh", whereby:
    • when "phr" is set in "acr_values" and a 2 factor rodauth feature (such as otp or sms_codes) is loaded, it’ll require it when authenticating the user with OpenID Provider.
    • when "phr" is set in "acr_values" and rodauth “webauthn_login” feature is loaded, it’ll require it when authenticating the user with OpenID Provider.
    • anything else is up to the integrator via the require_acr_value callback.
  • claims (optional): used to enable specific claims to be returned from the UserInfo Endpoint and/or in the ID Token.

Example: https://oauth-server.com/authorize?client_id=23uhu23d89u3298du21j38q&redirect_uri=https%3A%2F%2Fclient.com%2Fcallback&scope=openid+email+profile.name+bricks.build+bricks.destroy&nonce=23r0rif3j0923j

The :oidc feature also supports secured authorization requests.

Note: the offline_access scope is also supported.

ID Token

The ID token is a security token containing the claims defined by the OpenID spec, such as email, full name, phone number, etc. Its usage is restricted to providing authentication claims only, it should not be used when requesting anything from resource servers (that’s what the access token is for).

Claim Types

It supports the Standard Claims via the get_oidc_param function, which can be used by the integration to provide the value, as per the example above. If you pass it a standard claim in the scope, the extended claims will be exposed to get_oidc_param, i.e with scope=openid email as scope param, both the email and email_verified claims will be requested via get_oidc_param.

Distributed and aggregated claims can be implemented by overriding the fill_with_account_claims auth method:

plugin :rodauth do
  enable :oidc

  fill_with_account_claims do |claims, account, scopes, claims_locales|
    super(claims, account, scopes, claims_locales)
    if scopes.include?("profile") # if this is what you want to filter it by
      claims[:_claim_names] = {
        "payment_info" => "src1",
        "shipping_address" => "src1",
        "credit_score" => "src2"
      }
      claims[:_claim_sources] = {
        "src1" => {"endpoint" => "https://bank.example.com/claim_source"},
         "src2": {"endpoint" => "https://creditagency.example.com/claims_here",
                  "access_token" => "ksj3n283dke"}
      }
    end
  end

Signed and (optionally) encrypted

The ID token is signed, and optionally encrypted. If the Provider exposes multiple signing JWKs, client applications can choose which signing algorithm their ID tokens should be signed with, by setting the client application attribute oauth_applications_id_token_signed_response_alg_column (encryption options for the same token are oauth_applications_id_token_encrypted_response_alg_column and oauth_applications_id_token_encrypted_response_enc_column).

Home