OAuth2ClientFilter

The OAuth2ClientFilter uses OAuth 2.0 delegated authorization to authenticate end users. The filter can act as an OpenID Connect relying party or as an OAuth 2.0 client.

OAuth2ClientFilter performs the following tasks:

  • Allows the user to select an authorization server from one or more static client registrations, or by discovery and dynamic registration.

    In static client registration, authorization servers are provided by "Issuer", and registrations are provided by "ClientRegistration".

  • Redirects the user through the authentication and authorization steps of an OAuth 2.0 authorization code grant, which results in the authorization server returning an access_token to the filter.

  • When an authorization grant succeeds, injects the access_token data into a configurable target in the context so that subsequent filters and handlers can access the access_token. Subsequent requests can use the access_token without authenticating again.

  • When an authorization grant fails, invokes a failureHandler.

Service URIs

Service URIs are constructed from the clientEndpoint. Task that the OAuth2ClientFilter performs is determined by the service URI, as follows:

clientEndpoint/login/?discovery=user-input&goto=url

Discover and register dynamically with the end user's OpenID Provider or with the client registration endpoint as described in RFC 7591, using the value of user-input.

After successful registration, redirect the end user to the provider for authentication and authorization consent. Then redirect the user-agent back to the callback client endpoint, and then the goto URI.

The goto URL must use the same scheme, host, and port as the original URI, or be a relative URI (just the path). Otherwise, the request fails with an error. To redirect a request to a site that does not meet the goto URL criteria, change the original URI by using a ForwardedRequestFilter.

Supported with OpenAM 13 and later versions, and AM 5 and later versions.

clientEndpoint/login?registration=clientId&issuer=issuerName&goto=url

Redirect the end user for authorization with the specified registration, defined by the ClientRegistration's clientId and issuerName. For information, see "ClientRegistration".

The provider corresponding to the registration then authenticates the end user and obtains authorization consent before redirecting the user-agent back to the callback client endpoint.

If the whole process is successful, the filter saves the authorization state in the session and redirects the user-agent to the specified goto URL.

The goto URL must use the same scheme, host, and port as the original URI, or be a relative URI (just the path). Otherwise, the request fails with an error. To redirect a request to a site that does not meet the goto URL criteria, change the original URI by using a ForwardedRequestFilter.

clientEndpoint/logout?goto=url

Remove the authorization state for the end user, and redirect to the specified goto URL.

The goto URL must use the same scheme, host, and port as the original URI, or be a relative URI (just the path). Otherwise, the request fails with an error. To redirect a request to a site that does not meet the goto URL criteria, change the original URI by using a ForwardedRequestFilter.

If no goto URL is specified in the request, use the defaultLogoutGoto.

clientEndpoint/callback

Handle the callback from the OAuth 2.0 authorization server, that occurs as part of the authorization process.

If the callback is handled successfully, the filter saves the authorization state in the context at the specified target location and redirects to the URL provided to the login endpoint during login.

Other request URIs

Restore the authorization state in the specified target location, and call the next filter or handler in the chain.

Usage

{
  "name": string,
  "type": "OAuth2ClientFilter",
  "config": {
    "clientEndpoint": runtime expression<uri sting>,
    "failureHandler": Handler reference,
    "loginHandler": Handler reference,
    "registrations": [ ClientRegistration reference(s) ],
    "metadata": dynamic registration client metadata object,
    "cacheExpiration": configuration expression<duration>,
    "executor": executor service reference,
    "target": configuration expression<lvalue-expression>,
    "defaultLoginGoto": runtime expression<uri string>,
    "defaultLogoutGoto": runtime expression<uri string>,
    "requireHttps": configuration expression<boolean>,
    "requireLogin": configuration expression<boolean>,
    "issuerRepository": Issuer repository reference,
    "discoveryHandler": Handler reference,
    "discoverySecretId": configuration expression<secret-id>,
    "tokenEndpointAuthMethod": configuration expression<enumeration>,
    "tokenEndpointAuthSigningAlg": configuration expression<string>,
    "secretsProvider": SecretsProvider reference
  }
}

