Docsright arrowEdge Stackright arrowUsing The OAuth2 Filter

12 min • read

Using The OAuth2 Filter

The OAuth2 filter type performs OAuth2 authorization against an identity provider implementing OIDC Discovery. The filter is both:

  • An OAuth Client, which fetches resources from the Resource Server on the user's behalf.
  • Half of a Resource Server, validating the Access Token before allowing the request through to the upstream service, which implements the other half of the Resource Server.

This is different from most OAuth implementations where the Authorization Server and the Resource Server are in the same security domain. With Ambassador Edge Stack, the Client and the Resource Server are in the same security domain, and there is an independent Authorization Server.


See the OAuth2 Filter API reference for an overview of all the supported fields.

The Ambassador authentication flow

This is what the authentication process looks like at a high level when using Ambassador Edge Stack with an external identity provider. The use case is an end-user accessing a secured app service.

Ambassador Authentication OAuth/OIDC

Some basic authentication terms

For those unfamiliar with authentication, here is a basic set of definitions.

  • OpenID: is an open standard and decentralized authentication protocol. OpenID allows users to be authenticated by co-operating sites, referred to as "relying parties" (RP) using a third-party authentication service. End-users can create accounts by selecting an OpenID identity provider (such as Auth0, Okta, etc), and then use those accounts to sign onto any website that accepts OpenID authentication.
  • Open Authorization (OAuth): an open standard for token-based authentication and authorization on the Internet. OAuth provides to clients a "secure delegated access" to server or application resources on behalf of an owner, which means that although you won't manage a user's authentication credentials, you can specify what they can access within your application once they have been successfully authenticated. The current latest version of this standard is OAuth 2.0.
  • Identity Provider (IdP): an entity that creates, maintains, and manages identity information for user accounts (also referred to "principals") while providing authentication services to external applications (referred to as "relying parties") within a distributed network, such as the web.
  • OpenID Connect (OIDC): is an authentication layer that is built on top of OAuth 2.0, which allows applications to verify the identity of an end-user based on the authentication performed by an IdP, using a well-specified RESTful HTTP API with JSON as a data format. Typically an OIDC implementation will allow you to obtain basic profile information for a user that successfully authenticates, which in turn can be used for implementing additional security measures like Role-based Access Control (RBAC).
  • JSON Web Token (JWT): is a JSON-based open standard for creating access tokens, such as those generated from an OAuth authentication. JWTs are compact, web-safe (or URL-safe), and are often used in the context of implementing single sign-on (SSO) within federated applications and organizations. Additional profile information, claims, or role-based information can be added to a JWT, and the token can be passed from the edge of an application right through the application's service call stack.

If you look back at the authentication process diagram, the function of the entities involved should now be much clearer.

Using an identity hub

Using an identity hub or broker allows you to support many IdPs without having to code individual integrations with them. For example, Auth0 and Keycloak both offer support for using Google and GitHub as an IdP.

An identity hub sits between your application and the IdP that authenticates your users, which not only adds a level of abstraction so that your application (and Ambassador Edge Stack) is isolated from any changes to each provider's implementation, but it also allows your users to chose which provider they use to authenticate (and you can set a default, or restrict these options).

The Auth0 docs provide a guide for adding social IdP "connections" to your Auth0 account, and the Keycloak docs provide a guide for adding social identity "brokers".

