Microsoft
Let users authenticate with your app by using their Microsoft account.
You can use Gloo Mesh Gateway external auth to authenticate users to your apps with other accounts that they have. In this guide, you set up Gloo Mesh 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 Mesh 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 Mesh 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
- Set up Gloo Mesh Gateway in a single cluster.
- Install Bookinfo and other sample apps.
Configure an HTTP listener on your gateway and set up basic routing for the sample apps.
Get the external address of your ingress gateway. The steps vary depending on the type of load balancer that backs the ingress gateway.
export INGRESS_GW_ADDRESS=$(kubectl get svc -n istio-ingress istio-ingressgateway -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}") echo $INGRESS_GW_ADDRESSNote: Depending on your environment, you might see
<pending>instead of an external IP address. For example, if you are testing locally in kind or minikube, or if you have insufficient permissions in your cloud platform, you can instead port-forward the service port of the ingress gateway:kubectl -n istio-ingress port-forward deploy/istio-ingressgateway-main 8081
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.
If you have not already, create your user directory. For instructions, see the Microsoft Entra ID docs.
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>
- 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.
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 Mesh 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 documentURL without the/.well-known/openid-configurationsubpath.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
groupsclaim 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>
- 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.
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.
Create an HTTPS listener on a virtual 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.
Follow the HTTPS listener guide to create the TLS configuration for the HTTPS listener.
For the virtual gateway, you can use a configuration similar to the following. Make sure to update the
secretNameif you used a different value.kubectl apply -f - <<EOF apiVersion: networking.gloo.solo.io/v2 kind: VirtualGateway metadata: name: httpbin-ingress namespace: httpbin spec: listeners: - http: {} port: number: 443 tls: mode: SIMPLE secretName: gw-ssl-1-secret - http: {} httpsRedirect: true port: number: 80 workloads: - selector: labels: istio: ingressgateway EOF
Create a route table 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
/ipmatcher that is set up in the following route table.export APP_URL=${INGRESS_GW_ADDRESS}/ipThe
/callbackmatcher is set up to match the redirect URI that you previously configured in your Microsoft Entra app.kubectl apply -f - <<EOF apiVersion: networking.gloo.solo.io/v2 kind: RouteTable metadata: name: httpbin-ingress namespace: httpbin labels: expose: "true" spec: hosts: - '*' http: - forwardTo: destinations: - port: number: 8000 ref: name: httpbin namespace: httpbin matchers: - uri: exact: /ip name: httpbin - forwardTo: destinations: - port: number: 8000 ref: name: httpbin namespace: httpbin matchers: - uri: exact: /callback name: httpbin-callback virtualGateways: - name: httpbin-ingress namespace: httpbin cluster: $CLUSTER_NAME workloadSelectors: [] EOF
Step 3: Create the secrets for the external auth service
To use Microsoft Entra ID as an identity provider (IdP), you must set up Entra ID and register your app.
If you have not already, create your user directory. For instructions, see the Microsoft Entra ID docs.
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>
- 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.
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 Mesh 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 documentURL without the/.well-known/openid-configurationsubpath.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
groupsclaim 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>
- 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.
Step 4: Configure authentication policies
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.
Create an external auth server to use for your policies.
kubectl apply -f - <<EOF apiVersion: admin.gloo.solo.io/v2 kind: ExtAuthServer metadata: name: ext-auth-server namespace: httpbin spec: destinationServer: port: number: 8083 ref: cluster: $CLUSTER_NAME name: ext-auth-service namespace: gloo-mesh EOFCreate 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. Theazure_claimssetting gets thegroupsclaim 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
groupsclaim 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- Sets the input state key to
Choose from the following OAuth options.
Want to use multiple OAuth configs in combination? Check out the boolean expression setting in your auth config.Authorization code
Create an external auth policy 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
azuresection from the external auth policy.kubectl apply -f - <<EOF apiVersion: security.policy.gloo.solo.io/v2 kind: ExtAuthPolicy metadata: name: httpbin-test namespace: httpbin spec: applyToDestinations: - selector: labels: app: httpbin config: server: cluster: $CLUSTER_NAME name: ext-auth-server namespace: httpbin glooAuth: configs: - oauth2: oidcAuthorizationCode: appUrl: $APP_URL azure: claimsCachingOptions: host: redis.gloo-mesh.svc.cluster.local:6379 clientId: $EXTAUTH_CLIENT_ID clientSecret: name: microsoft-extauth namespace: gloo-mesh tenantId: $EXTAUTH_TENANT_ID callbackPath: /callback clientId: $HTTPBIN_APP_CLIENT_ID clientSecretRef: name: microsoft-httpbin namespace: gloo-mesh issuerUrl: $HTTPBIN_APP_ISSUER_URL scopes: - $HTTPBIN_APP_SCOPE - profile - email - openid session: redis: cookieName: oidcsession options: host: redis.gloo-mesh.svc.cluster.local:6379 - name: opa opaAuth: modules: - name: httpbin-rego namespace: httpbin query: data.test.allow == true EOFReview the following table to understand this configuration. For more information, see the API reference.
Setting Description applyToDestinationsUse labels to apply the policy to destinations. Destinations might be a Kubernetes service, VirtualDestination, or ExternalService (if supported by the policy). If you do not specify any destinations or routes, the policy applies to all destinations in the workspace by default. If you do not specify any destinations but you do specify a route, the policy applies to the route but to no destinations. Alternatively, you can apply the policy to a route instead of a destination. serverThe external auth server to use for the policy. oauth2Configure the OAuth 2.0 protocol details to use to authenticate requests. The example uses Microsoft as the external identity provider. Gloo Mesh 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 callbackPathattribute. 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 ashttps://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 formattenant-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 appUrlsetting. After a user authenticates, the identity provider redirects the user to this callback URL. Gloo Mesh 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 Mesh Gateway automatically discovers OIDC configuration by querying the .well-known/openid-configurationendpoint on theissuer_url. In this example, Gloo Mesh 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 openidscope is included, which returns the OIDC protocol information that is needed to verify the user’s identity. For Azure, you must also include theapiscope, which is the Application ID URI that you previously configured in Microsoft Entra. This example also requests theemailandprofilescopes. 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 Mesh Gateway can use the OPA policy to resolve thequery. 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
truemeans that the request is authorized. Any other value or error means that the request is denied. In this example,data.test.allowis set totrue.datais the section in the config map.testis the package name, andallowthe name of the Rego rule that you defined in the OPA policy earlier. Access is allowed only if the response meets theallowconditions 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
azuresection from the external auth policy.
Is your JWT in a custom header? By default, the JWT token is expected in theAuthorization: Bearer <token>header format. If you use a different header, apply a transformation policy.kubectl apply -f - <<EOF apiVersion: security.policy.gloo.solo.io/v2 kind: ExtAuthPolicy metadata: name: httpbin-test namespace: httpbin spec: applyToDestinations: - selector: labels: app: httpbin config: server: cluster: $CLUSTER_NAME name: ext-auth-server namespace: httpbin glooAuth: configs: - oauth2: accessTokenValidation: jwt: remoteJwks: url: <jwks_url> issuer: <issuer_url> claimsToHeaders: - claim: groups header: x-groups azure: claimsCachingOptions: host: redis.gloo-mesh.svc.cluster.local:6379 clientId: $EXTAUTH_CLIENT_ID clientSecret: name: microsoft-extauth namespace: gloo-mesh tenantId: $EXTAUTH_TENANT_ID - name: opa opaAuth: modules: - name: httpbin-rego namespace: httpbin query: data.test.allow == true EOFReview the following table to understand this configuration. For more information, see the API reference.
Setting Description applyToDestinationsUse labels to apply the policy to destinations. Destinations might be a Kubernetes service, VirtualDestination, or ExternalService (if supported by the policy). If you do not specify any destinations or routes, the policy applies to all destinations in the workspace by default. If you do not specify any destinations but you do specify a route, the policy applies to the route but to no destinations. Alternatively, you can apply the policy to a route instead of a destination. serverThe external auth server to use for the policy. oauth2Configure the OAuth 2.0 protocol details to use to authenticate requests. The example uses Microsoft as the external identity provider. Gloo Mesh 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 issfield in JWT token of the incoming request must match this field, or else the request is denied. If omitted, theissfield 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-groupsheader to contain the content from thegroupsclaim 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 formattenant-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 Mesh Gateway can use the OPA policy to resolve thequery. 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
truemeans that the request is authorized. Any other value or error means that the request is denied. In this example,data.test.allowis set totrue.datais the section in the config map.testis the package name, andallowthe name of the Rego rule that you defined in the OPA policy earlier. Access is allowed only if the response meets theallowconditions in the policy.
Step 5: Verify the OAuth policy
The following steps show how you might authenticate with your Microsoft user account when using OAuth2 authorization code authentication.
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_URLExample output:
HTTP/2 302 < location: https://login.microsoftonline.com/...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_URLEnter your Microsoft user credentials.

Figure: Microsoft login page 
Figure: Microsoft login page Example output for authorized users: Gloo Mesh 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 Example output for unauthorized users: If you log in as a user that is not authorized to the group, you see a
Rejectedmessage similar to the following figure.
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-mesh kubectl delete Secret microsoft-httpbin -n gloo-mesh kubectl delete ExtAuthServer ext-auth-server -n httpbin kubectl delete VirtualGateway httpbin-ingress -n httpbin kubectl delete RouteTable httpbin-ingress -n httpbin kubectl delete ConfigMap httpbin-rego -n httpbin kubectl delete ExtAuthPolicy httpbin-test -n httpbin