Properties

"clientEndpoint": runtime expression<uri string>, required

The URI to the client endpoint.

So that routes can accept redirects from the authorization server to the callback endpoint, the clientEndpoint must be the same as the route condition or a sub path of the route condition. For example:

  • The same as the route condition:

    "condition": "${matches(request.uri.path, '^/discovery')}"

    "clientEndpoint": "/discovery"

  • As a sub path of the route condition:

    "condition": "${matches(request.uri.path, '^/home/id_token')}"

    "clientEndpoint": "/home/id_token/sub-path"

The service URIs are constructed from the clientEndpoint. For example, when clientEndpoint is openid, the service URIs are /openid/login, /openid/logout, and /openid/callback. These endpoints are implicitly reserved, and attempts to access them directly can cause undefined errors.

The result of the expression must be a string that represents a valid URI, but is not a real java.net.URI object. For example, it would be incorrect to use ${request.uri}, which is not a String but a MutableUri.

See also "Expressions".

"failureHandler": handler reference, required

Provide an inline handler configuration object, or the name of a handler object that is defined in the heap.

When the OAuth 2.0 Resource Server denies access to a resource, the failure handler can be invoked only if the error response contains a WWW-Authenticate header (meaning that there was a problem with the OAuth 2.0 exchange). All other responses are forwarded to the user-agent without invoking the failure handler.

If the value of the WWW-Authenticate header is invalid_token, the OAuth2ClientFilter tries to refresh the access_token:

  • If the token is refreshed, the OAuth2ClientFilter tries again to access the protected resource.

  • If the token is not refreshed, or if the second attempt to access the protected resource fails, the OAuth2ClientFilter invokes the failure handler.

When the failure handler is invoked, the target in the context can be populated with information such as the exception, client registration, and error. The failure object in the target is a simple map, similar to the following example:

{
    "client_registration": "ClientRegistration name string",
    "error": {
        "realm": "optional string",
        "scope": [ "optional scope string (required by the client)", ... ],
        "error": "optional string",
        "error_description": "optional string",
        "error_uri": "optional string"
    },
    "access_token": "string",
    "id_token": "string",
    "token_type": "Bearer",
    "expires_in": "number",
    "scope": [ "optional scope string", ... ],
    "client_endpoint": "URL string",
    "exception": exception
}

In the failure object, the following fields are not always present. Their presence depends on when the failure occurs:

  • "access_token"

  • "id_token"

  • "token_type"

  • "expires_in"

  • "scope"

  • "client_endpoint"

See also Handlers.

"loginHandler": Handler reference, required if there are zero or multiple client registrations, optional if there is one client registration

Use this Handler when the user must choose an authorization server. When registrations contains only one client registration, this Handler is optional but is displayed if specified.

Provide either the name of a Handler object defined in the heap, or an inline Handler configuration object.

See also Handlers.

"registrations": Array of ClientRegistration references or inline ClientRegistration declarations, optional

List of client registrations that authenticate IG to the authorization server. The list must contain all client registrations that are to be used by the client filter.

The value represents a static client registration with an authorization server, as described in "ClientRegistration".

"metadata": client metadata object, required for dynamic client registration and ignored otherwise

This object holds client metadata as described in OpenID Connect Dynamic Client Registration 1.0 , and optionally a list of scopes. See that document for additional details and a full list of fields.

This object can also hold client metadata as described in RFC 7591, OAuth 2.0 Dynamic Client Registration Protocol . See that RFC for additional details.

The following partial list of metadata fields is not exhaustive, but includes metadata that is useful with AM as OpenID Provider:

"redirect_uris": array of URI strings, required

The array of redirection URIs to use when dynamically registering this client.

One of the registered values must match the clientEndpoint.

"client_name": string, optional

Name of the client to present to the end user.

"scope": space separated string, optional

Space separated string of scopes to request of the OpenID Provider, for example:

"scope": "openid profile"

This property is available for dynamic client registration with AM 5.5 and later versions, or with authorization servers that support RFC 7591, OAuth 2.0 Dynamic Client Registration Protocol

