You can use Gloo Gateway external auth to authenticate users to your apps with other accounts that they have. In this guide, you set up Gloo Gateway to authenticate with users’ Microsoft accounts.

About

As part of your Microsoft setup, you can use Microsoft Entra ID for cloud-based identity and access management across all your Microsoft resources, such as Microsoft 365 and Azure. You can register users and applications in Entra ID to set up OIDC authentication in Gloo Gateway.

Gloo even supports distributed claims for the identity tokens that are returned. In Azure Active Directory, identity tokens can only support a user’s membership in up to 200 groups. Sometimes, user memberships exceed this limit. In such cases, the authentication fails unless you set up distributed claims. You can give Gloo Gateway the details of your app in Entra ID. Then, behind the scenes, the Gloo external auth service talks to the Microsoft Graph API to retrieve the complete identity token. You can even set up caching, so that the Graph API does not accidentally become throttled if you have many client requests.

You can set up distributed claims for both types of OAuth through an authorization code or an access token. With access token authentication, the distributed claim can be stored in a JWT. The JWT itself can also be in a header other than the expected Authorization: Bearer header, if you combine the authentication policy with a transformation policy.

Before you begin

  1. Follow the Get started guide to install Gloo Gateway, set up a gateway resource, and deploy the httpbin sample app.

  2. Get the external address of the gateway and save it in an environment variable.

Step 1: Set up Microsoft Entra ID

To use Microsoft Entra ID as an identity provider (IdP), you must set up Entra ID and register your app.

  1. If you have not already, create your user directory. For instructions, see the Microsoft Entra ID docs.

  2. Create and register an app with Microsoft Entra ID. This app is used by the Gloo external auth service for authentication purposes to call the Microsoft Graph API. For instructions, see the Microsoft Entra ID docs. At a minimum, make sure that you set up and note the values of the following fields:

    • Overview > Application (client) ID: The client ID that Microsoft Entra generates. Later, you create a Kubernetes secret for the Gloo external auth service with the client ID.
        export EXTAUTH_CLIENT_ID=<client-id>
        
    • Overview > Directory (tenant) ID: The tenant ID for when you configure the external auth policy later.
        export EXTAUTH_TENANT_ID=<tenant-id>
        
    • Manage > Certificates & secrets: The client secret that Microsoft Entra generates. Later, you create a Kubernetes secret for the Gloo external auth service with the client secret.
        export EXTAUTH_SECRET=<secret>
        
  3. Create and register another app with Microsoft Entra ID. This app represents the backing service that your users want to access, such as an httpbin app. When users access the service, Gloo Gateway handles the OIDC authorization flow and redirects them to Microsoft to authenticate. The identity token is returned upon successful authentication, per the configuration in this app. For instructions, see the Microsoft Entra ID docs. At a minimum, make sure that you set up and note the values of the following fields:

    • Overview > Application (client) ID: The client ID that Microsoft Entra generates. Later, you create a Kubernetes secret for the Gloo external auth service with the client ID.
        export HTTPBIN_APP_CLIENT_ID=<client-id>
        
    • Overview > Endpoints: The issuer URL for the app, which is similar to the OpenID Connect metadata document URL without the /.well-known/openid-configuration subpath.
        export HTTPBIN_APP_ISSUER_URL=https://login.microsoftonline.com/<tenant-id>/v2.0
        
    • Manage > Certificates & secrets: The client secret that Microsoft Entra generates. Later, you create a Kubernetes secret for the Gloo external auth service with the client secret.
        export HTTPBIN_APP_SECRET=<secret>
        
    • Manage > Authentication: A redirect URI to use as part of the OAuth flow that you set up later. To create a redirect URI for your web app, click Add a platform > Web. Typically, the format of the redirect URI looks similar to https://<app-url>/callback. If you do not have a custom domain for your external auth app, you might use the ingress gateway’s address for the <app-url>.
    • Manage > App roles: A default role for the app.
    • Manage > Token configuration: Add the groups claim and any other claim that you want returned in the identity token.
    • Manage > Expose an API: Add an Application ID URI. Then, use this Application ID URI to add a scope.
        export HTTPBIN_APP_SCOPE=api://<app-url>/<scope-name>
        

Step 2: Prepare routing for your app

Set up the routing for the app that your users want to access. The following example uses the httpbin app. You create an HTTPS listener on a virtual gateway for the httpbin app, which is the same app that you configured an app URL and redirect URI for in Microsoft Entra.

  1. Create an HTTPS listener on your gateway to expose that app that you want to configure external auth for. This app is the same app that you configured an app URL and redirect URI for in Microsoft Entra.

  2. Create an HTTPRoute for the app that sets up routing rules for the app URL and redirect URI that you configured in Microsoft Entra.

    • The app URL is the ingress gateway address with the /ip matcher that is set up in the following route. If you used a HTTPS domain that you own, update the ${INGRESS_GW_ADDRESS} accordingly, such as https://mydomain.com/ip.

        export APP_URL=${INGRESS_GW_ADDRESS}/ip
        
    • The /callback matcher is set up to match the redirect URI that you previously configured in your Microsoft Entra app.

        kubectl apply -f- <<EOF
      apiVersion: gateway.networking.k8s.io/v1
      kind: HTTPRoute
      metadata:
        name: httpbin-oauth-microsoft
        namespace: httpbin
      spec:
        hostnames:
        - "www.httpbin.org"
        parentRefs:
        - name: https
          namespace: gloo-system
        rules:
          - matches:
            - path:
                type: Exact
                value: /ip
            backendRefs:
              - name: httpbin
                port: 8000
          - matches:
            - path:
                type: Exact
                value: /callback
      EOF
        
  3. Verify that the /ip route returns a 200 response. If you used a HTTPS domain that you own, update the following command accordingly, such as curl -vik https://mydomain.com/ip.

      curl -vik --resolve "www.httpbin.org:443:${INGRESS_GW_ADDRESS}" https://www.httpbin.org:443/ip
      

    Example output:

      ...
    > GET /ip HTTP/2
    > Host: www.httpbin.org
    > User-Agent: curl/8.7.1
    > Accept: */*
    > 
    * Request completely sent off
    < HTTP/2 200 
    HTTP/2 200 
      

Step 3: Create the secrets for the external auth service

Configure the Gloo external auth service to handle the OAuth flow for you. To do so, you create secrets for the external auth service based on the information that you configured in Microsoft Entra.

  1. Store the client secret for the external auth service. This way, the external auth service can talk to the MS Graph API to retrieve distributed claims for users that are members of more than 200 groups. Create the Kubernetes secret in the same cluster that create the auth policy in.

      kubectl apply -f - <<EOF
    apiVersion: v1
    kind: Secret
    metadata:
      name: microsoft-extauth
      namespace: gloo-system
    type: extauth.solo.io/oauth
    stringData:
      client-secret: ${EXTAUTH_SECRET}
    EOF
      
  2. Store the client secret of the second Microsoft app that represents the backing service such as httpbin. This way, the external auth service can handle the OIDC flow for requests to the httpbin app in Microsoft Entra. Create the Kubernetes secret in the same cluster that you want to create the auth policy in.

      kubectl apply -f - <<EOF
    apiVersion: v1
    kind: Secret
    metadata:
      name: microsoft-httpbin
      namespace: gloo-system
    type: extauth.solo.io/oauth
    stringData:
      client-secret: ${HTTPBIN_APP_SECRET}
    EOF
      

Step 4: Configure the AuthConfig

Create a Rego policy to evaluate requests for user membership in a particular group. Then, create an external auth policy that has two modules. One module sets up Microsoft as an OIDC provider, including distributed claims. The other module sets up OPA to enforce a Rego policy on the identity token that is returned from the OIDC provider.

You can set up distributed claims for both types of OAuth through an authorization code or an access token. With access token authentication, the distributed claim can be stored in a JWT. The JWT itself can also be in a header other than the expected Authorization: Bearer header, if you combine the authentication policy with a transformation policy.

  1. Create a config map with the Rego policy that you want to enforce. For more information, see the OPA docs. The following Rego policy:

    • Sets the input state key to azure_claims. The azure_claims setting gets the groups claim values from the Microsoft OIDC claims in the token, along with any distributed claims. This way, the user can be a member of less than or more than 200 groups.
    • Iterates through all of the groups claim values.
    • Allows requests if the user is a member of the group with ID 12345-67-89-10111213. You can update this group ID value accordingly. To find your group IDs in Microsoft Entra, go to Identity > Groups > All groups, search for your group, and copy the Object Id value.
      kubectl apply -f - <<EOF
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: httpbin-rego
      namespace: httpbin
    data:
      policy.rego: |
       package test
    
       default allow = false
       allow {
          # Allow group with ID 12345-67-89-10111213
          count({i | input.state["azure_claims"]["groups"][i] == "12345-67-89-10111213"}) > 0
        }
    EOF
      
  2. Choose from the following OAuth options.

Authorization code

Create an AuthConfig that uses Microsoft for OIDC and enforces the Rego policy. The policy also enables distributed claims and caching for OIDC with Microsoft. You only need distributed claims if the users that authenticate are members in more than 200 groups. If not, you can remove the azure section from the external auth policy.

  kubectl apply -f - <<EOF
apiVersion: enterprise.gloo.solo.io/v1
kind: AuthConfig
metadata:
  name: httpbin-test
  namespace: httpbin
spec:
  configs:
  - oauth2:
      oidcAuthorizationCode:
        appUrl: $APP_URL
        azure:
          claimsCachingOptions:
            host: redis.gloo-system.svc.cluster.local:6379
          clientId: $EXTAUTH_CLIENT_ID
          clientSecret:
            name: microsoft-extauth
            namespace: gloo-system
          tenantId: $EXTAUTH_TENANT_ID
        callbackPath: /callback
        clientId: $HTTPBIN_APP_CLIENT_ID
        clientSecretRef:
          name: microsoft-httpbin
          namespace: gloo-system
        issuerUrl: $HTTPBIN_APP_ISSUER_URL
        scopes:
        - $HTTPBIN_APP_SCOPE
        - profile
        - email
        - openid
        session:
          redis:
            cookieName: oidcsession
            options:
              host: redis.gloo-system.svc.cluster.local:6379
  - name: opa
    opaAuth:
      modules:
      - name: httpbin-rego
        namespace: httpbin
      query: data.test.allow == true
EOF
  

Review the following table to understand this configuration. For more information, see the API reference for OAuth2 in the Gloo Edge docs.

SettingDescription
oauth2Configure the OAuth 2.0 protocol details to use to authenticate requests. The example uses Microsoft as the external identity provider. Gloo Gateway handles the OIDC flow by validating the contents of an ID token based on the configuration details that you configure in oidcAuthorizationCode.
appUrlThe public URL of the app that you want to set up external auth for. This setting is used in combination with the callbackPath attribute. If your app does not have a custom domain, you can use the address of the ingress gateway and the path that your app is exposed on, such as https://52.xxx.xx.xxx/ip.
azureThe configuration details for the external auth service to authenticate with the Microsoft Graph API for distributed claims and caching. You use distributed claims for cases where users are members of more than 200 groups. If you do not need distributed claims, you can omit this section.
  • claimsCachingOptions: Enable caching to avoid performance issues of accessing the Microsoft Graph API too many times. In this example, the cache is set to the Redis instance that you get when you enable the Gloo external auth service. You can also use your own Redis instance. The cache key name is in the format tenant-id/client-id/user-id/claim-name. The cache key expires roughly at the same time as the token from the IdP, or you can clear the cache manually in your Redis instance.
  • clientId: The client ID of the first app that you configured in Azure to access the Graph API.
  • clientSecret: The reference to the Kubernetes secret that you previously created for the first Azure app. The secret must exist on the same cluster as the ExtAuthServer resource that this policy refers to. In this example, you created the secret in an earlier step.
  • tenantId: The tenant ID of the first Azure app that you configured to access the Graph API.
callbackPathThe callback path, relative to the appUrl setting. After a user authenticates, the identity provider redirects the user to this callback URL. Gloo Gateway intercepts requests with this path, exchanges the authorization code received from the IdP for an ID token, places the ID token in a cookie on the request, and forwards the request to its original destination. Note: The callback path must have a matching route in the route table that is associated with the external auth policy. 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 the request goes through the routing filters including external auth.
clientIdThe client ID of the Microsoft Entra ID app for your user-facing service such as httpbin (not the client ID of the app for the external auth service).
clientSecretRefThe reference to the Kubernetes secret that you previously created for the Microsoft Entra ID app of your user-facing service such as httpbin (not the app for the external auth service). The secret must exist on the same cluster as the ExtAuthServer resource that this policy refers to.
issuerUrlThe URL of the OpenID Connect identity provider. Gloo Gateway automatically discovers OIDC configuration by querying the .well-known/openid-configuration endpoint on the issuer_url. In this example, Gloo Gateway expects to find OIDC discovery information at the address in Microsoft Entra that you previously retrieved, https://login.microsoftonline.com/<tenant-id>/v2.0.
scopesOther OIDC scopes to request. By default, the openid scope is included, which returns the OIDC protocol information that is needed to verify the user’s identity. For Azure, you must also include the api scope, which is the Application ID URI that you previously configured in Microsoft Entra. This example also requests the email and profile scopes. For more information, see the OpenID docs.
sessionDetails on how to store the user session details. In this example, the cookie is stored in Redis.
opaAuthThe configuration details for the OPA policy that you want to enforce.
  • modules: Refer to the name and namespace of the config map that has the OPA policy. Then, Gloo Gateway can use the OPA policy to resolve the query. This example uses the config map that you previously created.
  • The query that determines the authentication decision. The result of this query must be either a boolean or an array with a boolean as the first element. A value of true means that the request is authorized. Any other value or error means that the request is denied. In this example, data.test.allow is set to true. data is the section in the config map. test is the package name, and allow the name of the Rego rule that you defined in the OPA policy earlier. Access is allowed only if the response meets the allow conditions in the policy.

Access token

Create an external auth policy that uses Microsoft for OIDC and enforces the Rego policy. Review the following key features of the policy.

  • The policy retrieves the access token from a JWT from your MS Entra issuer.
  • The policy also enables distributed claims and caching for OIDC with Microsoft. You only need distributed claims if the users that authenticate are members in more than 200 groups. If not, you can remove the azure section from the external auth policy.
  kubectl apply -f - <<EOF
apiVersion: enterprise.gloo.solo.io/v1
kind: AuthConfig
metadata:
  name: httpbin-test
  namespace: httpbin
spec:
  configs:
  - oauth2:
      accessTokenValidation:
        jwt:
          remoteJwks: 
            url: <jwks_url>
          issuer: <issuer_url>
        claimsToHeaders:
        - claim: groups
          header: x-groups
        azure:
          claimsCachingOptions:
            host: redis.gloo-system.svc.cluster.local:6379
          clientId: $EXTAUTH_CLIENT_ID
          clientSecret:
            name: microsoft-extauth
            namespace: gloo-system
          tenantId: $EXTAUTH_TENANT_ID
  - name: opa
    opaAuth:
      modules:
      - name: httpbin-rego
        namespace: httpbin
      query: data.test.allow == true
EOF
  

Review the following table to understand this configuration. For more information, see the API reference for OAuth2 in the Gloo Edge docs.

SettingDescription
oauth2Configure the OAuth 2.0 protocol details to use to authenticate requests. The example uses Microsoft as the external identity provider. Gloo Gateway handles the OIDC flow by validating the contents of an access token based on the configuration details that you configure in accessTokenValidation.
jwtConfigure the details for how to verify the JWT, such as the issuer and JSON Key Web set (JWKS) locations. The example uses a remote JWKS, but you can inline a local JWKS instead.
remoteJwksThe JWKS server to get the public keys from. You get this URL from your MS Entra instance. Note that this URL must be reachable from your cluster.
issuerThe principal that issued the JWT, usually a URL from your MS Entra instance. If specified, the iss field in JWT token of the incoming request must match this field, or else the request is denied. If omitted, the iss field in the JWT token is not checked.
claimsToHeadersOptionally, you can copy claims from the JWT to individual headers before forwarding the request. For example, you might want an x-groups header to contain the content from the groups claim in the JWT.
azureThe configuration details for the external auth service to authenticate with the Microsoft Graph API for distributed claims and caching. You use distributed claims for cases where users are members of more than 200 groups. If you do not need distributed claims, you can omit this section.
  • claimsCachingOptions: Enable caching to avoid performance issues of accessing the Microsoft Graph API too many times. In this example, the cache is set to the Redis instance that you get when you enable the Gloo external auth service. You can also use your own Redis instance. The cache key name is in the format tenant-id/client-id/user-id/claim-name. The cache key expires roughly at the same time as the token from the IdP, or you can clear the cache manually in your Redis instance.
  • clientId: The client ID of the first app that you configured in Azure to access the Graph API.
  • clientSecret: The reference to the Kubernetes secret that you previously created for the first Azure app. The secret must exist on the same cluster as the ExtAuthServer resource that this policy refers to. In this example, you created the secret in an earlier step.
  • tenantId: The tenant ID of the first Azure app that you configured to access the Graph API.
opaAuthThe configuration details for the OPA policy that you want to enforce.
  • modules: Refer to the name and namespace of the config map that has the OPA policy. Then, Gloo Gateway can use the OPA policy to resolve the query. This example uses the config map that you previously created.
  • The query that determines the authentication decision. The result of this query must be either a boolean or an array with a boolean as the first element. A value of true means that the request is authorized. Any other value or error means that the request is denied. In this example, data.test.allow is set to true. data is the section in the config map. test is the package name, and allow the name of the Rego rule that you defined in the OPA policy earlier. Access is allowed only if the response meets the allow conditions in the policy.

Step 5: Attach the AuthConfig to your route

To attach the AuthConfig to your route, you can use a RouteOption. For more options, see Policy attachment.

  1. Create a RouteOption that refers to the AuthConfig that you created.

      kubectl apply -f- <<EOF
    apiVersion: gateway.solo.io/v1
    kind: RouteOption
    metadata:
      name: httpbin-oauth
      namespace: httpbin
    spec:
      options:
        extauth:
          configRef:
            name: httpbin-test
            namespace: httpbin
    EOF
      
  2. Update your HTTPRoute resource to attach the RouteOption to the /ip route by using an ExtensionRef filter.

      kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: httpbin-oauth-microsoft
      namespace: httpbin
    spec:
      hostnames:
      - "www.httpbin.org"
      parentRefs:
      - name: https
        namespace: gloo-system
      rules:
        - matches:
          - path:
              type: Exact
              value: /ip
          backendRefs:
            - name: httpbin
              port: 8000
          filters:
            - type: ExtensionRef
              extensionRef:
                group: gateway.solo.io
                kind: RouteOption
                name: httpbin-oauth
        - matches:
          - path:
              type: Exact
              value: /callback
    EOF
      

Step 6: Verify the OAuth policy

The following steps show how you might authenticate with your Microsoft user account when using OAuth2 authorization code authentication.

  1. Send a curl request to your application. Verify that you get back a 302 Found code, because the request is temporarily moved to the Microsoft OIDC authentication flow.

      curl -vik $APP_URL
      

    Example output:

      HTTP/2 302 
    < location: https://login.microsoftonline.com/...
      
  2. In your web browser, open the path to your application, such as the ingress gateway IP address and the path that you configured in the route table. You are redirected to the authentication page from the Microsoft identity provider.

      open $APP_URL
      
  3. Enter your Microsoft user credentials.

    Figure: Microsoft login page
    Figure: Microsoft login page
    Figure: Microsoft login page
    Figure: Microsoft login page

    Example output for authorized users: Gloo Gateway redirects you to the app URL, such as 52.xxx.xx.x/ip. In this example, the httpbin app returns the origin IP address, 10.xx.xx.x.

    Figure: Example response of origin IP address
    Figure: Example response of origin IP address
    Figure: Example response of origin IP address
    Figure: Example response of origin IP address

    Example output for unauthorized users: If you log in as a user that is not authorized to the group, you see a Rejected message similar to the following figure.

    Figure: Example response of rejected unauthorized user
    Figure: Example response of rejected unauthorized user
    Figure: Example response of rejected unauthorized user
    Figure: Example response of rejected unauthorized user

Cleanup

You can optionally remove the resources that you set up as part of this guide.
  kubectl delete Secret microsoft-extauth -n gloo-system
kubectl delete Secret microsoft-httpbin -n gloo-system 
kubectl delete ConfigMap httpbin-rego -n httpbin 
kubectl delete AuthConfig httpbin-test -n httpbin 
kubectl delete RouteOption httpbin-oauth -n httpbin
kubectl delete HTTPRoute httpbin-oauth-microsoft -n httpbin