UNPKG

@ory/mcp-oauth-provider

Version:
2 lines 5.81 kB
import {ServerError}from'@modelcontextprotocol/sdk/server/auth/errors.js';import {OAuthClientInformationFullSchema,OAuthTokensSchema}from'@modelcontextprotocol/sdk/shared/auth.js';import*as h from'crypto';var d=class{constructor(e){this.skipLocalPasswordGrant=false;this.skipLocalPkceValidation=true;var t;this._endpoints=e.endpoints,this._providerType=e.providerType,this._hydraAdminUrl=e.hydraAdminUrl,this._hydraApiKey=e.hydraApiKey,this._networkProjectUrl=e.networkProjectUrl,this._networkProjectApiKey=e.networkProjectApiKey,(t=e.endpoints)!=null&&t.revocationUrl&&(this.revokeToken=async(r,n)=>{let i=this._endpoints.revocationUrl;if(!i)throw new Error("No revocation endpoint configured");let o=new URLSearchParams;o.set("token",n.token),o.set("client_id",r.client_id),r.client_secret&&o.set("client_secret",r.client_secret),n.token_type_hint&&o.set("token_type_hint",n.token_type_hint);let s=await fetch(i,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:o.toString()});if(!s.ok)throw new ServerError(`Token revocation failed: ${s.status}`)});}get clientsStore(){let e=this._endpoints.registrationUrl;return {getClient:this.getClient.bind(this),...e&&{registerClient:async t=>{let r=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!r.ok)throw new ServerError(`Client registration failed: ${r.status}`);let n=await r.json();return OAuthClientInformationFullSchema.parse(n)}}}}async fetchClients(){if(this._providerType==="hydra"){if(!this._hydraAdminUrl)throw new Error("Hydra admin URL is required for hydra provider type");let e=await fetch(`${this._hydraAdminUrl}/admin/clients`,{headers:{Authorization:`Bearer ${this._hydraApiKey}`,"Content-Type":"application/json"}});if(!e.ok)throw new Error(`Failed to list OAuth2 clients: ${e.statusText}`);return (await e.json()).map(r=>OAuthClientInformationFullSchema.parse(r))}if(this._providerType==="network"){if(!this._networkProjectUrl)throw new Error("Network project URL is required for network provider type");let e=await fetch(`${this._networkProjectUrl}/admin/clients`,{headers:{Authorization:`Bearer ${this._networkProjectApiKey}`,"Content-Type":"application/json"}});if(!e.ok)throw new Error(`Failed to list OAuth2 clients: ${e.statusText}`);return (await e.json()).map(r=>OAuthClientInformationFullSchema.parse(r))}throw new Error("Invalid provider type")}async listOAuth2Clients(){try{return (await this.fetchClients()).reduce((t,r)=>(t[r.client_id]=r,t),{})}catch(e){throw console.error("Error listing OAuth2 clients:",e),e}}async getClient(e){try{return (await this.listOAuth2Clients())[e]}catch(t){throw console.error("Error getting client:",t),t}}async authorize(e,t,r){var s;let n="";t.state||(n=h.randomBytes(32).toString("hex"),t.state=n);let i=new URL(this._endpoints.authorizationUrl),o=new URLSearchParams({client_id:e.client_id,response_type:"code",redirect_uri:t.redirectUri,code_challenge:t.codeChallenge,code_challenge_method:"S256"});t.state&&o.set("state",t.state),(s=t.scopes)!=null&&s.length&&o.set("scope",t.scopes.join(" ")),i.search=o.toString(),await new Promise(p=>setTimeout(p,100)),r.redirect(i.toString());}async challengeForAuthorizationCode(e,t){return await new Promise(r=>setTimeout(r,100)),""}async exchangeAuthorizationCode(e,t,r){let n=new URLSearchParams({grant_type:"authorization_code",client_id:e.client_id,code:t,redirect_uri:e.redirect_uris[0]});e.client_secret&&n.append("client_secret",e.client_secret),r&&n.append("code_verifier",r);let i=await fetch(this._endpoints.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:n.toString()});if(!i.ok)throw new ServerError(`Token exchange failed: ${i.status}`);let o=await i.json();return OAuthTokensSchema.parse(o)}async exchangeRefreshToken(e,t,r){let n=new URLSearchParams({grant_type:"refresh_token",client_id:e.client_id,refresh_token:t});e.client_secret&&n.set("client_secret",e.client_secret),r!=null&&r.length&&n.set("scope",r.join(" "));let i=await fetch(this._endpoints.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:n.toString()});if(!i.ok)throw new ServerError(`Token refresh failed: ${i.status}`);let o=await i.json();return OAuthTokensSchema.parse(o)}async introspectToken(e){if(this._providerType==="hydra"){if(!this._hydraAdminUrl)throw new Error("Hydra admin URL is required for hydra provider type");let t=await fetch(`${this._hydraAdminUrl}/admin/oauth2/introspect`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Authorization:`Basic ${Buffer.from(e).toString("base64")}`},body:new URLSearchParams({token:e,token_type_hint:"access_token"})});if(!t.ok)throw new Error(`Token introspection failed: ${t.statusText}`);return t.json()}if(this._providerType==="network"){if(!this._networkProjectUrl)throw new Error("Network project URL is required for network provider type");let t=await fetch(`${this._networkProjectUrl}/admin/oauth2/introspect`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Authorization:`Bearer ${this._networkProjectApiKey}`},body:new URLSearchParams({token:e,token_type_hint:"access_token"})});if(!t.ok)throw new Error(`Token introspection failed: ${t.statusText}`);return t.json()}throw new Error("Invalid provider type")}async verifyAccessToken(e){var t;try{let r=await this.introspectToken(e);if(!r.active)throw new Error("Token is not active");if(!(await this.listOAuth2Clients())[r.client_id])throw new Error("Token client ID mismatch");return {token:e,clientId:r.client_id,scopes:((t=r.scope)==null?void 0:t.split(" "))||[],expiresAt:r.exp}}catch(r){throw console.error("Token verification failed:",r),r}}};export{d as OryProvider};//# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map