Use both scope and scopes to dynamically register with a wider range of identity providers.

"scopes": array of strings, optional

Array of scope strings to request of the OpenID Provider, for example:

"scopes": [
  "openid",
  "profile",
  "email"
]

This property is available for dynamic client registration with AM 5.5 and earlier versions only.

Use both scope and scopes to dynamically register with a wider range of identity providers.

"cacheExpiration": configuration expression<duration>, optional

Duration for which to cache user-info resources.

IG lazily fetches user info from the OpenID provider. In other words, IG only fetches the information when a downstream Filter or Handler uses the user info. Caching allows IG to avoid repeated calls to OpenID providers when reusing the information over a short period.

Default: 10 minutes

Set this to disabled or zero to disable caching. When caching is disabled, user info is still lazily fetched.

For information about supported formats for duration, see duration.

"executor": executor service reference, optional

An executor service to schedule the execution of tasks, such as the eviction of entries in the OpenID Connect user information cache.

Default: ScheduledExecutorService

See also "ScheduledExecutorService".

"target": configuration expression<lvalue-expression>, optional

An expression that yields the target object. Downstream filters and handlers can use data in the target to enrich the existing request or create a new request.

When the target is openid, the following information can be provided in ${attributes.openid}:

  • access_token: The value of the OAuth 2.0 access_token

  • client_endpoint: The URL to the client endpoint

  • client_registration: The client ID of the OAuth 2.0 client that enables IG to communicate as an OAuth 2.0 client with an authorization server

  • expires_in: Number of milliseconds until the token expires

  • id_token_claims: The claims used in the token

  • scope: The scopes associated with the token

  • token_type: The type or authentication token

  • user_info: The profile attributes of an authenticated user

Data is provided to the target as follows:

  • If the authorization process completes successfully, the OAuth2ClientFilter injects the authorization state data into the target. In the following example, a downstream StaticRequestFilter retrieves the username and password from the target to log the user in to the sample application.

    {
      "type": "StaticRequestFilter",
      "config": {
        "method": "POST",
        "uri": "http://app.example.com:8081/login",
        "form": {
          "username": [
            "${attributes.openid.user_info.sub}"
          ],
           "password": [
            "${attributes.openid.user_info.family_name}"
          ]
        }
      }
    }

    For information about setting up this example, see "Authenticating Automatically to the Sample Application".

  • If the failure handler is invoked, the target can be populated with information such as the exception, client registration, and error, as described in "failureHandler" in this reference page.

Default: ${attributes.openid}

See also "Expressions".

"defaultLoginGoto": runtime expression<uri string>, optional

After successful authentication and authorization, if the user accesses the clientEndpoint/login endpoint without providing a landing page URL in the goto parameter, the request is redirected to this URI.

The goto URL must use the same scheme, host, and port as the original URI, or be a relative URI (just the path). Otherwise, the request fails with an error. To redirect a request to a site that does not meet the goto URL criteria, change the original URI by using a ForwardedRequestFilter.

The result of the expression must be a string that represents a valid URI, but is not a real java.net.URI object. For example, it would be incorrect to use ${request.uri}, which is not a String but a MutableUri.

Default: return an empty page.

See also "Expressions".

"defaultLogoutGoto": runtime expression<uri string>, optional

If the user accesses the clientEndpoint/logout endpoint without providing a goto URL, the request is redirected to this URI.

The goto URL must use the same scheme, host, and port as the original URI, or be a relative URI (just the path). Otherwise, the request fails with an error. To redirect a request to a site that does not meet the goto URL criteria, change the original URI by using a ForwardedRequestFilter.

The result of the expression must be a string that represents a valid URI, but is not a real java.net.URI object. For example, it would be incorrect to use ${request.uri}, which is not a String but a MutableUri.

Default: return an empty page.

See also "Expressions".

"requireHttps": configuration expression<boolean>, optional

Whether to require that original target URI of the request (originalUri in "UriRouterContext") uses the HTTPS scheme.

If the request received by the web container is not using HTTPS, the request is rejected.

Default: true.

