OAuth

This feature is available in Gloo Enterprise only. If you are using the open source version of Gloo, this tutorial will not work.

Gloo Edge supports authentication via OpenID Connect (OIDC). OIDC is an identity layer on top of the OAuth 2.0 protocol. In OAuth 2.0 flows, authentication is performed by an external Identity Provider (IdP) which, in case of success, returns an Access Token representing the user identity. The protocol does not define the contents and structure of the Access Token, which greatly reduces the portability of OAuth 2.0 implementations.

The goal of OIDC is to address this ambiguity by additionally requiring Identity Providers to return a well-defined ID Token. OIDC ID tokens follow the JSON Web Token standard and contain specific fields that your applications can expect and handle. This standardization allows you to switch between Identity Providers - or support multiple ones at the same time - with minimal, if any, changes to your downstream services; it also allows you to consistently apply additional security measures like Role-based Access Control (RBAC) based on the identity of your users, i.e. the contents of their ID token (check out this guide for an example of how to use Gloo Edge to apply RBAC policies to JWTs).

In this guide, we will focus on the format of the Gloo Edge API for OIDC authentication.

This feature requires Gloo Edge’s external auth server to communicate with an external OIDC provider/authorization server. Because of this interaction, the OIDC flow may take longer than the default timeout of 200ms. You can increase this timeout by setting the requestTimeout value on external auth settings . The external auth settings can be configured on the global Gloo Edge Settings object .

Configuration format

The auth configuration format shown on this page was introduced with Gloo Enterprise, release 0.20.1. If you are using an earlier version, please refer to this page to see which configuration formats are supported by each version.

Following is an example of an AuthConfig with an OIDC configuration (for more information on AuthConfig CRDs, see the main page of the authentication docs):

apiVersion: enterprise.gloo.solo.io/v1
kind: AuthConfig
metadata:
  name: oidc
  namespace: gloo-system
spec:
  configs:
  - oauth2:
      oidcAuthorizationCode:
        issuerUrl: theissuer.com
        appUrl: https://myapp.com
        authEndpointQueryParams:
          paramKey: paramValue
        callbackPath: /my/callback/path/
        clientId: myclientid
        clientSecretRef:
          name: my-oauth-secret
          namespace: gloo-system
        scopes:
        - email

The AuthConfig consists of a single config of type oauth. Let’s go through each of its attributes:

The callback path must have a matching route in the VirtualService associated with the OIDC settings. For example, you could simply have a / path-prefix route which would match any callback path. The important part of this callback “catch all” route is that it goes through the routing filters including external auth. Please see the examples for Google, Dex, and Okta.

Use the cookieOptions field to customize cookie behavior:

Example configuration:

apiVersion: enterprise.gloo.solo.io/v1
kind: AuthConfig
metadata:
  name: oidc-dex
  namespace: gloo-system
spec:
  configs:
  - oauth2:
      oidcAuthorizationCode:
        appUrl: http://localhost:8080/
        callbackPath: /callback
        clientId: gloo
        clientSecretRef:
          name: oauth
          namespace: gloo-system
        issuerUrl: http://dex.gloo-system.svc.cluster.local:32000/
        scopes:
        - email
        session:
          cookieOptions:
            notSecure: true
            maxAge: 3600

Logout URL

Gloo also supports specifying a logout url. When specified, accessing this url will trigger a deletion of the user session and revoke the user’s access token. This action returns with an empty 200 HTTP response.

Example configuration:

apiVersion: enterprise.gloo.solo.io/v1
kind: AuthConfig
metadata:
  name: oidc-dex
  namespace: gloo-system
spec:
  configs:
  - oauth2:
      oidcAuthorizationCode:
        appUrl: http://localhost:8080/
        callbackPath: /callback
        clientId: gloo
        clientSecretRef:
          name: oauth
          namespace: gloo-system
        issuerUrl: http://dex.gloo-system.svc.cluster.local:32000/
        scopes:
        - email
        logoutPath: /logout

When this URL is accessed, the user session and cookie are deleted. The access token on the server is also revoked based on the discovered revocation endpoint. You can also override the revocation endpoint through the DiscoveryOverride field in AuthConfig.

If the authorization server has a service error, Gloo logs out the user, but does not retry revoking the access token. Check the logs and your identity provider for errors, and manually revoke the access token.

Sessions in Cookies

You can store the ID token, access token, and other tokens that are returned from your OIDC provider in a cookie on the client side. To do this, you configure your cookie options, such as the keyPrefix that you want to add to the token name, in the oauth2.oidcAuthorizationCode.session.cookie section of your authconfig as shown in the following example. After a client successfully authenticates with the OIDC provider, the tokens are stored in the Set-Cookie response header and sent to the client. If you set a keyPrefix value in your cookie configuration, the prefix is added to the name of the token before it is sent to the client, such as Set-Cookie: <myprefix>_id-token=<ID_token>. To prove successful authentication with the OIDC provider in subsequent requests, clients send their tokens in a Cookie header.

Cookie headers can have a maximum size of 4KB. If you find that your cookie header exceeds this value, you can either limit the size of the cookie header or store the tokens in Redis and send back a Redis session ID instead.

