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.

MK

Mohammed Kafeel

Machine Learning Researcher

June 19, 202618 min read
On this page

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:

  1. MCP client connects, receives 401 Unauthorized with WWW-Authenticate header
  2. Client fetches Protected Resource Metadata (RFC 9728) from /.well-known/oauth-protected-resource
  3. Client discovers the authorization server via OAuth 2.0 Server Metadata or OIDC Discovery
  4. Client initiates Authorization Code flow with PKCE (S256)
  5. User authenticates via enterprise SSO (MFA, conditional access)
  6. IdP issues an access token scoped to the MCP server (RFC 8707)
  7. Client sends every request with Authorization: Bearer <token>
  8. 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.readonly
  • https://www.googleapis.com/auth/gmail.readonly
  • https://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

  1. Applications → MCP app → Provisioning
  2. Enable SCIM provisioning, enter your SCIM endpoint
  3. Configure Push Groups to sync Okta groups to MCP roles
  4. 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, not github: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

  1. Create policy targeting your MCP app
  2. Conditions: include all users, exclude break-glass accounts
  3. Grant controls: require MFA + compliant device
  4. 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 resource parameter
  • 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