"requireLogin": configuration expression<boolean>, optional

Whether to require authentication for all incoming requests.

Default: true.

"issuerRepository": Issuer repository reference, optional

A repository of OAuth 2.0 issuers, built from discovered issuers and the IG configuration.

Provide the name of an IssuerRepository object defined in the heap.

Default: Look up an issuer repository named IssuerRepository in the heap. If none is explicitly defined, then a default one named IssuerRepository is created in the current route.

See also "IssuerRepository".

"discoveryHandler": Handler reference, optional

Use this property for discovery and dynamic registration of OpenID Connect clients.

Provide either the name of a Handler object defined in the heap, or an inline Handler configuration object. Usually set this to the name of a ClientHandler configured in the heap, or a chain that ends in a ClientHandler.

Default: The default ClientHandler.

See also Handlers, "ClientHandler".

"discoverySecretId": configuration expression<secret-id>, required for discovery and dynamic registration

Use this property for discovery and dynamic registration of OAuth 2.0 clients.

Specifies the secret ID of the secret that is used to sign a JWT before the JWT is sent to the authorization server.

If discoverySecretId is used, then the tokenEndpointAuthMethod is always private_key_jwt.

For information about supported formats for secret-id, see secret-id.

"tokenEndpointAuthMethod": configuration expression<enumeration>, optional

Use this property for discovery and dynamic registration of OAuth 2.0 clients.

The authentication method with which a client authenticates to the authorization server or OpenID provider at the token endpoint. For information about client authentication methods, see OpenID Client Authentication. The following client authentication methods are allowed:

  • client_secret_basic: Clients that have received a client_secret value from the authorization server authenticate with the authorization server by using the HTTP Basic authentication scheme, as in the following example:

    POST /oauth2/token HTTP/1.1
    Host: as.example.com
    Authorization: Basic ....
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=authorization_code&
    code=...

  • client_secret_post: Clients that have received a client_secret value from the authorization server authenticate with the authorization server by including the client credentials in the request body, as in the following example:

    POST /oauth2/token HTTP/1.1
    Host: as.example.com
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=authorization_code&
    client_id=...&
    client_secret=...&
    code=...

  • private_key_jwt: Clients send a signed JSON Web Token (JWT) to the authorization server. IG builds and signs the JWT, and prepares the request as in the following example:

    POST /token HTTP/1.1
    Host: as.example.com
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=authorization_code&
    code=...&
    client_id=<clientregistration_id>&
    client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&
    client_assertion=PHNhbWxwOl ... ZT

    If the authorization server doesn't support private_key_jwt, a dynamic registration falls back on the method returned by the authorization server, for example, client_secret_basic or client_secret_post.

    If tokenEndpointAuthSigningAlg is not configured, the RS256 signing algorithm is used for private_key_jwt.

Consider these points for identity providers:

  • Some providers accept more than one authentication method.

  • If a provider strictly enforces how the client must authenticate, align the authentication method with the provider.

  • If a provider doesn't support the authentication method, the provider sends an HTTP 400 Bad Request response with an invalid_client error message, according to RFC 6749 The OAuth 2.0 Authorization Framework, section 5.2 .

  • If the authentication method is invalid, the provider sends an IllegalArgumentException.

Default:

  • If discoverySecretId is used, then the tokenEndpointAuthMethod is always private_key_jwt.

  • Otherwise, client_secret_basic

"tokenEndpointAuthSigningAlg": configuration expression<string>, optional

The JSON Web Algorithm (JWA) used to sign the JWT that is used to authenticate the client at the token endpoint. The property is used when private_key_jwt is used for authentication.

If the authorization server sends a notification to use a different algorithm to sign the JWT, that algorithm is used.

Default:

  • If discoverySecretId is used, then the tokenEndpointAuthSigningAlg is RS256.

  • Otherwise, not used.

"secretsProvider": SecretsProvider reference, required

The "SecretsProvider" to use to resolve queried secrets, such as passwords and cryptographic keys. Provide either the name of a SecretsProvider object defined in the heap, or specify a SecretsProvider object inline.

Read a different version of :