Storing the raw, unencrypted tokens in a cookie header is not a recommended security practice as they can be manipulated through malicious attacks. To encrypt your tokens, see Symmetric cookie encryption. For a more secure setup, store the tokens in a Redis instance and send back a Redis session ID in the cookie header.

Example configuration:

apiVersion: enterprise.gloo.solo.io/v1
kind: AuthConfig
metadata:
  name: oidc-dex
  namespace: gloo-system
spec:
  configs:
  - oauth2:
      oidcAuthorizationCode:
        appUrl: http://localhost:8080/
        callbackPath: /callback
        clientId: gloo
        clientSecretRef:
          name: oauth
          namespace: gloo-system
        issuerUrl: http://dex.gloo-system.svc.cluster.local:32000/
        scopes:
        - email
        session:
          cookie:
            keyPrefix: "my_cookie_prefix"

By default, the tokens that are sent in the cookie header are not encrypted and can be manipulated through malicious attacks. To encrypt the cookie values, you can add a cipherConfig section to your session configuration as shown in the following example.

Setting the cipherConfig attribute is supported in Gloo Edge version 1.15 and later and can be used only to encrypt cookie sessions. You cannot use this feature to encrypt Redis sessions.

  1. Create a secret with your encryption key. Note that the key must be 32 bytes in length.

    glooctl create secret encryptionkey --name my-encryption-key --key "an example of an encryption key1"
    
  2. Reference the secret in the cipherConfig section of your authconfig.

       ...
       kind: AuthConfig
       spec:
         configs:
         - oauth2:
              oidcAuthorizationCode:
                session:
                  cipherConfig:
                    keyRef:
                      name: my-encryption-key
                      namespace: gloo-system
                    cookie:
                      keyPrefix: "my_cookie_prefix"
       

Sessions in Redis

By default, the tokens will be saved in a secure client side cookie. Gloo can instead use Redis to save the OIDC tokens, and set a randomly generated session id in the user’s cookie. Going forward in the Gloo Edge documentation, we will be using examples of OIDC using a redis session.

Example configuration:

apiVersion: enterprise.gloo.solo.io/v1
kind: AuthConfig
metadata:
  name: oidc-dex
  namespace: gloo-system
spec:
  configs:
  - oauth2:
      oidcAuthorizationCode:
        appUrl: http://localhost:8080/
        callbackPath: /callback
        clientId: gloo
        clientSecretRef:
          name: oauth
          namespace: gloo-system
        issuerUrl: http://dex.gloo-system.svc.cluster.local:32000/
        scopes:
        - email
        session:
          failOnFetchFailure: true
          redis:
            cookieName: session
            options:
              host: redis.gloo-system.svc.cluster.local:6379

Forwarding the ID token upstream

You can configure gloo to forward the id token to the upstream on successful authentication. To do that, set the headers section in the configuration.

Example configuration:

apiVersion: enterprise.gloo.solo.io/v1
kind: AuthConfig
metadata:
  name: oidc-dex
  namespace: gloo-system
spec:
  configs:
  - oauth2:
      oidcAuthorizationCode:
        appUrl: http://localhost:8080/
        callbackPath: /callback
        clientId: gloo
        clientSecretRef:
          name: oauth
          namespace: gloo-system
        issuerUrl: http://dex.gloo-system.svc.cluster.local:32000/
        scopes:
        - email
        headers:
          idTokenHeader: "x-token"

Proof Key for Code Exchange (PKCE) for public and untrusted clients

In a traditional OAuth Authorization flow, the client sends a client secret to the authorization server to request an access token. Depending on the type of client that you use, the client secret might be shared across users and devices. Public clients, such as a mobile app, cannot securely store the client secret as it is embedded in the web browser or can be retrieved by decompiling the app. To avoid authorization code injection attacks, you can leverage the Proof Key for Code Exchange (PKCE) OAuth extension.

PKCE builds on top of the OAuth2 protocol. Instead of sending a client secret to the authorization server, the client generates a random value that is called the Code Verifier and hashes the Code Verifier to create the Code Challenge. The Code Challenge is sent to the authorization server where it is stored for later verification. At the same time, the authorization server returns an authorization code that is good for one use. To request an access token, the client now sends the authorization code and the Code Verifier that was generated earlier. The authorization server hashes the Code Verifier and compares the result to the Code Challenge that the client sent earlier. If both values match, the client is authorized and an access token is returned.

With Gloo Edge, you can implement PKCE-secured OAuth flows by leveraging the authEndpointQueryParams and tokenEndpointQueryParams fields in the AuthConfig. For example, to send the code challenge, add the code_challenge query parameter to the authEndpointQueryParams field. To request an access token, include the code and code_verifier in the tokenEndpointQueryParams field.

PKCE-secured OAuth flows can be configured for all supported OIDC providers, except for Okta. Support for the Okta OIDC provider is planned to be added in Gloo Edge Enterprise version 1.15.0.

For more information, see the Auth0 docs.

Examples

We have seen how a sample OIDC AuthConfig is structured. For complete examples of how to set up an OIDC flow with Gloo Edge, check out the following guides: