Skip to main content
logoTetrate Service BridgeVersion: 1.14.x

Move Application SSO to the Gateway

Many applications implement single sign-on (SSO) in their own code: they redirect users to the identity provider, validate the tokens that come back, and check the user's roles before serving a request. This guide shows how to move that work to the application's Ingress Gateway, so that the application receives only requests from users who have already logged in.

The examples use Microsoft Entra ID as the identity provider, and a payments application published at https://payments.example.com. The same steps apply to any OpenID Connect (OIDC) provider; only the provider details change. For the general OIDC configuration, see User Authentication with OIDC.

What changes for the application​

TaskBeforeAfter
Redirect users to log inApplication codeIngress Gateway
Validate tokensApplication code or libraryIngress Gateway
Check roles, per pathApplication codeIngress Gateway, with authorization rules
Know who the user isApplication sessionThe X-ID-TOKEN header that the gateway adds to each request
Change identity providerCode change in each applicationChange to the Gateway resource

The application keeps any checks that depend on its own data, such as "this user can only see their own account".

Migration path​

Move one application at a time. Each phase can be rolled back on its own.

  1. Onboard the application: Publish the application through a TSB Ingress Gateway, with TLS, and leave its SSO code unchanged.
  2. Move login to the gateway: Configure OIDC on the Gateway resource (Steps 1 to 3), and remove the login and token validation code from the application (Step 4). Deploy both changes together, so that users are not asked to log in twice.
  3. Move role checks to the gateway (optional): Add authorization rules based on the user's roles (Step 5), and remove the equivalent checks from the application.

Before you begin​

  • The application is published through a TSB Ingress Gateway over HTTPS. The OIDC flow relies on redirects and cookies, so it must use HTTPS.
  • You can create a Kubernetes secret in the namespace of the Ingress Gateway.
  • You can create an app registration in your Entra ID tenant, or ask your identity team to create one.

Step 1: Register the application in Entra ID​

In the Entra admin center, create an App registration for the application, and note the following values:

ValueWhere to find itExample
Tenant IDOverview page<tenant-id>
Client IDOverview page, Application (client) ID<client-id>
Client secretCertificates & secrets → New client secret<client-secret>
Redirect URIAuthentication → Add a platform → Webhttps://payments.example.com/callback

The redirect URI must match the redirectUri in the Gateway resource exactly. Choose a path that the application does not use, such as /callback.

If you plan to check roles at the gateway, also define the roles under App roles, for example payments-admin, and assign them to users or groups under Enterprise applications → Users and groups. Entra ID adds the user's app roles to the roles claim of the ID token.

Step 2: Create the client secret​

Create a secret with the client secret, in the namespace of the Ingress Gateway. The key must be istio_generic_secret:

kubectl create secret generic payments-oidc-secret \
--from-literal=istio_generic_secret=<client-secret> \
-n payments

Step 3: Configure OIDC on the Gateway​

Add the authentication.oidc section to the HTTP server that publishes the application. The provider URLs follow the same pattern for every Entra ID tenant:

apiVersion: gateway.tsb.tetrate.io/v2
kind: Gateway
metadata:
organization: tetrate
tenant: tetrate
workspace: payments-ws
group: payments-gw
name: payments-gateway
spec:
workloadSelector:
namespace: payments
labels:
app: payments-ingress-gw
http:
- name: payments
port: 443
hostname: payments.example.com
tls:
mode: SIMPLE
secretName: payments-cert
authentication:
oidc:
clientId: <client-id>
clientTokenSecret: payments-oidc-secret
redirectUri: https://payments.example.com/callback
authScopes:
- profile
- email
provider:
issuer: https://login.microsoftonline.com/<tenant-id>/v2.0
authorizationEndpoint: https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/authorize
tokenEndpoint: https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token
jwksUri: https://login.microsoftonline.com/<tenant-id>/discovery/v2.0/keys
routing:
rules:
- route:
serviceDestination:
host: payments/payments.payments.svc.cluster.local
port: 8080
  • The gateway always requests the openid scope. profile and email add the user's name and email address to the ID token.
  • Users can log out at /signout. To use another path, set signoutPath.

For all the OIDC fields, see OIDCConfig.

Step 4: Update the application​

When a user who has not logged in sends a request, the gateway redirects them to Entra ID. After login, the gateway validates the ID token, keeps the tokens in cookies, and forwards each request to the application with the following headers:

HeaderContent
X-ID-TOKENThe claims of the validated ID token, as base64url-encoded JSON. Use it to read the user's identity, for example oid, name, preferred_username and roles.
AuthorizationBearer <access-token>, the access token issued by Entra ID

Remove the login redirect, the callback handling and the token validation from the application, and read the user's identity from the X-ID-TOKEN header instead. The gateway has already validated the token, so the application only needs to decode the header.

The access token is not for your application

With the scopes in this example, Entra ID issues the access token for Microsoft Graph, and your application cannot validate it. If the application needs an access token for its own API, expose an API scope in the app registration, such as api://<client-id>/payments.read, and add it to authScopes.

Only accept identity headers from the gateway

The application now trusts the identity in the headers that it receives. Make sure that the gateway is the only way to reach the application from outside its Workspace. If your platform uses a deny-all security posture, as recommended in Extend Security Rules, this is already the case; review any security rules that open the application to other Workspaces.

Step 5: Check roles at the gateway​

If the application checks roles before serving some paths, you can move these checks to the gateway. Add an authorization section to the same HTTP server:

      authorization:
local:
rules:
- name: admins
from:
- jwt:
other:
roles: payments-admin
to:
- paths: ['/admin*']
- name: signed-in-users
to:
- paths: ['/', '/api*', '/static*']
  • The rules match the claims of the ID token. The roles claim is a list; the rule matches if the list contains payments-admin.
  • The rules form an allow list: a request that no rule allows is refused with 403 RBAC: access denied. List every path that signed-in users may reach.
  • Every request already comes from a signed-in user, because the gateway redirects users who have not logged in before it applies these rules.

From TSB 1.14.4000, rules can also refuse requests with action: DENY, and match claims with when conditions. See Gateway Authorization Rule Actions.

Use app roles rather than groups

Entra ID can also add the user's groups to the token, as the groups claim, but it identifies groups by their object ID, and it omits the claim for users who belong to many groups. App roles have readable names, and you assign them per application.

Verify the configuration​

Send a request without logging in. The gateway should redirect you to Entra ID:

curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' https://payments.example.com/
# 302 https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/authorize?client_id=...

Then open https://payments.example.com/ in a browser, log in, and check that:

  • The application responds, and receives the X-ID-TOKEN header.
  • A user without the payments-admin role receives 403 RBAC: access denied on /admin.
  • /signout logs the user out.

Troubleshooting​

SymptomLikely cause
Entra ID shows error AADSTS50011The redirect URI in the app registration does not match redirectUri in the Gateway resource.
The login succeeds, but the gateway returns an error on /callbackThe client secret is wrong, has expired, or is not in the gateway's namespace.
403 RBAC: access denied for a user who should have accessThe path is not listed in any rule, or the user's ID token does not contain the expected role. Decode the X-ID-TOKEN header to see the claims.
No redirect to Entra IDThe Gateway resource has not been applied to the gateway. See Gateway troubleshooting.

For details of each request, follow the gateway's access logs:

kubectl logs -n payments -l app=payments-ingress-gw -f