How do I pass an M2M token from Entra to the registration gate?¶
Question¶
I have an external registration gate (admission control webhook) that is protected by Microsoft Entra ID. I want the registry to automatically acquire a machine-to-machine (M2M) access token from Entra and pass it as a Bearer token to the gate endpoint. How do I configure this?
Answer¶
The registry supports OAuth2 Client Credentials authentication for the registration gate. When configured, the registry acquires a fresh access token from your Entra tenant before each gate call and sends it as Authorization: Bearer <token> to the gate endpoint.
This uses the standard OAuth2 Client Credentials flow (RFC 6749 Section 4.4), which is the M2M authentication pattern where a service (the registry) authenticates with a client ID and secret to obtain an access token, with no user interaction required.
Step 1: Create an App Registration in Entra¶
If you do not already have one, create an App Registration in the Azure Portal:
- Go to Azure Portal > App registrations > New registration
- Name it (e.g.,
mcp-registry-gate-client) - Under Certificates & secrets, create a new client secret and copy the value
- Note the Application (client) ID and your Tenant ID from the Overview page
- If your gate endpoint requires a specific audience, expose an API under Expose an API and note the Application ID URI (e.g.,
api://your-app-id)
Step 2: Configure the Registry¶
Set these environment variables on the registry service:
# Enable the registration gate
REGISTRATION_GATE_ENABLED=true
REGISTRATION_GATE_URL=https://your-gate-endpoint.example.com/check
# Use OAuth2 Client Credentials authentication
REGISTRATION_GATE_AUTH_TYPE=oauth2_client_credentials
# Entra token endpoint (replace {tenant-id} with your Azure AD tenant ID)
REGISTRATION_GATE_OAUTH2_TOKEN_URL=https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token
# App registration credentials
REGISTRATION_GATE_OAUTH2_CLIENT_ID=your-client-id
REGISTRATION_GATE_OAUTH2_CLIENT_SECRET=your-client-secret
# Entra scope (use the Application ID URI + /.default)
REGISTRATION_GATE_OAUTH2_SCOPE=api://your-app-id/.default
Step 3: Verify¶
When the registry starts, it will:
- Validate that the token URL, client ID, and client secret are all set
- Attempt a test token acquisition to verify the credentials work
- Log warnings if there are issues (check
docker compose logs registry)
When an agent, server, or skill is registered, the registry will:
- POST to the Entra token endpoint with
grant_type=client_credentials - Receive an access token (JWT signed by Entra)
- Send
Authorization: Bearer <entra-jwt>to your gate endpoint - If the gate returns 200, the registration proceeds; if 403, it is denied
If token acquisition fails (invalid credentials, network error, timeout), the registration is blocked immediately (fail-closed design). The gate endpoint is never called with missing or invalid credentials.
What the gate endpoint receives¶
The gate endpoint receives the Entra JWT in the Authorization header. You can decode the JWT to verify claims such as:
iss:https://sts.windows.net/{tenant-id}/(your Entra tenant)appid: your client IDaud: the scope/audience you configuredtid: your tenant ID
Works with other IdPs too¶
While this example uses Entra, the same configuration pattern works with any OAuth2 provider that supports the client credentials grant:
- Okta:
https://{domain}/oauth2/default/v1/token - Auth0:
https://{tenant}.auth0.com/oauth/token - Keycloak:
https://{host}/realms/{realm}/protocol/openid-connect/token - Cognito:
https://cognito-idp.{region}.amazonaws.com/{user-pool-id}
Helm chart configuration¶
If you deploy with Helm, set these values in your Helm values file:
charts/registry/values.yaml(lines 60-68): setapp.registrationGateAuthType,app.registrationGateOauth2TokenUrl,app.registrationGateOauth2ClientId,app.registrationGateOauth2ClientSecret, andapp.registrationGateOauth2Scopecharts/mcp-gateway-registry-stack/values.yaml(lines 229-237): same keys underregistry.app.*
These values are injected into the registry container via charts/registry/templates/secret.yaml (lines 173-190).
Related documentation¶
- Registration Webhooks and Gate for full configuration reference, including the OAuth2 parameter table and examples for multiple IdPs
- Issue #917 for the design specification