> ## Documentation Index
> Fetch the complete documentation index at: https://portkey-docs-chore-bedrock-service-tier-support.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Bring Your Own Auth

> Use your own identity provider for gateway authentication.

External OAuth enables using your existing identity provider (Okta, Auth0, Azure AD, Cognito) instead of Portkey's built-in authentication. Users authenticate with corporate credentials—no Portkey accounts needed.

## When to Use

Organizations with existing IdPs can use External OAuth. Users authenticate through the IdP for other services, and MCP access works the same way.

Common scenarios:

* **SSO for internal developers.** Engineers use corporate credentials to access MCP servers
* **B2B applications.** Your customers authenticate through their own IdP
* **Compliance requirements.** Mandate use of your own identity infrastructure
* **No Portkey accounts.** Users who aren't in Portkey need MCP access

***

## How It Works

```
1. User authenticates with your IdP
2. IdP issues a JWT (or opaque token)
3. User includes token in MCP requests to Portkey
4. Portkey validates token against your IdP
5. Request proceeds with user identity attached
```

Portkey never handles user credentials. Your IdP remains the source of truth for identity.

***

## Configuration

Configure JWT validation for your MCP server. Portkey validates incoming tokens using your IdP's public keys or introspection endpoint.

### Option 1: JWKS URI (Recommended)

The most common setup. Portkey fetches public keys from your IdP's JWKS endpoint.

```json theme={null}
{
  "jwt_validation": {
    "jwksUri": "https://your-idp.com/.well-known/jwks.json",
    "algorithms": ["RS256"],
    "requiredClaims": ["sub", "email"]
  }
}
```

**How it works:**

* Portkey fetches and caches your IdP's public keys
* Keys are cached for 24 hours by default
* If a key rotates, Portkey automatically refetches
* Validation happens locally (no network call per request)

### Option 2: Token Introspection

For opaque tokens requiring real-time validation, or for immediate revocation.

```json theme={null}
{
  "jwt_validation": {
    "introspectEndpoint": "https://your-idp.com/oauth/introspect",
    "introspectCacheMaxAge": 300
  }
}
```

**How it works:**

* Portkey calls your IdP's introspection endpoint
* Response is cached for the configured duration (default: no caching)
* With `introspectCacheMaxAge: 300`, results are cached for 5 minutes

**Caching tradeoff:**

* No cache: Every request calls introspection endpoint (slower, but immediate revocation)
* With cache: Better performance, but revocation takes up to cache TTL to take effect

See [JWT Validation](/product/mcp-gateway/authentication/jwt) for full configuration options.

***

## Client Configuration

Agents include the IdP token instead of a Portkey API key:

```json theme={null}
{
  "mcpServers": {
    "linear": {
      "url": "https://mcp.portkey.ai/linear/mcp",
      "headers": {
        "Authorization": "Bearer eyJhbGciOiJSUzI1NiIs..."
      }
    }
  }
}
```

Or in code:

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    # Get token from your IdP (example using OIDC)
    token = get_idp_token()  # Your IdP client

    headers = {
        "Authorization": f"Bearer {token}",
    }

    async with streamablehttp_client(
        "https://mcp.portkey.ai/linear/mcp",
        headers=headers
    ) as (read, write, _):
        # MCP operations...
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    // Get token from your IdP
    const token = await getIdpToken();  // Your IdP client

    const client = new MCPClient({
      url: "https://mcp.portkey.ai/linear/mcp",
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });
    ```
  </Tab>
</Tabs>

***

## Validating Claim Values

Validate that tokens are issued by the correct IdP and intended for MCP access:

```json theme={null}
{
  "jwt_validation": {
    "jwksUri": "https://your-idp.com/.well-known/jwks.json",
    "algorithms": ["RS256"],
    "requiredClaims": ["sub", "email"],
    "claimValues": {
      "iss": {
        "values": "https://your-idp.com",
        "matchType": "exact"
      },
      "aud": {
        "values": ["api://mcp", "https://mcp.yourcompany.com"],
        "matchType": "contains"
      }
    }
  }
}
```

This prevents:

* Tokens from other IdPs being accepted
* Tokens intended for other services being used for MCP

***

## Combining with Identity Forwarding

External OAuth pairs naturally with identity forwarding. Portkey validates the incoming JWT, extracts user claims, and forwards them to MCP servers.

```json theme={null}
{
  "jwt_validation": {
    "jwksUri": "https://your-idp.com/.well-known/jwks.json",
    "requiredClaims": ["sub", "email", "groups"]
  },
  "user_identity_forwarding": {
    "method": "claims_header",
    "include_claims": ["sub", "email", "groups"]
  }
}
```

The MCP server receives user identity without handling OAuth itself. It can use this for:

* **Authorization**: Check if user belongs to required groups
* **Logging**: Audit trail with user identity
* **Personalization**: Customize responses based on user

See [Identity Forwarding](/product/mcp-gateway/authentication/identity-forwarding).

***

## IdP-Specific Examples

### Okta

1. Create an authorization server in Okta Admin Console
2. Create an OAuth application (Web or SPA)
3. Note your issuer URL (e.g., `https://dev-12345.okta.com/oauth2/default`)

