@0x-wim/mcp-oauth
v0.2.1
Published
Platform-independent OAuth 2.1 authorization provider
Readme
@0x-wim/mcp-oauth
Platform-independent OAuth 2.1 provider, forked from @cloudflare/workers-oauth-provider with Cloudflare dependencies removed. Runs on Next.js, Node.js, and any standard fetch environment.
Installation
npm install @0x-wim/mcp-oauthPackages
| Entry point | Contents |
| ------------------------ | ------------------------------------------------------------- |
| @0x-wim/mcp-oauth | Core OAuthProvider, MemoryStore, StorageAdapter |
| @0x-wim/mcp-oauth/next | Next.js App Router helpers (createOAuthHandlers, getAuth) |
| @0x-wim/mcp-oauth/oidc | OIDC discovery and ID token verification |
Storage
Instead of Cloudflare KV, supply a StorageAdapter. MemoryStore is provided for development:
import { OAuthProvider, MemoryStore } from '@0x-wim/mcp-oauth';
const provider = new OAuthProvider({
storage: new MemoryStore(),
// ...
});For production, implement the StorageAdapter interface (get, put, delete, list) backed by Redis, a database, etc.
Basic Usage
import { OAuthProvider, MemoryStore } from '@0x-wim/mcp-oauth';
const provider = new OAuthProvider({
storage: new MemoryStore(),
apiRoute: ['/api/'],
apiHandler: {
async fetch(request, env, ctx) {
return new Response(`Hello, ${ctx.props.username}`);
},
},
defaultHandler: {
async fetch(request, env, ctx) {
const url = new URL(request.url);
if (url.pathname === '/authorize') {
const oauthReqInfo = await env.OAUTH_PROVIDER.parseAuthRequest(request);
// ... render consent UI ...
const { redirectTo } = await env.OAUTH_PROVIDER.completeAuthorization({
request: oauthReqInfo,
userId: '1234',
scope: oauthReqInfo.scope,
props: { username: 'Alice' },
});
return Response.redirect(redirectTo, 302);
}
return new Response('Not found', { status: 404 });
},
},
authorizeEndpoint: '/authorize',
tokenEndpoint: '/oauth/token',
clientRegistrationEndpoint: '/oauth/register',
});Next.js App Router
// app/[...oauth]/route.ts
import { createOAuthHandlers } from '@0x-wim/mcp-oauth/next';
export const { GET, POST, OPTIONS, DELETE, PUT, PATCH } = createOAuthHandlers(provider);The Next adapter automatically reconstructs the public request URL from
Forwarded, X-Forwarded-*, and Host headers before calling the provider, so
standalone/Docker deployments do not leak internal hostnames in OAuth metadata
or audience checks.
Authenticate requests in route handlers:
import { getAuth } from '@0x-wim/mcp-oauth/next';
const auth = await getAuth(provider, request);
if (!auth.authenticated) return auth.error;
// auth.token.grant.props — your user dataOIDC Helpers
import { discoverOIDC, verifyIdToken, fetchUserInfo } from '@0x-wim/mcp-oauth/oidc';
const config = await discoverOIDC('https://accounts.google.com');
const payload = await verifyIdToken(idToken, {
jwks: config.jwks_uri,
issuer: config.issuer,
audience: 'your-client-id',
});Key Options
See the upstream README for full option documentation. Differences from upstream:
storage: StorageAdapter— required (replacesOAUTH_KVbinding)- No Cloudflare-specific setup needed (no
wrangler.jsonc, no compatibility flags)
Standards
OAuth 2.1 · RFC 8414 · RFC 9728 · RFC 7591 · RFC 8693 · RFC 8707 · MCP Authorization
License
MIT
