OAuth2

  • This filter should be configured with the type URL type.googleapis.com/envoy.extensions.filters.http.oauth2.v3.OAuth2.

  • v3 API reference

The OAuth filter’s flow involves:

  • An unauthenticated user arrives at myapp.com, and the oauth filter redirects them to the authorization_endpoint for login. The client_id and the redirect_uri are sent as query string parameters in this first redirect.

  • After a successful login, the authn server should be configured to redirect the user back to the redirect_uri provided in the query string in the first step. In the below code example, we choose /callback as the configured match path. An “authorization grant” is included in the query string for this second redirect.

  • Using this new grant and the token_secret, the filter then attempts to retrieve an access token from the token_endpoint. The filter knows it has to do this instead of reinitiating another login because the incoming request has a path that matches the redirect_path_matcher criteria.

  • Upon receiving an access token, the filter sets cookies so that subseqeuent requests can skip the full flow. These cookies are calculated using the hmac_secret to assist in encoding.

  • The filter calls continueDecoding() to unblock the filter chain.

  • The filter sets IdToken and RefreshToken cookies if they are provided by Identity provider along with AccessToken. These cookie names can be customized by setting cookie_names.

When the authn server validates the client and returns an authorization token back to the OAuth filter, no matter what format that token is, if forward_bearer_token is set to true the filter will send over a cookie named BearerToken to the upstream. Additionally, the Authorization header will be populated with the same value.

The OAuth filter encodes URLs in query parameters using the URL encoding algorithm.

When receiving request redirected from the authorization service the Oauth filer decodes URLs from query parameters. However the encoded character sequences that represent ASCII control characters or extended ASCII codepoints are not decoded. The characters without defined meaning in URL according to RFC 3986 are also left undecoded. Specifically the following characters are left in the encoded form:

  • Control characters with values less than or equal 0x1F

  • Space (0x20)

  • DEL character (0x7F)

  • Extended ASCII characters with values greater than or equal 0x80

  • Characters without defined meaning in URL: "<>\^{}|

Note

By default, OAuth2 filter sets some cookies with the following names: BearerToken, OauthHMAC, and OauthExpires. These cookie names can be customized by setting cookie_names.

Attention

The OAuth2 filter is currently under active development.

Example configuration

The following is an example configuring the filter.

config:
  token_endpoint:
    cluster: oauth
    uri: oauth.com/token
    timeout: 3s
  authorization_endpoint: https://oauth.com/oauth/authorize/
  redirect_uri: "%REQ(x-forwarded-proto)%://%REQ(:authority)%/callback"
  redirect_path_matcher:
    path:
      exact: /callback
  signout_path:
    path:
      exact: /signout
  credentials:
    client_id: foo
    token_secret:
      name: token
      sds_config:
        path: "/etc/envoy/token-secret.yaml"
    hmac_secret:
      name: hmac
      sds_config:
        path: "/etc/envoy/hmac.yaml"
  # (Optional): defaults to 'user' scope if not provided
  auth_scopes:
  - user
  - openid
  - email
  # (Optional): set resource parameter for Authorization request
  resources:
  - oauth2-resource
  - http://example.com

Below is a complete code example of how we employ the filter as one of HttpConnectionManager HTTP filters

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address:
        protocol: TCP
        address: 127.0.0.1
        port_value: 10000
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          http_filters:
          - name: envoy.filters.http.oauth2
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.oauth2.v3.OAuth2
              config:
                token_endpoint:
                  cluster: oauth
                  uri: oauth.com/token
                  timeout: 3s
                authorization_endpoint: https://oauth.com/oauth/authorize/
                redirect_uri: "%REQ(x-forwarded-proto)%://%REQ(:authority)%/callback"
                redirect_path_matcher:
                  path:
                    exact: /callback
                signout_path:
                  path:
                    exact: /signout
                credentials:
                  client_id: foo
                  token_secret:
                    name: token
                    sds_config:
                      path: "/etc/envoy/token-secret.yaml"
                  hmac_secret:
                    name: hmac
                    sds_config:
                      path: "/etc/envoy/hmac.yaml"
                # (Optional): defaults to 'user' scope if not provided
                auth_scopes:
                - user
                - openid
                - email
                # (Optional): set resource parameter for Authorization request
                resources:
                - oauth2-resource
                - http://example.com
          - name: envoy.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
          tracing: {}
          codec_type: "AUTO"
          stat_prefix: ingress_http
          route_config:
            virtual_hosts:
            - name: service
              domains: ["*"]
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: service
                  timeout: 5s

  clusters:
  - name: service
    connect_timeout: 5s
    type: STATIC
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: service
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 127.0.0.1
                port_value: 8080
  - name: oauth
    connect_timeout: 5s
    type: LOGICAL_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: oauth
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: auth.example.com
                port_value: 443
    transport_socket:
      name: envoy.transport_sockets.tls
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
        sni: auth.example.com

Finally, the following code block illustrates sample contents inside a yaml file containing both credential secrets. Both the token_secret and the hmac_secret can be defined in one shared file.

static_resources:
  secrets:
  - name: token
    generic_secret:
      secret: <Your token secret here>
  - name: hmac
    generic_secret:
      secret: <Your hmac secret here>

Notes

When enabled, the OAuth filter does not protect against Cross-Site-Request-Forgery attacks on domains with cached authentication (in the form of cookies). It is recommended to pair this filter with the CSRF Filter to prevent malicious social engineering.

The service must be served over HTTPS for this filter to work properly, as the cookies use ;secure. Without https, your authorization_endpoint provider will likely reject the incoming request, and your access cookies will not be cached to bypass future logins.

The signout path will redirect the current user to ‘/’, and clear all authentication cookies related to the HMAC validation. Consequently, the OAuth filter will then restart the full OAuth flow at the root path, sending the user to the configured auth endpoint.

pass_through_matcher provides an interface for users to provide specific header matching criteria such that, when applicable, the OAuth flow is entirely skipped. When this occurs, the oauth_passthrough metric is incremented but success is not.

deny_redirect_matcher can be used to specify requests for which unauthorized response is returned on token expiration and will not automatically redirect to the authorization endpoint. Token refresh can be still performed during those requests by enabling the use_refresh_token flag. This behavior can be useful for AJAX requests which cannot handle redirects correctly.

use_refresh_token provides possibility to update access token by using a refresh token. By default after expiration the user is always redirected to the authorization endpoint to log in again. By enabling this flag a new access token is obtained using by a refresh token without redirecting the user to log in again. This requires the refresh token to be provided by authorization_endpoint when the user logs in. If the attempt to get an access token by using a refresh token fails then the user is redirected to the authorization endpoint as usual.

Generally, allowlisting is inadvisable from a security standpoint.

Statistics

The OAuth2 filter outputs statistics in the <stat_prefix>. namespace.

Name

Type

Description

oauth_failure

Counter

Total requests that were denied.

oauth_passthrough

Counter

Total request that matched a passthrough header.

oauth_success

Counter

Total requests that were allowed.

oauth_unauthorization_rq

Counter

Total unauthorized requests.

oauth_refreshtoken_success

Counter

Total successfull requests for update access token using by refresh token

oauth_refreshtoken_failure

Counter

Total failed requests for update access token using by refresh token