OAuth2 path-specific arguments

  • scope: A list of OAuth scope values to include in the scope of the authorization request. If one of the scope values for a path is not granted, then access to that resource is forbidden; if the scope argument lists foo, but the authorization response from the provider does not include foo in the scope, then it will be taken to mean that the authorization server forbade access to this path, as the authenticated user does not have the foo resource scope.

    If grantType: "AuthorizationCode", then the openid scope value is always included in the requested scope, even if it is not listed in the FilterPolicy argument.

    If grantType: "ClientCredentials" or grantType: "Password", then the default scope is empty. If your identity provider does not have a default scope, then you will need to configure one here.

    As a special case, if the offline_access scope value is requested, but not included in the response then access is not forbidden. With many identity providers, requesting the offline_access scope is necessary to receive a Refresh Token.

    The ordering of scope values does not matter, and is ignored.

  • scopes is deprecated, and is equivalent to setting scope.

  • insteadOfRedirect: An action to perform instead of redirecting the User-Agent to the identity provider, when using grantType: "AuthorizationCode". By default, if the User-Agent does not have a currently-authenticated session, then the Ambassador Edge Stack will redirect the User-Agent to the identity provider. Setting insteadOfRedirect allows you to modify this behavior. insteadOfRedirect does nothing when grantType: "ClientCredentials", because the Ambassador Edge Stack will never redirect the User-Agent to the identity provider for the client credentials grant type.

    • If insteadOfRedirect is non-null, then by default it will apply to all requests that would cause the redirect; setting the ifRequestHeader sub-argument causes it to only apply to requests that have the HTTP header field name (case-insensitive) either set to (if negate: false) or not set to (if negate: true)
      • a non-empty string if neither value nor valueRegex are set
      • the exact string value (case-sensitive) (if value is set)
      • a string that matches the regular expression valueRegex (if valueRegex is set). This uses RE2 syntax (always, not obeying regex_type in the Module) but does not support the \C escape sequence.
    • By default, it serves an authorization-denied error page; by default HTTP 403 ("Forbidden"), but this can be configured by the httpStatusCode sub-argument.
    • DEPRECATED Instead of serving that simple error page, it can instead be configured to call out to a list of other Filters, by setting the filters list. The syntax and semantics of this list are the same as .spec.rules[].filters in a FilterPolicy. Be aware that if one of these filters modify the request rather than returning a response, then the request will be allowed through to the backend service, even though the OAuth2 Filter denied it.
    • It is invalid to specify both httpStatusCode and filters.

XSRF protection

The ambassador_xsrf.NAME.NAMESPACE cookie is an opaque string that should be used as an XSRF token. Applications wishing to leverage the Ambassador Edge Stack in their XSRF attack protection should take two extra steps:

  1. When generating an HTML form, the server should read the cookie, and include a <input type="hidden" name="_xsrf" value="COOKIE_VALUE" /> element in the form.
  2. When handling submitted form data should verify that the form value and the cookie value match. If they do not match, it should refuse to handle the request, and return an HTTP 4XX response.

Applications using request submission formats other than HTML forms should perform analogous steps of ensuring that the value is present in the request duplicated in the cookie and also in either the request body or secure header field. A secure header field is one that is not Cookie, is not "simple", and is not explicitly allowed by the CORS policy.

Proof Key for Code Exchange (PKCE)

Proof Key for Code Exchange (PKCE) is an extension to the standard OAuth2 Authorization Code Flow outlined in rfc7636, which helps protect against auhorization code interception attacks. Ambassador Edge Stack 3.10+ has added support for configuring PKCE to the gateway.getambassador.io/v1alpha1 Custom Resources. It is highly recommended to use PKCE if you are using the Authorization Code Flow and your identity provider supports PKCE.

Here is an example of how you can easily configure your Filter resource by just adding pkce: {}:

RP-initiated logout

When a logout occurs, it is often not enough to delete the Ambassador Edge Stack's session cookie or session data; after this happens, and the web browser is redirected to the Identity Provider to re-log-in, the Identity Provider may remember the previous login, and immediately re-authorize the user; it would be like the logout never even happened.

To solve this, the Ambassador Edge Stack can use OpenID Connect Session Management to perform an "RP-Initiated Logout", where Edge Stack (the OpenID Connect "Relying Party" or "RP") communicates directly with Identity Providers that support OpenID Connect Session Management, to properly log out the user. Unfortunately, many Identity Providers do not support OpenID Connect Session Management.

This is done by having your application direct the web browser POST and navigate to /.ambassador/oauth2/logout. There are 2 form-encoded values that you need to include:

  1. realm: The name.namespace of the Filter that you want to log out of. This may be submitted as part of the POST body, or may be set as a URL query parameter.
  2. _xsrf: The value of the ambassador_xsrf.{{realm}} cookie (where {{realm}} is as described above). This must be set in the POST body, the URL query part will not be checked.

Example configurations

Using JavaScript:

Redis

The Ambassador Edge Stack relies on Redis to store short-lived authentication credentials and rate limiting information. If the Redis data store is lost, users will need to log back in and all existing rate-limits would be reset.

Further reading

In this architecture, Ambassador Edge Stack is functioning as an Identity Aware Proxy in a Zero Trust Network. For more about this security architecture, read the BeyondCorp security architecture whitepaper by Google.

The "How-to" section has detailed tutorials on integrating Ambassador with a number of Identity Providers.