plugin-oauth
Skill1 starsChanged 7 days agoMITView on GitHub
Add OAuth 2.1 sign-in to a remote MCP server so ChatGPT, Claude and other MCP clients can link a user's account - discovery documents, PKCE S256, Client ID Metadata Documents (CIMD) for ChatGPT and Claude plus Dynamic Client Registration (DCR) for everyone else, redirect allowlists, the iss parameter, refresh-token rotation, scopes, a consent page, and a reviewer email-and-password sign-in with no verification codes. Use when building or debugging MCP authentication, when a store says auth settings are incomplete, when linking an account bounces back to the sign-in page, or when a reviewer can't log in.
In this repository8 other files it gives its agents.
- AGENTS.mdAGENTS.md
- mcp-app-cardsSkill
- mcp-server-for-pluginsSkill
- plugin-packageSkill
- plugin-prerequisitesSkill
- publish-mcp-serverSkill
- submit-to-chatgptSkill
- submit-to-claudeSkill
The file
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 2 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 50
Ask for the fewest scopes at link time.
- Distinctive: line 72
Keep the password out of your repo, listing files and package: it goes only in each portal's credentials field.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
OAuth for an MCP server in both stores
The MCP authorization spec is OAuth 2.1 with PKCE, where your MCP server is the protected
resource and some authorization server (yours or a provider's) issues tokens. ChatGPT and Claude
both discover everything from metadata, register themselves, send the user to your sign-in page,
and come back with a code. Endpoint shapes and payloads: references/endpoints.md.
What to serve
- Protected resource metadata (RFC 9728) at
https://api.example.com/.well-known/oauth-protected-resource: the resource (…/mcp), the authorization server, the scopes. - Authorization server metadata (RFC 8414) at
/.well-known/oauth-authorization-server:authorization_endpoint,token_endpoint,registration_endpoint,revocation_endpoint,code_challenge_methods_supported: ["S256"],client_id_metadata_document_supported: true,authorization_response_iss_parameter_supported: true,scopes_supported. - 401 on
/mcpwithout a valid token, withWWW-Authenticate: Bearer resource_metadata="…". A token with too few scopes gets 403insufficient_scopenaming the scope it needs.
Registering clients: support both ways
- CIMD (ChatGPT, Claude, Claude Code): the
client_idis an https URL on the app's own domain (for examplehttps://claude.ai/oauth/...,https://chatgpt.com/oauth/.../client.json). Check its host against your list of known hosts before fetching, and fetch over https only, with no redirects, a short timeout and a size cap. Then check that itsclient_idequals its own URL, that its redirect URIs are on its own host or loopback, and that it usestoken_endpoint_auth_method: none. Cache the document for about an hour. - DCR (Cursor, Inspector, others): accept
POST /register, rate-limit it, and allow redirect URIs only on known app hosts, loopback, or app schemes you trust.
Known return addresses: Claude uses https://claude.ai/api/mcp/auth_callback; ChatGPT shows its
https://chatgpt.com/connector/oauth/<id> in the portal's connect panel.
The flow, and the details reviews check
- PKCE S256 required; reject
plain. - Bind every token to your MCP URL (the
resourceparameter, RFC 8707) and check it on use. - Send
isson every authorization response (RFC 9207), success and error. - Short-lived access tokens; refresh tokens that rotate, with a short reuse grace so a retried refresh doesn't log the user out.
- Ask for the fewest scopes at link time; ask for the sensitive one (spending credits) only when a tool first needs it.
- The consent page names the app (from its metadata), says whether it's a verified host, lists
each permission in plain words, and has Allow and Cancel. Accept only real clicks
(
event.isTrusted) so an extension or script can't allow on the user's behalf. That check runs in the browser only, so also refuse to be framed (Content-Security-Policy: frame-ancestors 'none') and require a CSRF token, tied to the session and the pending request, on the Allow POST.
The reviewer login
Both stores' reviewers need to sign in with an email and password and no codes. Do it without weakening real users' sign-in:
- One reviewer account in your identity provider with email/password enabled.
- Your server accepts a password sign-in only for that account's user id (an allowlist in config), never for an address that belongs to a real user, and pins the stored email so the token can't claim another address.
- Show the form only on the consent page, behind a small "App reviewers: sign in with email" link.
- Give the account a long random password used nowhere else, rate-limit the form, and give the account no admin, billing or other users' data. The form is public, so treat it as a target.
- Lift the account's usage limits and fill it with data for every test case.
- Keep the password out of your repo, listing files and package: it goes only in each portal's credentials field. If it may have leaked, change it and update both portals.
Debugging "it sends me back to the sign-in page"
Work from logs and analytics before theorising. Seen in practice:
- A trailing character in the pasted server URL ("…/mcp." → 404 at discovery).
- Another open tab of your web app signing the user out the moment the new sign-in lands (an auth listener that treats its first "no user yet" callback as a sign-out). Only a change from a signed-in user to nobody should end a session, and a tab should only adopt a token for the session's own person.
- Bot protection blocking the store's servers. Allow their published IP ranges for
/mcpand the OAuth endpoints. - A client-side fix that hasn't reached tabs opened before the deploy: reload them.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

