{"version":3,"file":"pushedAuthorizationRequestEndpoint.mjs","names":[],"sources":["../../../src/openid4vc-issuer/router/pushedAuthorizationRequestEndpoint.ts"],"sourcesContent":["import { AgentContext, joinUriParts, utils } from '@credo-ts/core'\nimport type { HttpMethod, ParsePushedAuthorizationRequestResult, RequestLike } from '@openid4vc/oauth2'\nimport {\n  Oauth2ErrorCodes,\n  Oauth2ServerErrorResponseError,\n  pushedAuthorizationRequestUriPrefix,\n} from '@openid4vc/oauth2'\nimport { addSecondsToDate } from '@openid4vc/utils'\nimport type { NextFunction, Response, Router } from 'express'\nimport type { OpenId4VciCredentialConfigurationsSupportedWithFormats } from '../../shared'\nimport {\n  getAllowedAndRequestedScopeValues,\n  getCredentialConfigurationsSupportedForScopes,\n  getOfferedCredentials,\n  getScopesFromCredentialConfigurationsSupported,\n} from '../../shared'\nimport {\n  getRequestContext,\n  sendJsonResponse,\n  sendOauth2ErrorResponse,\n  sendUnknownServerErrorResponse,\n} from '../../shared/router'\nimport { OpenId4VcIssuanceSessionState } from '../OpenId4VcIssuanceSessionState'\nimport { OpenId4VcIssuerModuleConfig } from '../OpenId4VcIssuerModuleConfig'\nimport { OpenId4VcIssuerService } from '../OpenId4VcIssuerService'\nimport { OpenId4VcIssuanceSessionRecord, OpenId4VcIssuerRecord } from '../repository'\nimport type { OpenId4VcIssuanceRequest } from './requestContext'\n\nexport async function handlePushedAuthorizationRequest(\n  agentContext: AgentContext,\n  options: {\n    issuer: OpenId4VcIssuerRecord\n    issuanceSession: OpenId4VcIssuanceSessionRecord\n    parsedAuthorizationRequest: ParsePushedAuthorizationRequestResult\n    request: RequestLike\n  }\n) {\n  const openId4VcIssuerService = agentContext.dependencyManager.resolve(OpenId4VcIssuerService)\n  const config = agentContext.dependencyManager.resolve(OpenId4VcIssuerModuleConfig)\n\n  const { issuanceSession, parsedAuthorizationRequest, issuer, request } = options\n  const issuerMetadata = await openId4VcIssuerService.getIssuerMetadata(agentContext, issuer)\n\n  if (!parsedAuthorizationRequest.authorizationRequest.scope) {\n    throw new Oauth2ServerErrorResponseError({\n      error: Oauth2ErrorCodes.InvalidScope,\n      error_description: `Missing required 'scope' parameter`,\n    })\n  }\n\n  if (!parsedAuthorizationRequest.authorizationRequest.redirect_uri) {\n    throw new Oauth2ServerErrorResponseError({\n      error: Oauth2ErrorCodes.InvalidScope,\n      error_description: `Missing required 'redirect_uri' parameter.`,\n    })\n  }\n\n  const allowedStates = [OpenId4VcIssuanceSessionState.OfferCreated, OpenId4VcIssuanceSessionState.OfferUriRetrieved]\n  if (!allowedStates.includes(issuanceSession.state)) {\n    throw new Oauth2ServerErrorResponseError(\n      {\n        error: Oauth2ErrorCodes.InvalidRequest,\n        error_description: `Invalid 'issuer_state' parameter`,\n      },\n      {\n        internalMessage: `Issuance session '${issuanceSession.id}' has state '${\n          issuanceSession.state\n        }' but expected one of ${allowedStates.join(', ')}`,\n      }\n    )\n  }\n\n  if (!issuanceSession.chainedIdentity?.externalAuthorizationServerUrl) {\n    throw new Oauth2ServerErrorResponseError(\n      {\n        error: Oauth2ErrorCodes.InvalidRequest,\n        error_description: `Unexpected redirect call for session.`,\n      },\n      {\n        internalMessage: `Issuance session '${issuanceSession.id}' is not configured to use chained identity for authorization.`,\n      }\n    )\n  }\n\n  const authorizationServer = openId4VcIssuerService.getOauth2AuthorizationServer(agentContext, {\n    issuanceSessionId: issuanceSession.id,\n  })\n\n  const { clientAttestation, dpop } = await authorizationServer.verifyPushedAuthorizationRequest({\n    authorizationRequest: parsedAuthorizationRequest.authorizationRequest,\n    // First authorization server is the internal authorization server\n    authorizationServerMetadata: issuerMetadata.authorizationServers[0],\n    request,\n    clientAttestation: {\n      ...parsedAuthorizationRequest.clientAttestation,\n      // First session config, fall back to global config\n      required: issuanceSession.walletAttestation?.required ?? config.walletAttestationsRequired,\n    },\n    dpop: {\n      ...parsedAuthorizationRequest.dpop,\n      // First session config, fall back to global config\n      required: issuanceSession.dpop?.required ?? config.dpopRequired,\n    },\n  })\n\n  if (dpop) {\n    // Bind dpop jwk thumbprint to session\n    issuanceSession.dpop = {\n      // If dpop is provided at the start, it's required from now on.\n      required: true,\n      dpopJkt: dpop.jwkThumbprint,\n    }\n  }\n\n  if (clientAttestation) {\n    issuanceSession.walletAttestation = {\n      // If client attestation is provided at the start, it's required from now on.\n      required: true,\n    }\n  }\n\n  const offeredCredentialConfigurations = getOfferedCredentials(\n    issuanceSession.credentialOfferPayload.credential_configuration_ids,\n    issuerMetadata.credentialIssuer.credential_configurations_supported\n  )\n  const allowedScopes = getScopesFromCredentialConfigurationsSupported(offeredCredentialConfigurations)\n  const requestedScopes = getAllowedAndRequestedScopeValues({\n    allowedScopes,\n    requestedScope: parsedAuthorizationRequest.authorizationRequest.scope,\n  })\n  const requestedCredentialConfigurations = getCredentialConfigurationsSupportedForScopes(\n    offeredCredentialConfigurations,\n    requestedScopes\n  ) as OpenId4VciCredentialConfigurationsSupportedWithFormats\n  if (requestedScopes.length === 0 || Object.keys(requestedCredentialConfigurations).length === 0) {\n    throw new Oauth2ServerErrorResponseError({\n      error: Oauth2ErrorCodes.InvalidScope,\n      error_description: `No requested 'scope' values match with offered credential configurations.`,\n    })\n  }\n\n  issuanceSession.authorization = {\n    ...issuanceSession.authorization,\n    scopes: requestedScopes,\n  }\n\n  // If client attestation is used we have verified this client_id matches with the sub\n  // of the wallet attestation\n  issuanceSession.clientId =\n    clientAttestation?.clientAttestation.payload.sub ?? parsedAuthorizationRequest.authorizationRequest.client_id\n\n  const oauth2Client = openId4VcIssuerService.getOauth2Client(agentContext, issuer)\n  const authorizationServerUrl = issuanceSession.chainedIdentity.externalAuthorizationServerUrl\n\n  const authorizationServerConfig = issuer.chainedAuthorizationServerConfigs?.find(\n    (config) => config.issuer === authorizationServerUrl\n  )\n  if (!authorizationServerConfig) {\n    throw new Oauth2ServerErrorResponseError(\n      {\n        error: Oauth2ErrorCodes.ServerError,\n      },\n      {\n        internalMessage: `Issuer '${issuer.issuerId}' does not have a chained authorization server config for issuer '${authorizationServerUrl}'`,\n      }\n    )\n  }\n\n  const authorizationServerMetadata = await oauth2Client.fetchAuthorizationServerMetadata(\n    authorizationServerConfig.issuer\n  )\n  if (!authorizationServerMetadata) {\n    throw new Oauth2ServerErrorResponseError(\n      {\n        error: Oauth2ErrorCodes.ServerError,\n        error_description: `Unable to retrieve authorization server metadata from external identity provider.`,\n      },\n      {\n        internalMessage: `Unable to retrieve authorization server metadata from '${authorizationServerConfig.issuer}'`,\n      }\n    )\n  }\n\n  const redirectUri = joinUriParts(config.baseUrl, [issuer.issuerId, 'redirect'])\n  const chainedIdentityState = utils.uuid()\n\n  let scopes: string[] = []\n  let additionalRequestPayload: Record<string, unknown> | undefined\n  let redirectUris: string[] | undefined = authorizationServerConfig.redirectUris\n\n  if (config.getChainedAuthorizationRequestParameters) {\n    const dynamicConfiguration = await config.getChainedAuthorizationRequestParameters({\n      agentContext,\n      issuanceSession,\n      chainedAuthorizationServerConfig: authorizationServerConfig,\n      requestedCredentialConfigurations,\n    })\n\n    scopes = dynamicConfiguration.scopes\n    additionalRequestPayload = dynamicConfiguration.additionalPayload\n    redirectUris = dynamicConfiguration.redirectUris\n  } else {\n    for (const scope of requestedScopes) {\n      if (!authorizationServerConfig.scopesMapping) {\n        throw new Oauth2ServerErrorResponseError(\n          {\n            error: Oauth2ErrorCodes.ServerError,\n          },\n          {\n            internalMessage: `Issuer '${issuer.issuerId}' does not have a scope mapping for scope '${scope}' for external authorization server '${authorizationServerConfig.issuer}'`,\n          }\n        )\n      }\n\n      if (scope in authorizationServerConfig.scopesMapping) {\n        scopes.push(...authorizationServerConfig.scopesMapping[scope])\n      } else {\n        throw new Oauth2ServerErrorResponseError(\n          {\n            error: Oauth2ErrorCodes.ServerError,\n          },\n          {\n            internalMessage: `Issuer '${issuer.issuerId}' does not have a scope mapping for scope '${scope}' for external authorization server '${authorizationServerConfig.issuer}'`,\n          }\n        )\n      }\n    }\n  }\n\n  if (redirectUris && !redirectUris.includes(parsedAuthorizationRequest.authorizationRequest.redirect_uri)) {\n    throw new Oauth2ServerErrorResponseError(\n      {\n        error: Oauth2ErrorCodes.InvalidRequest,\n        error_description: `Invalid 'redirect_uri' parameter.`,\n      },\n      {\n        internalMessage: `Redirect URI '${parsedAuthorizationRequest.authorizationRequest.redirect_uri}' is not allowed for external authorization server '${authorizationServerConfig.issuer}'`,\n      }\n    )\n  }\n\n  // TODO: add support for DPoP\n  const { authorizationRequestUrl, pkce } = await oauth2Client.initiateAuthorization({\n    authorizationServerMetadata,\n    clientId: authorizationServerConfig.clientAuthentication.clientId,\n    redirectUri,\n    state: chainedIdentityState,\n    scope: scopes.join(' '),\n    additionalRequestPayload,\n  })\n\n  issuanceSession.chainedIdentity = {\n    ...issuanceSession.chainedIdentity,\n    requestUriReferenceValue: utils.uuid(),\n    externalAuthorizationRequestUrl: authorizationRequestUrl,\n    requestUriExpiresAt: addSecondsToDate(new Date(), config.requestUriExpiresInSeconds),\n    pkceCodeVerifier: pkce?.codeVerifier,\n    externalState: chainedIdentityState,\n    state: parsedAuthorizationRequest.authorizationRequest.state,\n    redirectUri: parsedAuthorizationRequest.authorizationRequest.redirect_uri,\n    externalAuthorizationServerMetadata: authorizationServerMetadata,\n  }\n\n  const { pushedAuthorizationResponse } = authorizationServer.createPushedAuthorizationResponse({\n    expiresInSeconds: config.requestUriExpiresInSeconds,\n    requestUri: pushedAuthorizationRequestUriPrefix + issuanceSession.chainedIdentity.requestUriReferenceValue,\n  })\n\n  await openId4VcIssuerService.updateState(\n    agentContext,\n    issuanceSession,\n    OpenId4VcIssuanceSessionState.AuthorizationInitiated\n  )\n\n  return { pushedAuthorizationResponse }\n}\n\nexport function configurePushedAuthorizationRequestEndpoint(router: Router, config: OpenId4VcIssuerModuleConfig) {\n  router.post(\n    config.pushedAuthorizationRequestEndpoint,\n    async (request: OpenId4VcIssuanceRequest, response: Response, next: NextFunction) => {\n      const requestContext = getRequestContext(request)\n      const { agentContext, issuer } = requestContext\n\n      try {\n        const config = agentContext.dependencyManager.resolve(OpenId4VcIssuerModuleConfig)\n        const openId4VcIssuerService = agentContext.dependencyManager.resolve(OpenId4VcIssuerService)\n        const issuerMetadata = await openId4VcIssuerService.getIssuerMetadata(agentContext, issuer)\n        const authorizationServer = openId4VcIssuerService.getOauth2AuthorizationServer(agentContext)\n        const fullRequestUrl = joinUriParts(issuerMetadata.credentialIssuer.credential_issuer, [\n          config.pushedAuthorizationRequestEndpoint,\n        ])\n\n        const requestLike = {\n          headers: new Headers(request.headers as Record<string, string>),\n          method: request.method as HttpMethod,\n          url: fullRequestUrl,\n        } as const\n\n        const parseResult = await authorizationServer.parsePushedAuthorizationRequest({\n          authorizationRequest: request.body,\n          request: requestLike,\n        })\n\n        if (parseResult.authorizationRequestJwt) {\n          throw new Oauth2ServerErrorResponseError({\n            error: Oauth2ErrorCodes.InvalidRequest,\n            error_description: `Using JWT-secured authorization request is not supported.`,\n          })\n        }\n\n        // TODO: we could allow dynamic issuance sessions here. Maybe based on a callback?\n        // Not sure how to decide which credentials are allowed to be requested dynamically\n        if (!parseResult.authorizationRequest.issuer_state) {\n          throw new Oauth2ServerErrorResponseError({\n            error: Oauth2ErrorCodes.InvalidRequest,\n            error_description: `Missing required 'issuer_state' parameter. Only requests initiated by a credential offer are supported for pushed authorization requests.`,\n          })\n        }\n\n        if (!parseResult.authorizationRequest.scope) {\n          throw new Oauth2ServerErrorResponseError({\n            error: Oauth2ErrorCodes.InvalidScope,\n            error_description: `Missing required 'scope' parameter`,\n          })\n        }\n\n        const issuanceSession = await openId4VcIssuerService.findSingleIssuanceSessionByQuery(agentContext, {\n          issuerId: issuer.issuerId,\n          issuerState: parseResult.authorizationRequest.issuer_state,\n        })\n\n        if (!issuanceSession) {\n          throw new Oauth2ServerErrorResponseError(\n            {\n              error: Oauth2ErrorCodes.InvalidRequest,\n              error_description: `Invalid 'issuer_state' parameter`,\n            },\n            {\n              internalMessage: `Issuance session not found for 'issuer_state' parameter '${parseResult.authorizationRequest.issuer_state}'`,\n            }\n          )\n        }\n\n        const { pushedAuthorizationResponse } = await handlePushedAuthorizationRequest(agentContext, {\n          issuanceSession,\n          issuer,\n          parsedAuthorizationRequest: parseResult,\n          request: requestLike,\n        })\n\n        return sendJsonResponse(response, next, pushedAuthorizationResponse)\n      } catch (error) {\n        if (error instanceof Oauth2ServerErrorResponseError) {\n          return sendOauth2ErrorResponse(response, next, agentContext.config.logger, error)\n        }\n        return sendUnknownServerErrorResponse(response, next, agentContext.config.logger, error)\n      }\n    }\n  )\n}\n"],"mappings":"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"}