0

WorkOS Authentication

awesome-llm-appsauthentication

Setting up OAuth with WorkOS AuthKit.

Sign in to save downloads to your library and vote.

Preview

WorkOS Authentication

Setting up OAuth with WorkOS AuthKit.

Learn more: WorkOS MCP docs · WorkOS AuthKit


Quick Start

import { MCPServer, oauthWorkOSProvider, object } from "mcp-use/server";

const server = new MCPServer({
  name: "my-server",
  version: "1.0.0",
  oauth: oauthWorkOSProvider(),
});

server.tool(
  { name: "whoami", description: "Get authenticated user info" },
  async (_args, ctx) =>
    object({
      userId: ctx.auth.user.userId,
      email: ctx.auth.user.email,
      name: ctx.auth.user.name,
    }),
);

server.listen();

With a .env file:

MCP_USE_OAUTH_WORKOS_SUBDOMAIN=your-company.authkit.app

That's it. JWT verification, OAuth discovery, and token proxying are handled automatically.


Environment Variables

VariableRequiredDescription
MCP_USE_OAUTH_WORKOS_SUBDOMAINYesYour full AuthKit domain (e.g., my-company.authkit.app)
MCP_USE_OAUTH_WORKOS_CLIENT_IDNoPre-registered OAuth client ID. Omit for DCR mode
MCP_USE_OAUTH_WORKOS_API_KEYNoWorkOS API key for making WorkOS API calls

Finding Your Subdomain

WorkOS Dashboard → Domains tab → AuthKit Domain

Use the full AuthKit domain including .authkit.app. For example, if your AuthKit domain is my-company.authkit.app, set the value to my-company.authkit.app (not just my-company).


Configuration Options

Zero-config (reads from env vars):

oauth: oauthWorkOSProvider();

Explicit config (overrides env vars):

oauth: oauthWorkOSProvider({
  subdomain: "my-company.authkit.app",
  clientId: "client_01KB5DRXBDDY1VGCBKY108SKJW", // optional
  apiKey: "sk_test_...", // optional
  verifyJwt: false, // development only
});
OptionTypeDefaultDescription
subdomainstringenv varFull AuthKit domain (e.g., my-company.authkit.app)
clientIdstring?env varPre-registered client ID. Omit for DCR
apiKeystring?env varWorkOS API key
verifyJwtboolean?trueSet false to skip JWT verification (development only)

Dynamic Client Registration (DCR)

DCR lets MCP clients register themselves automatically with WorkOS. This is the recommended mode for MCP servers.

Testing with the MCP Inspector: Use DCR mode (do not set MCP_USE_OAUTH_WORKOS_CLIENT_ID). The Inspector relies on DCR to self-register — without it, the OAuth flow will stall because the Inspector has no pre-configured client_id.

Setup:

  1. Don't set MCP_USE_OAUTH_WORKOS_CLIENT_ID
  2. Enable DCR in WorkOS Dashboard → Connect → Configuration

MCP clients (like the Inspector) will register themselves on first connection.

Pre-registered Client (Alternative)

If you need a specific OAuth client instead of DCR:

  1. Create an OAuth application in WorkOS Dashboard → Connect → OAuth Applications
  2. Set MCP_USE_OAUTH_WORKOS_CLIENT_ID to the client ID
  3. Configure redirect URIs in the dashboard to match your MCP client

User Context

WorkOS populates these fields on ctx.auth.user:

FieldTypeSource
userIdstringsub claim
emailstring?email claim
namestring?name claim
usernamestring?preferred_username claim
picturestring?picture claim
rolesstring[]roles claim
permissionsstring[]permissions claim
scopesstring[]Parsed from scope claim
email_verifiedboolean?email_verified claim
organization_idstring?org_id claim
sidstring?Session ID

Role-Based Access

server.tool(
  { name: "admin-action", description: "Admin-only operation" },
  async (_args, ctx) => {
    if (!ctx.auth.user.roles?.includes("admin")) {
      return error("Forbidden: admin role required");
    }

    // ... admin logic
    return text("Done");
  },
);

Making WorkOS API Calls

Use the WorkOS API key (not the user's access token) for WorkOS management API calls:

const WORKOS_API_KEY = process.env.MCP_USE_OAUTH_WORKOS_API_KEY;

server.tool(
  { name: "get-workos-user", description: "Fetch user profile from WorkOS" },
  async (_args, ctx) => {
    if (!WORKOS_API_KEY) {
      return error("WorkOS API key not configured");
    }

    const res = await fetch(
      `https://api.workos.com/user_management/users/${ctx.auth.user.userId}`,
      {
        headers: {
          Authorization: `Bearer ${WORKOS_API_KEY}`,
          "Content-Type": "application/json",
        },
      },
    );

    if (!res.ok) {
      return error(`WorkOS API failed: ${res.status} ${res.statusText}`);
    }

    return object(await res.json());
  },
);

Example .env

# Required: Full AuthKit domain (WorkOS Dashboard → Domains → AuthKit Domain)
MCP_USE_OAUTH_WORKOS_SUBDOMAIN=my-company.authkit.app

# Optional: Pre-registered OAuth client ID (omit for DCR mode)
# MCP_USE_OAUTH_WORKOS_CLIENT_ID=client_01KB5DRXBDDY1VGCBKY108SKJW

# Optional: WorkOS API key for management API calls
MCP_USE_OAUTH_WORKOS_API_KEY=sk_test_...

Troubleshooting

Redirect URI Mismatch

If you get a redirect URI error during the OAuth flow, add your client's callback URL to WorkOS:

  1. Go to WorkOS Dashboard → Developer → Redirects tab
  2. Click Edit redirect URIs
  3. Add the redirect URI your MCP client expects

For example, if testing locally with the MCP Inspector on port 3000:

http://localhost:3000/oauth/callback

The exact URI depends on your client and port — check the error message for the expected value.

Note: Changes to redirect URIs in WorkOS may take a few minutes to take effect.


Next Steps

Ingestion metadata

Source catalog
awesome-llm-apps
File path
generative_ui_agents/ai-mcp-app-builder/apps/mcp-use-server/.agent/skills/mcp-apps-builder/references/authentication/workos.md
Last refreshed
10/24/2026, 3:00:14 AM (5h ago)
Refresh schedule
Daily · 03:00 UTC
Dedupe status
Unique · deduped by (source, url)