{"version":3,"sources":["../src/index.ts"],"names":["OryProvider","options","_a","client","request","revocationUrl","params","response","ServerError","registrationUrl","data","OAuthClientInformationFullSchema","acc","error","clientId","res","state","h","targetUrl","searchParams","resolve","_client","_authorizationCode","authorizationCode","codeVerifier","OAuthTokensSchema","refreshToken","scopes","token","introspection"],"mappings":"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","file":"index.cjs","sourcesContent":["// Copyright © 2025 Ory Corp\n\nimport { OAuthRegisteredClientsStore } from '@modelcontextprotocol/sdk/server/auth/clients.js';\nimport { ServerError } from '@modelcontextprotocol/sdk/server/auth/errors.js';\nimport {\n  AuthorizationParams,\n  OAuthServerProvider,\n} from '@modelcontextprotocol/sdk/server/auth/provider.js';\nimport { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js';\nimport {\n  OAuthClientInformationFull,\n  OAuthClientInformationFullSchema,\n  OAuthTokenRevocationRequest,\n  OAuthTokensSchema,\n  OAuthTokens,\n} from '@modelcontextprotocol/sdk/shared/auth.js';\nimport * as crypto from 'crypto';\nimport { Response } from 'express';\n\nexport type OryEndpoints = {\n  authorizationUrl: string;\n  tokenUrl: string;\n  revocationUrl?: string;\n  registrationUrl?: string;\n};\n\nexport type HydraClient = {\n  client_id: string;\n  redirect_uris: string[];\n};\n\nexport type OryProviderType = 'network' | 'hydra';\n\nexport type BaseOryOptions = {\n  endpoints: OryEndpoints;\n  providerType: OryProviderType;\n  hydraAdminUrl?: string;\n  hydraApiKey?: string;\n  networkProjectUrl?: string;\n  networkProjectApiKey?: string;\n};\n\nexport type OryOptions = BaseOryOptions;\n\nexport class OryProvider implements OAuthServerProvider {\n  protected readonly _endpoints: OryEndpoints;\n  protected readonly _providerType: OryProviderType;\n  protected readonly _hydraAdminUrl?: string;\n  protected readonly _hydraApiKey?: string;\n  protected readonly _networkProjectUrl?: string;\n  protected readonly _networkProjectApiKey?: string;\n\n  skipLocalPasswordGrant = false;\n  skipLocalPkceValidation = true;\n\n  revokeToken?: (\n    client: OAuthClientInformationFull,\n    request: OAuthTokenRevocationRequest\n  ) => Promise<void>;\n\n  constructor(options: OryOptions) {\n    this._endpoints = options.endpoints;\n    this._providerType = options.providerType;\n    this._hydraAdminUrl = options.hydraAdminUrl;\n    this._hydraApiKey = options.hydraApiKey;\n    this._networkProjectUrl = options.networkProjectUrl;\n    this._networkProjectApiKey = options.networkProjectApiKey;\n\n    if (options.endpoints?.revocationUrl) {\n      this.revokeToken = async (\n        client: OAuthClientInformationFull,\n        request: OAuthTokenRevocationRequest\n      ): Promise<void> => {\n        const revocationUrl = this._endpoints.revocationUrl;\n\n        if (!revocationUrl) {\n          throw new Error('No revocation endpoint configured');\n        }\n\n        const params = new URLSearchParams();\n        params.set('token', request.token);\n        params.set('client_id', client.client_id);\n        if (client.client_secret) {\n          params.set('client_secret', client.client_secret);\n        }\n        if (request.token_type_hint) {\n          params.set('token_type_hint', request.token_type_hint);\n        }\n\n        const response = await fetch(revocationUrl, {\n          method: 'POST',\n          headers: {\n            'Content-Type': 'application/x-www-form-urlencoded',\n          },\n          body: params.toString(),\n        });\n\n        if (!response.ok) {\n          throw new ServerError(`Token revocation failed: ${response.status}`);\n        }\n      };\n    }\n  }\n\n  get clientsStore(): OAuthRegisteredClientsStore {\n    const registrationUrl = this._endpoints.registrationUrl;\n    return {\n      getClient: this.getClient.bind(this),\n      ...(registrationUrl && {\n        registerClient: async (\n          client: OAuthClientInformationFull\n        ): Promise<OAuthClientInformationFull> => {\n          const response = await fetch(registrationUrl, {\n            method: 'POST',\n            headers: {\n              'Content-Type': 'application/json',\n            },\n            body: JSON.stringify(client),\n          });\n\n          if (!response.ok) {\n            throw new ServerError(`Client registration failed: ${response.status}`);\n          }\n\n          const data = (await response.json()) as Record<string, unknown>;\n          return OAuthClientInformationFullSchema.parse(data);\n        },\n      }),\n    };\n  }\n\n  private async fetchClients(): Promise<OAuthClientInformationFull[]> {\n    if (this._providerType === 'hydra') {\n      if (!this._hydraAdminUrl) {\n        throw new Error('Hydra admin URL is required for hydra provider type');\n      }\n      const response = await fetch(`${this._hydraAdminUrl}/admin/clients`, {\n        headers: {\n          Authorization: `Bearer ${this._hydraApiKey}`,\n          'Content-Type': 'application/json',\n        },\n      });\n\n      if (!response.ok) {\n        throw new Error(`Failed to list OAuth2 clients: ${response.statusText}`);\n      }\n\n      const clients = (await response.json()) as unknown[];\n      return clients.map((client: unknown) => OAuthClientInformationFullSchema.parse(client));\n    }\n\n    if (this._providerType === 'network') {\n      if (!this._networkProjectUrl) {\n        throw new Error('Network project URL is required for network provider type');\n      }\n      const response = await fetch(`${this._networkProjectUrl}/admin/clients`, {\n        headers: {\n          Authorization: `Bearer ${this._networkProjectApiKey}`,\n          'Content-Type': 'application/json',\n        },\n      });\n\n      if (!response.ok) {\n        throw new Error(`Failed to list OAuth2 clients: ${response.statusText}`);\n      }\n\n      const clients = (await response.json()) as unknown[];\n      return clients.map((client: unknown) => OAuthClientInformationFullSchema.parse(client));\n    }\n\n    throw new Error('Invalid provider type');\n  }\n\n  async listOAuth2Clients(): Promise<Record<string, OAuthClientInformationFull>> {\n    try {\n      const clients = await this.fetchClients();\n      return clients.reduce(\n        (acc: Record<string, OAuthClientInformationFull>, client: OAuthClientInformationFull) => {\n          acc[client.client_id] = client;\n          return acc;\n        },\n        {}\n      );\n    } catch (error) {\n      console.error('Error listing OAuth2 clients:', error);\n      throw error;\n    }\n  }\n\n  async getClient(clientId: string): Promise<OAuthClientInformationFull | undefined> {\n    try {\n      const clients = await this.listOAuth2Clients();\n      return clients[clientId];\n    } catch (error) {\n      console.error('Error getting client:', error);\n      throw error;\n    }\n  }\n\n  async authorize(\n    client: OAuthClientInformationFull,\n    params: AuthorizationParams,\n    res: Response\n  ): Promise<void> {\n    let state = '';\n    if (!params.state) {\n      state = crypto.randomBytes(32).toString('hex');\n      params.state = state;\n    }\n\n    // Start with required OAuth parameters\n    const targetUrl = new URL(this._endpoints.authorizationUrl);\n    const searchParams = new URLSearchParams({\n      client_id: client.client_id,\n      response_type: 'code',\n      redirect_uri: params.redirectUri,\n      code_challenge: params.codeChallenge,\n      code_challenge_method: 'S256',\n    });\n\n    // Add optional standard OAuth parameters\n    if (params.state) searchParams.set('state', params.state);\n    if (params.scopes?.length) searchParams.set('scope', params.scopes.join(' '));\n\n    targetUrl.search = searchParams.toString();\n    // This below line is just a hack to make the function async as lint will complain\n    await new Promise(resolve => setTimeout(resolve, 100));\n    res.redirect(targetUrl.toString());\n  }\n\n  async challengeForAuthorizationCode(\n    _client: OAuthClientInformationFull,\n    _authorizationCode: string\n  ): Promise<string> {\n    // In a proxy setup, we don't store the code challenge ourselves\n    // Instead, we proxy the token request and let the upstream server validate it\n    // This below line is just a hack to make the function async as lint will complain\n    await new Promise(resolve => setTimeout(resolve, 100));\n    return '';\n  }\n\n  async exchangeAuthorizationCode(\n    client: OAuthClientInformationFull,\n    authorizationCode: string,\n    codeVerifier?: string\n  ): Promise<OAuthTokens> {\n    const params = new URLSearchParams({\n      grant_type: 'authorization_code',\n      client_id: client.client_id,\n      code: authorizationCode,\n      redirect_uri: client.redirect_uris[0],\n    });\n\n    if (client.client_secret) {\n      params.append('client_secret', client.client_secret);\n    }\n\n    if (codeVerifier) {\n      params.append('code_verifier', codeVerifier);\n    }\n\n    const response = await fetch(this._endpoints.tokenUrl, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/x-www-form-urlencoded',\n      },\n      body: params.toString(),\n    });\n\n    if (!response.ok) {\n      throw new ServerError(`Token exchange failed: ${response.status}`);\n    }\n\n    const data = (await response.json()) as Record<string, unknown>;\n    return OAuthTokensSchema.parse(data);\n  }\n\n  async exchangeRefreshToken(\n    client: OAuthClientInformationFull,\n    refreshToken: string,\n    scopes?: string[]\n  ): Promise<OAuthTokens> {\n    const params = new URLSearchParams({\n      grant_type: 'refresh_token',\n      client_id: client.client_id,\n      refresh_token: refreshToken,\n    });\n\n    if (client.client_secret) {\n      params.set('client_secret', client.client_secret);\n    }\n\n    if (scopes?.length) {\n      params.set('scope', scopes.join(' '));\n    }\n\n    const response = await fetch(this._endpoints.tokenUrl, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/x-www-form-urlencoded',\n      },\n      body: params.toString(),\n    });\n\n    if (!response.ok) {\n      throw new ServerError(`Token refresh failed: ${response.status}`);\n    }\n\n    const data = (await response.json()) as Record<string, unknown>;\n    return OAuthTokensSchema.parse(data);\n  }\n\n  private async introspectToken(token: string): Promise<{\n    active: boolean;\n    client_id: string;\n    scope?: string;\n    exp: number;\n  }> {\n    if (this._providerType === 'hydra') {\n      if (!this._hydraAdminUrl) {\n        throw new Error('Hydra admin URL is required for hydra provider type');\n      }\n      const response = await fetch(`${this._hydraAdminUrl}/admin/oauth2/introspect`, {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/x-www-form-urlencoded',\n          Authorization: `Basic ${Buffer.from(token).toString('base64')}`,\n        },\n        body: new URLSearchParams({\n          token,\n          token_type_hint: 'access_token',\n        }),\n      });\n\n      if (!response.ok) {\n        throw new Error(`Token introspection failed: ${response.statusText}`);\n      }\n\n      return response.json() as Promise<{\n        active: boolean;\n        client_id: string;\n        scope?: string;\n        exp: number;\n      }>;\n    }\n\n    if (this._providerType === 'network') {\n      if (!this._networkProjectUrl) {\n        throw new Error('Network project URL is required for network provider type');\n      }\n      const response = await fetch(`${this._networkProjectUrl}/admin/oauth2/introspect`, {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/x-www-form-urlencoded',\n          Authorization: `Bearer ${this._networkProjectApiKey}`,\n        },\n        body: new URLSearchParams({\n          token,\n          token_type_hint: 'access_token',\n        }),\n      });\n\n      if (!response.ok) {\n        throw new Error(`Token introspection failed: ${response.statusText}`);\n      }\n\n      return response.json() as Promise<{\n        active: boolean;\n        client_id: string;\n        scope?: string;\n        exp: number;\n      }>;\n    }\n\n    throw new Error('Invalid provider type');\n  }\n\n  async verifyAccessToken(token: string): Promise<AuthInfo> {\n    try {\n      const introspection = await this.introspectToken(token);\n\n      if (!introspection.active) {\n        throw new Error('Token is not active');\n      }\n\n      const clients = await this.listOAuth2Clients();\n      const client = clients[introspection.client_id];\n\n      if (!client) {\n        throw new Error('Token client ID mismatch');\n      }\n\n      return {\n        token,\n        clientId: introspection.client_id,\n        scopes: introspection.scope?.split(' ') || [],\n        expiresAt: introspection.exp,\n      };\n    } catch (error) {\n      console.error('Token verification failed:', error);\n      throw error;\n    }\n  }\n}\n"]}