@sphereon/did-auth-siop
Version:
Self Issued OpenID V2 (SIOPv2) and OpenID 4 Verifiable Presentations (OID4VP)
100 lines (89 loc) • 4.41 kB
text/typescript
import { PEX } from '@sphereon/pex'
import { getNonce, getWithUrl, removeNullUndefined } from '../helpers'
import { RequestObject } from '../request-object'
import { isTarget, isTargetOrNoTargets } from '../rp/Opts'
import { RPRegistrationMetadataPayloadSchema } from '../schemas'
import {
AuthorizationRequestPayload,
ClaimPayloadVID1,
ClientMetadataOpts,
PassBy,
RPRegistrationMetadataPayload,
SIOPErrors,
SupportedVersion,
} from '../types'
import { createRequestRegistration } from './RequestRegistration'
import { ClaimPayloadOptsVID1, CreateAuthorizationRequestOpts, PropertyTarget } from './types'
export const createPresentationDefinitionClaimsProperties = async (opts: ClaimPayloadOptsVID1): Promise<ClaimPayloadVID1> => {
if (
!opts ||
!opts.vp_token ||
(!opts.vp_token.presentation_definition && !opts.vp_token.presentation_definition_uri && !opts.vp_token.dcql_query)
) {
return undefined
}
let presentationDef = opts.vp_token.presentation_definition
if (!presentationDef && opts.vp_token.presentation_definition_uri) {
presentationDef = await getWithUrl(opts.vp_token.presentation_definition_uri, false)
}
if (presentationDef) {
const discoveryResult = PEX.definitionVersionDiscovery(presentationDef)
if (discoveryResult.error) {
return Promise.reject(new Error(SIOPErrors.REQUEST_CLAIMS_PRESENTATION_DEFINITION_NOT_VALID))
}
}
return {
...(opts.id_token ? { id_token: opts.id_token } : {}),
...((opts.vp_token.presentation_definition || opts.vp_token.presentation_definition_uri) && {
vp_token: {
...(!opts.vp_token.presentation_definition_uri && { presentation_definition: opts.vp_token.presentation_definition }),
...(opts.vp_token.presentation_definition_uri && { presentation_definition_uri: opts.vp_token.presentation_definition_uri }),
},
}),
...(opts.vp_token.dcql_query && { vp_token: { dcql_query: opts.vp_token.dcql_query } }),
}
}
export const createAuthorizationRequestPayload = async (
opts: CreateAuthorizationRequestOpts,
requestObject?: RequestObject,
): Promise<AuthorizationRequestPayload> => {
const payload = opts.payload
const state = payload?.state ?? undefined
const nonce = payload?.nonce ? getNonce(state, payload.nonce) : undefined
// TODO: if opts['registration] throw Error to get rid of test code using that key
const clientMetadata = opts['registration'] ?? (opts.clientMetadata as ClientMetadataOpts)
const registration = await createRequestRegistration(clientMetadata, opts)
const claims =
opts.version >= SupportedVersion.SIOPv2_ID1 ? opts.payload.claims : await createPresentationDefinitionClaimsProperties(opts.payload.claims)
const isRequestTarget = isTargetOrNoTargets(PropertyTarget.AUTHORIZATION_REQUEST, opts.requestObject.targets)
const isRequestByValue = opts.requestObject.passBy === PassBy.VALUE
if (isRequestTarget && isRequestByValue && !requestObject) {
throw Error(SIOPErrors.NO_JWT)
}
const request = isRequestByValue ? await requestObject.toJwt() : undefined
const authRequestPayload = {
...payload,
//TODO implement /.well-known/openid-federation support in the OP side to resolve the client_id (URL) and retrieve the metadata
...(clientMetadata.client_id && { client_id: clientMetadata.client_id }),
...(isRequestTarget && opts.requestObject.passBy === PassBy.REFERENCE ? { request_uri: opts.requestObject.reference_uri } : {}),
...(isRequestTarget && isRequestByValue && { request }),
...(nonce && { nonce }),
...(state && { state }),
...(registration.payload && isTarget(PropertyTarget.AUTHORIZATION_REQUEST, registration.clientMetadataOpts.targets) ? registration.payload : {}),
...(claims && { claims }),
}
return removeNullUndefined(authRequestPayload)
}
export const assertValidRPRegistrationMedataPayload = (regObj: RPRegistrationMetadataPayload) => {
if (regObj) {
const valid = RPRegistrationMetadataPayloadSchema(regObj)
if (!valid) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
throw new Error('Registration data validation error: ' + JSON.stringify(RPRegistrationMetadataPayloadSchema.errors))
}
}
if (regObj?.subject_syntax_types_supported && regObj.subject_syntax_types_supported.length == 0) {
throw new Error(`${SIOPErrors.VERIFY_BAD_PARAMS}`)
}
}