MCP SSO Integration: Connecting Enterprise Identity Providers
A deep-dive guide to MCP SSO integration - OAuth 2.1, SAML 2.0, LDAP, SCIM, agent identity, and step-by-step setup for Okta, Azure AD, Google, Keycloak.
Mohammed Kafeel
Machine Learning Researcher
On this page
- What Is MCP SSO Integration - and Why Should You Care?
- Why Enterprise MCP Authentication Is Harder Than It Looks
- The Three Protocols You Need to Know
- How to Connect Your Enterprise IdP to MCP - Step by Step
- SCIM Provisioning: Automating User Lifecycle in MCP
- Agent Identity vs. User Identity - A Critical Distinction
- Conditional Access Policies for MCP
- Cross-Tenant Scenarios
- Security Best Practices for MCP SSO Integration
- Common Mistakes to Avoid
- Key Takeaways
- FAQ
- Useful Sources
According to the Verizon DBIR 2025, 29% of all enterprise breaches start with stolen or compromised credentials - and that number climbs to 46% when you include phishing. Now add AI tooling: MCP servers are being wired into production at speed, and most sit outside your identity perimeter.
This guide is the practical playbook for closing that gap.
⚡ TL;DR - Key Takeaways
- MCP servers act as OAuth 2.1 resource servers. Your enterprise IdP is the authorization server.
- OAuth 2.1 + PKCE is the canonical MCP auth standard as of the 2025-11-25 spec.
- Enterprise-Managed Authorization (EMA) - now stable - lets admins provision MCP access centrally.
- Agent identity ≠ user identity. AI agents need their own scoped credentials.
- SCIM provisioning automates the full lifecycle - including deprovisioning.
- PKCE with S256 is mandatory. No exceptions.
What Is MCP SSO Integration - and Why Should You Care?
MCP SSO integration means connecting MCP servers and clients to your organization's existing SSO infrastructure, so the same identity policies governing your SaaS apps also govern your AI tooling.
What Is MCP?
Model Context Protocol (MCP) is an open standard that defines how AI agents connect to external tools, data sources, and APIs. Think of it as USB-C for AI.
MCP defines three roles:
- MCP Host - the AI application (Claude Desktop, VS Code)
- MCP Client - the component inside the host managing server connections
- MCP Server - the service exposing tools and data
Why Connecting Them Matters
Without MCP SSO integration, every MCP server becomes a shadow IT problem. With it, MCP connections inherit your existing MFA policies, conditional access rules, audit logs, and centralized deprovisioning.
Why Enterprise MCP Authentication Is Harder Than It Looks
The core challenge: MCP is a many-to-many system. A typical enterprise has dozens of MCP servers, multiple MCP clients, and multiple identity stores.
The "MCP Auth Gap" Problem
The original MCP spec had minimal authorization guidance. Early adopters cobbled together API keys, hardcoded tokens, and one-off OAuth apps.
The 2025 MCP specification (version 2025-11-25) addressed this. MCP servers are now formally defined as OAuth 2.1 resource servers.
Multiple Clients × Multiple Servers × Multiple Identity Stores
Consider:
- 5 MCP clients: Claude Desktop, VS Code extension, Cursor, Python agent, CI/CD agent
- 12 MCP servers: GitHub, Jira, Confluence, Salesforce, HR API, data warehouse, Slack, Drive, PagerDuty, Datadog, ServiceNow, ML model server
- 3 identity stores: Okta, Active Directory, Google Workspace
Each combination is a potential auth misconfiguration. MCP SSO integration is the only scalable answer.
The Three Protocols You Need to Know
OAuth 2.0 + OIDC - The Modern Standard
OAuth 2.1 is the canonical authorization framework for MCP. The spec mandates it for HTTP-based transports. (For a deeper dive into the flow itself, see our guide to MCP OAuth 2.1.)
The flow:
- MCP client connects, receives
401 UnauthorizedwithWWW-Authenticateheader - Client fetches Protected Resource Metadata (RFC 9728) from
/.well-known/oauth-protected-resource - Client discovers the authorization server via OAuth 2.0 Server Metadata or OIDC Discovery
- Client initiates Authorization Code flow with PKCE (S256)
- User authenticates via enterprise SSO (MFA, conditional access)
- IdP issues an access token scoped to the MCP server (RFC 8707)
- Client sends every request with
Authorization: Bearer <token> - MCP server validates the token - signature, issuer, audience, expiry
import jwt
from fastapi import HTTPException
KEYCLOAK_JWKS_URL = "https://keycloak.example.com/realms/mcp-realm/protocol/openid-connect/certs"
JWT_ISSUER = "https://keycloak.example.com/realms/mcp-realm"
JWT_AUDIENCE = ["mcp-server-prod"]
def validate_mcp_token(token: str) -> dict:
jwks_client = jwt.PyJWKClient(KEYCLOAK_JWKS_URL)
signing_key = jwks_client.get_signing_key_from_jwt(token)
payload = jwt.decode(
token,
signing_key.key,
algorithms=["RS256"],
audience=JWT_AUDIENCE,
issuer=JWT_ISSUER,
)
return payload
SAML 2.0 - The Enterprise Workhorse
SAML 2.0 is still dominant in large enterprises, especially with on-premises infrastructure or strict compliance (HIPAA, FedRAMP, SOC 2). (We cover the full set of compliance requirements for MCP agents in regulated industries separately.)
SAML doesn't integrate directly with MCP's OAuth model - but it plays a critical upstream role. The common pattern:
- SAML 2.0 handles user authentication at the IdP layer
- The IdP issues OAuth 2.0 / OIDC tokens for MCP server access
- This is the SAML-to-OAuth bridge pattern
LDAP / Active Directory - The Legacy Layer
LDAP is essential for:
- Group synchronization - AD groups into your IdP for RBAC
- JIT user provisioning
- Attribute enrichment -
sAMAccountName,mail,memberOf
Use LDAPS (port 636) or STARTTLS - never plain LDAP. Use a read-only service account with minimal permissions.
Protocol Comparison
| Feature | OAuth 2.1 + OIDC | SAML 2.0 | LDAP / AD |
|---|---|---|---|
| MCP native support | ✅ Yes (mandated) | ⚠️ Via IdP bridge | ❌ Indirect only |
| Token format | JWT | XML assertion | N/A |
| Best for | Modern MCP auth | Legacy enterprise SSO | Group sync |
| MFA support | ✅ Via IdP | ✅ Via IdP | ❌ |
| Machine-to-machine | ✅ Client Credentials | ❌ | ❌ |
| Real-time revocation | ✅ Token introspection | ❌ | ⚠️ Partial |
How to Connect Your Enterprise IdP to MCP - Step by Step
Connecting Okta to MCP
Okta is the first IdP to implement Enterprise-Managed Authorization (EMA) for MCP via its Cross App Access (XAA) protocol.
Step 1: Create OAuth 2.0 app in Okta (Applications → Create App Integration → OIDC).
Step 2: Define MCP-specific scopes: mcp:tools, mcp:read, mcp:write, mcp:admin.
Step 3: Configure your MCP server to validate Okta tokens:
OKTA_ISSUER = "https://your-org.okta.com/oauth2/default"
OKTA_AUDIENCE = "api://mcp-server-prod"
OKTA_JWKS_URL = f"{OKTA_ISSUER}/v1/keys"
Step 4: Enable EMA via Okta XAA.
Connecting Azure AD (Entra ID) to MCP
az ad app create \
--display-name "MCP Server - Production" \
--sign-in-audience AzureADMyOrg \
--web-redirect-uris "https://mcp.yourcompany.com/auth/callback"
Define app roles (MCP.User, MCP.Admin, MCP.ReadOnly). Configure MCP server:
ENTRA_TENANT_ID = "your-tenant-id"
ENTRA_CLIENT_ID = "your-app-client-id"
ENTRA_ISSUER = f"https://login.microsoftonline.com/{ENTRA_TENANT_ID}/v2.0"
ENTRA_JWKS_URL = f"https://login.microsoftonline.com/{ENTRA_TENANT_ID}/discovery/v2.0/keys"
ENTRA_AUDIENCE = f"api://{ENTRA_CLIENT_ID}"
Enable Conditional Access for the MCP application - require MFA, compliant devices, restrict to corporate IP ranges.
Connecting Google Workspace to MCP
Configure OAuth consent screen with MCP-related scopes:
https://www.googleapis.com/auth/drive.readonlyhttps://www.googleapis.com/auth/gmail.readonlyhttps://www.googleapis.com/auth/calendar.events.readonly
GOOGLE_JWKS_URL = "https://www.googleapis.com/oauth2/v3/certs"
GOOGLE_ISSUER = "https://accounts.google.com"
GOOGLE_AUDIENCE = "your-google-client-id.apps.googleusercontent.com"
Enable Context-Aware Access for device compliance and network location.
Connecting Keycloak to MCP
Keycloak 26+ has native MCP authorization server support.
./kcadm.sh create realms -s realm=mcp-realm -s enabled=true -s sslRequired=external
./kcadm.sh create clients -r mcp-realm \
-s clientId=mcp-client \
-s publicClient=true \
-s 'redirectUris=["http://localhost:3000/callback","https://mcp.yourcompany.com/callback"]' \
-s 'attributes={"pkce.code.challenge.method":"S256"}'
Create a client scope mcp-scope with an Audience Mapper pointing to your MCP server URI.
SCIM Provisioning: Automating User Lifecycle in MCP
SCIM (System for Cross-domain Identity Management) automates the entire user lifecycle between your IdP and MCP-connected systems.
Why SCIM Matters for MCP
When a developer joins: SCIM creates their account, assigns groups, grants MCP server access. When they leave: SCIM revokes all of it - instantly.
SCIM for Non-Human Identities (Agent Accounts)
AI agents and service accounts can now be managed as SCIM entities. Agent identities are provisioned, credentials rotated, and deprovisioned when projects end.
Setting Up SCIM with Okta
- Applications → MCP app → Provisioning
- Enable SCIM provisioning, enter your SCIM endpoint
- Configure Push Groups to sync Okta groups to MCP roles
- Enable Deprovisioning - the critical step most teams skip
SCIM Endpoint Requirements
GET /scim/v2/Users
POST /scim/v2/Users
GET /scim/v2/Users/{id}
PUT /scim/v2/Users/{id}
DELETE /scim/v2/Users/{id}
GET /scim/v2/Groups
Agent Identity vs. User Identity - A Critical Distinction
This is the section most MCP security guides skip, and it's arguably the most important.
If your AI agent runs under a user's credentials:
- Blast radius is huge - compromised agent token = full user-level access
- Audit logs are useless - can't tell human from agent action
- Deprovisioning is broken - kill the user, kill the agent's pipeline?
The Right Pattern: Service Accounts + Client Credentials Flow
async def get_agent_token(token_url, client_id, client_secret, scope):
async with httpx.AsyncClient() as client:
response = await client.post(
token_url,
data={
"grant_type": "client_credentials",
"client_id": client_id,
"client_secret": client_secret,
"scope": scope,
"resource": "https://mcp.yourcompany.com"
}
)
return response.json()["access_token"]
Agent Identity Best Practices
- One identity per agent type, not per agent instance
- Scope to the minimum -
github:read+jira:comment, notgithub:write - Short-lived tokens (15 minutes for agents). Rotate client secrets every 90 days.
- Log every agent action with the agent's identity, not the user's
- Use workload identity federation instead of static client secrets where possible
Conditional Access Policies for MCP
A well-configured conditional access policy for MCP can require:
- MFA for any MCP tool that writes data
- Compliant device - only managed, MDM-enrolled devices
- Network location - external access triggers step-up auth
- Risk score - block/challenge anomalous sessions
Entra ID Conditional Access for MCP
- Create policy targeting your MCP app
- Conditions: include all users, exclude break-glass accounts
- Grant controls: require MFA + compliant device
- Session controls: sign-in frequency of 8 hours
Keycloak Client Policies
{
"name": "mcp-security-policy",
"conditions": [
{"condition": "client-id", "configuration": {"clients": ["mcp-client"]}}
],
"profiles": ["mcp-security-profile"]
}
Cross-Tenant Scenarios
Pattern 1: Federated identity with a shared IdP - Okta Org2Org or Entra ID B2B.
Pattern 2: Token exchange across tenants - OAuth 2.0 Token Exchange (RFC 8693). Always exchange for a tenant-scoped token.
Pattern 3: SCIM cross-tenant sync - Microsoft Entra ID cross-tenant synchronization (GA 2024).
For the data-plane side of this - keeping each tenant's agents from touching another's resources - see our deep dive on multi-tenant identity isolation.
Security Rules
- Never pass tokens across tenant boundaries unmodified
- Enforce explicit consent for cross-tenant MCP tool access
- Audit cross-tenant actions separately
- Apply stricter conditional access to cross-tenant sessions
Security Best Practices for MCP SSO Integration
PKCE - Non-Negotiable
PKCE with S256 is mandatory. If your IdP's discovery metadata doesn't include code_challenge_methods_supported, clients must refuse to proceed.
import secrets, hashlib, base64
def generate_pkce_pair():
code_verifier = secrets.token_urlsafe(64)
code_challenge = base64.urlsafe_b64encode(
hashlib.sha256(code_verifier.encode()).digest()
).rstrip(b'=').decode()
return code_verifier, code_challenge
Token Validation
Check on every request:
- Signature via JWKS endpoint
- Issuer (
iss) - exact match - Audience (
aud) - your MCP server's canonical URI - Expiry (
exp) - reject expired - Not-before (
nbf) - if present
Scope Design - Least Privilege
| Scope | Grants |
|---|---|
mcp:github.read |
Read-only GitHub access |
mcp:jira.comment |
Post Jira comments |
mcp:salesforce.read |
Read CRM data |
mcp:admin |
Administrative MCP (restrict tightly) |
Never create mcp:all. (Scopes are only half the picture - pair them with per-tool access control to enforce RBAC at the tool layer.)
Secrets Management
- Secrets manager (Vault, AWS Secrets Manager, Azure Key Vault) - never env vars or code
- Rotate every 90 days - automate
- For agents: workload identity federation over static secrets
- Never log access tokens
Token Audience Binding (RFC 8707)
GET /authorize?
response_type=code&
client_id=mcp-client&
redirect_uri=https://app.example.com/callback&
scope=mcp:github.read&
resource=https://mcp.yourcompany.com&
code_challenge=...&
code_challenge_method=S256
Common Mistakes to Avoid
- Using long-lived API keys instead of OAuth tokens
- Skipping token audience validation
- Running agents under user credentials
- Not implementing SCIM deprovisioning
- Treating STDIO transport like HTTP transport
- Ignoring the
resourceparameter - Allowing personal accounts in enterprise MCP flows
- Not testing token revocation
Key Takeaways
- OAuth 2.1 + PKCE is the standard
- Your IdP is the authority
- Enterprise-Managed Authorization (EMA) is now stable - adopt it
- SAML 2.0 still matters as the upstream auth mechanism
- LDAP/AD feeds your IdP - keep it healthy
- Agent identity is a first-class concern
- SCIM provisioning closes the deprovisioning gap
- Conditional access separates secure from compliant-on-paper
FAQ
What is MCP SSO integration?
Connecting MCP servers and clients to your enterprise SSO. Users authenticate once through your IdP and receive OAuth 2.1 tokens that grant scoped access to MCP tools.
Does MCP support SAML 2.0 directly?
Not directly. MCP mandates OAuth 2.1. SAML plays an upstream role: SAML handles enterprise SSO at the IdP, and the IdP issues OAuth 2.1 tokens for MCP. This is the SAML-to-OAuth bridge.
How does MCP OAuth work with Okta?
Register your MCP server as an OAuth 2.0 app in Okta. Configure scopes and set up an Authorization Server. Your MCP client initiates Authorization Code flow with PKCE, Okta issues a scoped JWT, the MCP server validates via JWKS. Enable Okta XAA for EMA.
What is the difference between agent identity and user identity in MCP?
User identity: human authenticating interactively via SSO. Agent identity: autonomous AI process authenticating via Client Credentials flow. Agents need dedicated service account credentials, scoped to minimum permissions, separate from human accounts.
What is SCIM provisioning and why does MCP need it?
SCIM automates user lifecycle management. Your IdP can automatically provision MCP access on join, update on role change, and revoke on departure. Without SCIM deprovisioning, ex-employees retain MCP access indefinitely.
What is Enterprise-Managed Authorization (EMA)?
A stable MCP extension making your IdP the authoritative decision-maker for MCP server access. Admins define policies once; users get automatic connection to authorized servers - no per-server OAuth consent. Okta was the first IdP to implement EMA via its Cross App Access (XAA) protocol.
How do I handle cross-tenant MCP access for contractors?
Use token exchange (RFC 8693): contractor authenticates in their home tenant; your authorization server exchanges that token for a tenant-scoped token with limited permissions. Apply stricter conditional access to cross-tenant sessions.
Is LDAP authentication still relevant for MCP in 2025?
LDAP doesn't integrate directly with MCP's OAuth model, but it remains essential as the protocol your IdP uses to sync user and group data from on-prem Active Directory. Use LDAPS (636) or STARTTLS, read-only service account, sync groups regularly.
Useful Sources
- MCP Authorization Specification (2025-11-25)
- Enterprise-Managed Authorization Extension
- MCP Authorization Extensions Repository
- Keycloak MCP Authorization Server Guide
- Google Workspace MCP Server Configuration
- Microsoft Entra ID Conditional Access
- RFC 9728 - Protected Resource Metadata
- RFC 8707 - Resource Indicators for OAuth 2.0
- Verizon DBIR 2025
Keep reading
Multi-Tenant MCP: How to Isolate Agent Access Across Clients
Running multiple clients through a single MCP server without proper isolation is a data breach waiting to happen. Here's how to architect tenant boundaries that hold.
MCP Access Control: Implementing Per-Tool RBAC for AI Agents
A developer-first guide to per-tool role-based access control for MCP servers, with code, a decision matrix, real incidents, and a ready-to-use checklist.
How to Audit Third-Party MCP Servers Using mcp-scan
A step-by-step guide to auditing third-party MCP servers with mcp-scan — installation, CLI commands, threat types, tool pinning, CI/CD integration, and security best practices.



