How authentication works
Subscription keys are mandatory. Every MCP request must include anOcp-Apim-Subscription-Key header containing a valid API key. These keys identify which application is making requests, enable rate limiting per client, and determine which tools the subscription can access. Keys are provisioned automatically when your MCP access request is approved - separate keys for development, staging, and production environments.
JWT tokens are optional and used only when tools need user context. Operations like getMyAccountBalance or getMyTransactionHistory need to know which user the agent represents to retrieve the right data. When a JWT token is provided in the Authorization: Bearer <token> header, Grand Central validates its signature, checks expiration, extracts user claims, and propagates that identity to backend APIs. Without JWT, tools can only perform operations that don’t require user-specific authorization.
API key authentication
Configure your AI agent to send the subscription key with every MCP request:JWT token authentication (optional)
Use JWT tokens when tools need user context. Operations that retrieve user-specific data (account balances, transaction history, profile details) need to know which user the agent represents. Without JWT, these operations would require passing user IDs as parameters, which creates security risks - agents could request any user’s data by guessing IDs. With JWT tokens, the user identity is cryptographically signed and tamper-proof. Configure JWT authentication in your OpenAPI specification when exposing user-scoped operations:Mixed authentication patterns
Grand Central MCP servers can expose both public and user-scoped operations with different authentication requirements. Public operations like retrieving currency exchange rates or product catalogs only require a subscription key - there’s no user-specific data involved. User-scoped operations like viewing account balances or transaction history require both a subscription key AND a JWT token to identify which user’s data to retrieve. Authentication requirements are configured automatically based on tool metadata when tools are approved. Operations on public data get marked as subscription-key-only. Operations on user data get marked as requiring JWT. Your AI agent automatically handles this - if it has a JWT token, it sends it with every request. Tools that don’t need user context ignore the token; tools that need it extract user identity and use it for authorization.User context flow
User identity flows from your web application through the AI agent to Grand Central and finally to backend APIs: Your web application authenticates users and obtains JWT tokens from your identity provider (Azure AD, Okta, Auth0, etc.). When invoking an AI agent, it passes the JWT token so the agent can act on the user’s behalf. The AI agent stores the token securely (memory only, never logs or disk), validates expiration before use, and includes it in MCP requests. If the token expires during a conversation, the agent requests a refresh from your application. Grand Central validates the JWT signature against your identity provider’s public keys, checks audience and issuer claims match expected values, verifies expiration timestamps, and extracts user identity (like user ID, email, or custom claims). Backend APIs receive user context in request headers or JWTs, enforce user-scoped authorization (ensuring users only access their own data), perform operations with proper permissions, and log actions with user identity for audit trails.APIM policy implementation
Here’s what you need to configure in Azure APIM to make this authentication model work. Grand Central uses conditional JWT validation - meaning the JWT is validated only when present, allowing tools to support both public and authenticated use cases.Conditional JWT validation policy
This policy checks if an Authorization header exists, validates the JWT if present, and extracts user context. If no JWT is provided, the request proceeds as a public operation:<choose> conditional and apply <validate-jwt> directly - APIM will reject any request without a valid token.
JWT validation configuration can use OpenID Connect discovery to fetch signing keys dynamically from your identity provider, or you can configure static signing keys. The example above uses <openid-config> which automatically fetches keys from your identity provider’s discovery endpoint (Azure AD, Okta, Auth0). Alternatively, use <issuer-signing-keys> to specify keys directly - useful when your identity provider doesn’t support OpenID Connect discovery or you prefer static configuration for performance. The audiences and issuers claims ensure tokens are intended for your API.
Alternative: Static signing keys configuration
If you prefer static key configuration or your identity provider doesn’t support OpenID Connect discovery, use <issuer-signing-keys> with Named Values for secure key management:
jwt-signing-key-1 and jwt-signing-key-2 containing your Base64-encoded signing keys, then reference them using {{named-value}} syntax.
Static keys provide faster validation (no HTTP call to fetch keys) but require manual updates when keys rotate. OpenID Connect discovery handles rotation automatically but adds network latency to the first request after cache expiration.
User context extraction pulls the user ID from the JWT’s subject claim and stores it in APIM variables. Backend APIs receive this via custom headers or the original Authorization header, depending on your architecture.
Rate limiting by authentication status applies different quotas: authenticated users get 500 requests/minute tracked by user ID, anonymous requests get 50 requests/minute tracked by IP address. This prevents abuse while allowing public access for legitimate use cases.
Tool-level authentication in OpenAPI
Define authentication requirements per operation in your OpenAPI specification. Grand Central respects these security schemes and enforces them at the APIM layer: Public tools (no authentication required):security: - BearerAuth: [] require JWT validation at the APIM layer - requests without valid tokens get HTTP 401 before reaching your backend. Operations without security requirements work with the conditional policy shown above (JWT validated if present, allowed through if absent). You can configure APIM policies to always require JWT, always allow anonymous access, or use conditional logic - the choice depends on your tool’s security requirements.
Security layer responsibilities
APIM handles JWT signature validation, token expiration checks, audience and issuer claim verification, and rate limiting based on authentication status. This ensures invalid or expired tokens never reach your backends. Backend APIs handle user-scoped authorization (can this user access this specific resource?), business logic permissions (is this user allowed to perform this operation?), and data access controls (filter results to only what this user should see). Don’t duplicate validation - APIM guarantees that JWTs reaching your backend are cryptographically valid and not expired. Backends only need to extract user claims and enforce authorization rules specific to your domain.Security best practices
Keep JWT tokens short-lived - 1 hour expiration is typical. This limits damage if tokens leak. Implement refresh token rotation so agents can obtain new access tokens without re-authenticating users. Rotate subscription keys periodically, ideally every 90 days. Use different keys for development, staging, and production so compromising one environment doesn’t expose others. Monitor usage patterns - unexpected spikes in requests from a key might indicate compromise. Implement rate limiting per user and per subscription. Public operations might allow 100 requests/minute per subscription. User-scoped operations might allow 50 requests/minute per user to prevent one user from consuming all resources. Grand Central enforces both, providing fair allocation. Never log tokens or subscription keys in application output, error messages, or debug statements. If you need to reference them in logs, use masked values likesub-key-***1234. Audit logs capture authentication metadata (which key was used, which user) without exposing the secrets themselves.
Next steps
- Rate Limiting - Quota management, burst handling, and client-side throttling
- Connecting Agents - Configure Claude Desktop, Copilot Studio, or custom MCP clients