```json theme={null}
{
  "jwt_validation": {
    "jwksUri": "https://dev-12345.okta.com/oauth2/default/v1/keys",
    "algorithms": ["RS256"],
    "claimValues": {
      "iss": {
        "values": "https://dev-12345.okta.com/oauth2/default",
        "matchType": "exact"
      }
    }
  }
}
```

### Auth0

1. Create an API in Auth0 Dashboard
2. Note your tenant domain and API identifier

```json theme={null}
{
  "jwt_validation": {
    "jwksUri": "https://your-tenant.auth0.com/.well-known/jwks.json",
    "algorithms": ["RS256"],
    "claimValues": {
      "iss": {
        "values": "https://your-tenant.auth0.com/",
        "matchType": "exact"
      },
      "aud": {
        "values": "https://your-api-identifier",
        "matchType": "exact"
      }
    }
  }
}
```

### Azure AD / Entra ID

1. Register an application in Azure Portal
2. Note your tenant ID and client ID

```json theme={null}
{
  "jwt_validation": {
    "jwksUri": "https://login.microsoftonline.com/{tenant-id}/discovery/v2.0/keys",
    "algorithms": ["RS256"],
    "claimValues": {
      "iss": {
        "values": "https://login.microsoftonline.com/{tenant-id}/v2.0",
        "matchType": "exact"
      },
      "aud": {
        "values": "{client-id}",
        "matchType": "exact"
      }
    }
  }
}
```

### AWS Cognito

1. Create a User Pool in AWS Console
2. Note your region and pool ID

```json theme={null}
{
  "jwt_validation": {
    "jwksUri": "https://cognito-idp.{region}.amazonaws.com/{pool-id}/.well-known/jwks.json",
    "algorithms": ["RS256"],
    "claimValues": {
      "iss": {
        "values": "https://cognito-idp.{region}.amazonaws.com/{pool-id}",
        "matchType": "exact"
      }
    }
  }
}
```

***

## Securing Your Setup

### Validate Issuer and Audience

Always configure `claimValues` to verify `iss` and `aud`:

```json theme={null}
{
  "claimValues": {
    "iss": {
      "values": "https://your-idp.com",
      "matchType": "exact"
    },
    "aud": {
      "values": "your-client-id-or-api-identifier",
      "matchType": "exact"
    }
  }
}
```

Without this, tokens intended for other applications might be accepted.

### Require Essential Claims

Require essential claims:

```json theme={null}
{
  "requiredClaims": ["sub", "email"]
}
```

If a claim is missing, the request is rejected.

### Use Short Token Lifetimes

Configure the IdP to issue short-lived access tokens (15-60 minutes). This limits the window if a token is compromised.

***

## Troubleshooting

### "Invalid issuer" Error

The token's `iss` claim doesn't match your configuration. Verify the issuer URL exactly matches—including trailing slashes.

### "Missing required claims" Error

The token doesn't include claims you specified in `requiredClaims`. Check your IdP's token configuration and scopes.

### "Invalid audience" Error

The token's `aud` claim doesn't match your configuration. Verify the correct API identifier or client ID.

### "JWKS fetch failed" Error

Portkey couldn't fetch keys from your JWKS URI. Verify the URL is accessible and returns valid JWKS JSON.

***

## Related

| Topic                                                                          | Description                                     |
| ------------------------------------------------------------------------------ | ----------------------------------------------- |
| [JWT Validation](/product/mcp-gateway/authentication/jwt)                      | Full configuration reference for JWT validation |
| [Identity Forwarding](/product/mcp-gateway/authentication/identity-forwarding) | Pass validated claims to MCP servers            |
| [Authentication Overview](/product/mcp-gateway/authentication)                 | Understanding gateway authentication            |
