UNPKG

@sphereon/did-auth-siop

Version:

Self Issued OpenID V2 (SIOPv2) and OpenID 4 Verifiable Presentations (OID4VP)

950 lines (882 loc) 104 kB
import { EventEmitter } from 'events' import { SigningAlgo } from '@sphereon/oid4vc-common' import { IPresentationDefinition } from '@sphereon/pex' import { CredentialMapper, IPresentation, IProofType, IVerifiableCredential, W3CVerifiablePresentation } from '@sphereon/ssi-types' // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore import nock from 'nock' import { InMemoryRPSessionManager } from '..' import { OP, PassBy, PresentationDefinitionWithLocation, PresentationExchange, PresentationSignCallback, PresentationVerificationCallback, PropertyTarget, ResponseIss, ResponseType, RevocationStatus, RevocationVerification, RP, Scope, SubjectType, SupportedVersion, verifyRevocation, VPTokenLocation, } from '../' import { checkSIOPSpecVersionSupported } from '../helpers/SIOPSpecVersion' import { getVerifyJwtCallback, internalSignature } from './DidJwtTestUtils' import { getResolver } from './ResolverTestUtils' import { mockedGetEnterpriseAuthToken, WELL_KNOWN_OPENID_FEDERATION } from './TestUtils' import { UNIT_TEST_TIMEOUT, VERIFIER_LOGO_FOR_CLIENT, VERIFIER_NAME_FOR_CLIENT, VERIFIER_NAME_FOR_CLIENT_NL, VERIFIERZ_PURPOSE_TO_VERIFY, VERIFIERZ_PURPOSE_TO_VERIFY_NL, } from './data/mockedData' jest.setTimeout(30000) const EXAMPLE_REDIRECT_URL = 'https://acme.com/hello' const EXAMPLE_REFERENCE_URL = 'https://rp.acme.com/siop/jwts' const HOLDER_DID = 'did:example:ebfeb1f712ebc6f1c276e12ec21' const presentationSignCallback: PresentationSignCallback = async (_args) => ({ ...(_args.presentation as IPresentation), proof: { type: 'RsaSignature2018', created: '2018-09-14T21:19:10Z', proofPurpose: 'authentication', verificationMethod: 'did:example:ebfeb1f712ebc6f1c276e12ec21#keys-1', nonce: 'qBrR7mqnY3Qr49dAZycPF8FzgE83m6H0c2l0bzP4xSg', challenge: '1f44d55f-f161-4938-a659-f8026467f126', domain: '4jt78h47fh47', jws: 'eyJhbGciOiJSUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..kTCYt5XsITJX1CxPCT8yAV-TVIw5WEuts01mq-pQy7UJiN5mgREEMGlv50aqzpqh4Qq_PbChOMqsLfRoPsnsgxD-WUcX16dUOqV0G_zS245-kronKb78cPktb3rk-BuQy72IFLN25DYuNzVBAh4vGHSrQyHUGlcTwLtjPAnKb78', }, }) // eslint-disable-next-line @typescript-eslint/no-unused-vars const presentationVerificationCallback: PresentationVerificationCallback = async (_args: W3CVerifiablePresentation) => ({ verified: true, }) function getPresentationDefinition(): IPresentationDefinition { return { id: 'Insurance Plans', input_descriptors: [ { id: 'Ontario Health Insurance Plan', schema: [ { uri: 'https://did.itsourweb.org:3000/smartcredential/Ontario-Health-Insurance-Plan', }, { uri: 'https://www.w3.org/2018/credentials/v1', }, ], constraints: { limit_disclosure: 'preferred', fields: [ { path: ['$.issuer.id'], purpose: 'We can only verify bank accounts if they are attested by a source.', filter: { type: 'string', pattern: 'did:example:issuer', }, }, ], }, }, ], } } function getVCs(): IVerifiableCredential[] { const vcs: IVerifiableCredential[] = [ { identifier: '83627465', name: 'Permanent Resident Card', type: ['PermanentResidentCard', 'VerifiableCredential'], id: 'https://issuer.oidp.uscis.gov/credentials/83627465dsdsdsd', credentialSubject: { birthCountry: 'Bahamas', id: 'did:example:b34ca6cd37bbf23', type: ['PermanentResident', 'Person'], gender: 'Female', familyName: 'SMITH', givenName: 'JANE', residentSince: '2015-01-01', lprNumber: '999-999-999', birthDate: '1958-07-17', commuterClassification: 'C1', lprCategory: 'C09', image: 'data:image/png;base64,iVBORw0KGgokJggg==', }, expirationDate: '2029-12-03T12:19:52Z', description: 'Government of Example Permanent Resident Card.', issuanceDate: '2019-12-03T12:19:52Z', '@context': ['https://www.w3.org/2018/credentials/v1', 'https://w3id.org/citizenship/v1', 'https://w3id.org/security/suites/ed25519-2020/v1'], issuer: 'did:key:z6MkhfRoL9n7ko9d6LnB5jLB4aejd3ir2q6E2xkuzKUYESig', proof: { type: 'BbsBlsSignatureProof2020', created: '2020-04-25', verificationMethod: 'did:example:489398593#test', proofPurpose: 'assertionMethod', proofValue: 'kTTbA3pmDa6Qia/JkOnIXDLmoBz3vsi7L5t3DWySI/VLmBqleJ/Tbus5RoyiDERDBEh5rnACXlnOqJ/U8yFQFtcp/mBCc2FtKNPHae9jKIv1dm9K9QK1F3GI1AwyGoUfjLWrkGDObO1ouNAhpEd0+et+qiOf2j8p3MTTtRRx4Hgjcl0jXCq7C7R5/nLpgimHAAAAdAx4ouhMk7v9dXijCIMaG0deicn6fLoq3GcNHuH5X1j22LU/hDu7vvPnk/6JLkZ1xQAAAAIPd1tu598L/K3NSy0zOy6obaojEnaqc1R5Ih/6ZZgfEln2a6tuUp4wePExI1DGHqwj3j2lKg31a/6bSs7SMecHBQdgIYHnBmCYGNQnu/LZ9TFV56tBXY6YOWZgFzgLDrApnrFpixEACM9rwrJ5ORtxAAAAAgE4gUIIC9aHyJNa5TBklMOh6lvQkMVLXa/vEl+3NCLXblxjgpM7UEMqBkE9/QcoD3Tgmy+z0hN+4eky1RnJsEg=', nonce: '6i3dTz5yFfWJ8zgsamuyZa4yAHPm75tUOOXddR6krCvCYk77sbCOuEVcdBCDd/l6tIY=', }, }, ] vcs[0]['@context'] = ['https://www.w3.org/2018/credentials/v1', 'https://www.w3.org/2018/credentials/examples/v1'] vcs[0]['issuer'] = { id: 'did:example:issuer', } return vcs } describe.skip('RP and OP interaction should', () => { // FIXME SDK-45 Uniresolver failing it( 'succeed when calling each other in the full flow', async () => { // expect.assertions(1); const rpMockEntity = await mockedGetEnterpriseAuthToken('ACME RP') const opMockEntity = await mockedGetEnterpriseAuthToken('ACME OP') // eslint-disable-next-line @typescript-eslint/no-unused-vars const presentationVerificationCallback: PresentationVerificationCallback = async (_args) => ({ verified: true }) const resolver = getResolver(['ethr']) const eventEmitter = new EventEmitter() const replayRegistry = new InMemoryRPSessionManager(eventEmitter) const rp = RP.builder({ requestVersion: SupportedVersion.SIOPv2_ID1 }) .withEventEmitter(eventEmitter) .withSessionManager(replayRegistry) .withClientId(rpMockEntity.did) .withScope('test') .withResponseType(ResponseType.ID_TOKEN) .withRedirectUri(EXAMPLE_REDIRECT_URL) .withPresentationVerification(presentationVerificationCallback) .withRevocationVerification(RevocationVerification.NEVER) .withRequestBy(PassBy.REFERENCE, EXAMPLE_REFERENCE_URL) .withIssuer(ResponseIss.SELF_ISSUED_V2) .withVerifyJwtCallback(getVerifyJwtCallback(resolver)) .withCreateJwtCallback(internalSignature(rpMockEntity.hexPrivateKey, rpMockEntity.did, `${rpMockEntity.did}#controller`, SigningAlgo.ES256K)) .withClientMetadata({ client_id: WELL_KNOWN_OPENID_FEDERATION, idTokenSigningAlgValuesSupported: [SigningAlgo.EDDSA], requestObjectSigningAlgValuesSupported: [SigningAlgo.EDDSA, SigningAlgo.ES256], responseTypesSupported: [ResponseType.ID_TOKEN], vpFormatsSupported: { jwt_vc: { alg: [SigningAlgo.EDDSA] } }, scopesSupported: [Scope.OPENID_DIDAUTHN, Scope.OPENID], subjectTypesSupported: [SubjectType.PAIRWISE], subject_syntax_types_supported: ['did', 'did:ethr'], passBy: PassBy.VALUE, logo_uri: VERIFIER_LOGO_FOR_CLIENT, clientName: VERIFIER_NAME_FOR_CLIENT, 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100317', clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, }) .withSupportedVersions([SupportedVersion.SIOPv2_ID1]) .build() const op = OP.builder() .withPresentationSignCallback(presentationSignCallback) .withExpiresIn(1000) .withIssuer(ResponseIss.SELF_ISSUED_V2) .withVerifyJwtCallback(getVerifyJwtCallback(resolver)) .withCreateJwtCallback(internalSignature(opMockEntity.hexPrivateKey, opMockEntity.did, `${opMockEntity.did}#controller`, SigningAlgo.ES256K)) .withSupportedVersions(SupportedVersion.SIOPv2_ID1) //FIXME: Move payload options to seperate property .withRegistration({ authorizationEndpoint: 'www.myauthorizationendpoint.com', idTokenSigningAlgValuesSupported: [SigningAlgo.EDDSA], issuer: ResponseIss.SELF_ISSUED_V2, requestObjectSigningAlgValuesSupported: [SigningAlgo.EDDSA, SigningAlgo.ES256], responseTypesSupported: [ResponseType.ID_TOKEN], vpFormats: { jwt_vc: { alg: [SigningAlgo.EDDSA] } }, scopesSupported: [Scope.OPENID_DIDAUTHN, Scope.OPENID], subjectTypesSupported: [SubjectType.PAIRWISE], subject_syntax_types_supported: ['did:ethr'], passBy: PassBy.VALUE, logo_uri: VERIFIER_LOGO_FOR_CLIENT, clientName: VERIFIER_NAME_FOR_CLIENT, 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100318', clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, }) .withSupportedVersions(SupportedVersion.SIOPv2_ID1) .build() const requestURI = await rp.createAuthorizationRequestURI({ correlationId: '1234', nonce: { propertyValue: 'qBrR7mqnY3Qr49dAZycPF8FzgE83m6H0c2l0bzP4xSg' }, state: { propertyValue: 'b32f0087fc9816eb813fd11f' }, }) nock('https://rp.acme.com').get('/siop/jwts').times(3).reply(200, requestURI.requestObjectJwt) if (!op.verifyRequestOptions.supportedVersions) throw new Error('Supported versions not set') await checkSIOPSpecVersionSupported(requestURI.authorizationRequestPayload, op.verifyRequestOptions.supportedVersions) // The create method also calls the verifyRequest method, so no need to do it manually const verifiedRequest = await op.verifyAuthorizationRequest(requestURI.encodedUri) const authenticationResponseWithJWT = await op.createAuthorizationResponse(verifiedRequest, {}) nock(EXAMPLE_REDIRECT_URL).post(/.*/).times(3).reply(200, { result: 'ok' }) const response = await op.submitAuthorizationResponse(authenticationResponseWithJWT) await expect(response.json()).resolves.toMatchObject({ result: 'ok' }) const verifiedAuthResponseWithJWT = await rp.verifyAuthorizationResponse(authenticationResponseWithJWT.response.payload, { // audience: EXAMPLE_REDIRECT_URL, }) expect(verifiedAuthResponseWithJWT.idToken?.jwt).toBeDefined() expect(verifiedAuthResponseWithJWT.idToken?.payload.nonce).toMatch('qBrR7mqnY3Qr49dAZycPF8FzgE83m6H0c2l0bzP4xSg') }, UNIT_TEST_TIMEOUT, ) it('succeed when calling optional steps in the full flow', async () => { const opMock = await mockedGetEnterpriseAuthToken('OP') const opMockEntity = { ...opMock, didKey: `${opMock.did}#controller`, } const rpMock = await mockedGetEnterpriseAuthToken('RP') const rpMockEntity = { ...rpMock, didKey: `${rpMock.did}#controller`, } // eslint-disable-next-line @typescript-eslint/no-unused-vars const presentationVerificationCallback: PresentationVerificationCallback = async (_args) => ({ verified: true }) const resolver = getResolver('ethr') const eventEmitter = new EventEmitter() const replayRegistry = new InMemoryRPSessionManager(eventEmitter) const rp = RP.builder({ requestVersion: SupportedVersion.SIOPv2_ID1 }) .withEventEmitter(eventEmitter) .withSessionManager(replayRegistry) .withClientId(rpMockEntity.did) .withScope('test') .withResponseType(ResponseType.ID_TOKEN) .withRedirectUri(EXAMPLE_REDIRECT_URL) .withPresentationVerification(presentationVerificationCallback) .withRevocationVerification(RevocationVerification.NEVER) .withRequestBy(PassBy.VALUE) .withCreateJwtCallback(internalSignature(rpMockEntity.hexPrivateKey, rpMockEntity.did, rpMockEntity.didKey, SigningAlgo.ES256K)) .withVerifyJwtCallback(getVerifyJwtCallback(resolver)) .withClientMetadata({ client_id: WELL_KNOWN_OPENID_FEDERATION, idTokenSigningAlgValuesSupported: [SigningAlgo.EDDSA], requestObjectSigningAlgValuesSupported: [SigningAlgo.EDDSA, SigningAlgo.ES256], responseTypesSupported: [ResponseType.ID_TOKEN], vpFormatsSupported: { jwt_vc: { alg: [SigningAlgo.EDDSA] } }, scopesSupported: [Scope.OPENID_DIDAUTHN, Scope.OPENID], subjectTypesSupported: [SubjectType.PAIRWISE], subject_syntax_types_supported: ['did', 'did:ethr'], passBy: PassBy.VALUE, logo_uri: VERIFIER_LOGO_FOR_CLIENT, clientName: VERIFIER_NAME_FOR_CLIENT, 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100319', clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, }) .withSupportedVersions(SupportedVersion.SIOPv2_ID1) .build() const op = OP.builder() .withExpiresIn(1000) .withVerifyJwtCallback(getVerifyJwtCallback(resolver)) .withCreateJwtCallback(internalSignature(opMockEntity.hexPrivateKey, opMockEntity.did, opMockEntity.didKey, SigningAlgo.ES256K)) .withRegistration({ authorizationEndpoint: 'www.myauthorizationendpoint.com', idTokenSigningAlgValuesSupported: [SigningAlgo.EDDSA], issuer: ResponseIss.SELF_ISSUED_V2, requestObjectSigningAlgValuesSupported: [SigningAlgo.EDDSA, SigningAlgo.ES256], responseTypesSupported: [ResponseType.ID_TOKEN], vpFormats: { jwt_vc: { alg: [SigningAlgo.EDDSA] } }, scopesSupported: [Scope.OPENID_DIDAUTHN, Scope.OPENID], subjectTypesSupported: [SubjectType.PAIRWISE], subject_syntax_types_supported: [], passBy: PassBy.VALUE, logo_uri: VERIFIER_LOGO_FOR_CLIENT, clientName: VERIFIER_NAME_FOR_CLIENT, 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100320', clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, }) .withSupportedVersions(SupportedVersion.SIOPv2_ID1) .build() const requestURI = await rp.createAuthorizationRequestURI({ correlationId: '1234', nonce: { propertyValue: 'qBrR7mqnY3Qr49dAZycPF8FzgE83m6H0c2l0bzP4xSg' }, state: { propertyValue: 'b32f0087fc9816eb813fd11f' }, }) // Let's test the parsing const parsedAuthReqURI = await op.parseAuthorizationRequestURI(requestURI.encodedUri) expect(parsedAuthReqURI.authorizationRequestPayload).toBeDefined() expect(parsedAuthReqURI.requestObjectJwt).toBeDefined() if (!op.verifyRequestOptions.supportedVersions) throw new Error('Supported versions not set') if (!parsedAuthReqURI.requestObjectJwt) throw new Error('Request object JWT not found') const verifiedAuthReqWithJWT = await op.verifyAuthorizationRequest(parsedAuthReqURI.requestObjectJwt, { correlationId: '1234' }) expect(verifiedAuthReqWithJWT.issuer).toMatch(rpMockEntity.did) const authenticationResponseWithJWT = await op.createAuthorizationResponse(verifiedAuthReqWithJWT, {}) expect(authenticationResponseWithJWT).toBeDefined() expect(authenticationResponseWithJWT.correlationId).toEqual('1234') expect(authenticationResponseWithJWT.response.payload).toBeDefined() expect(authenticationResponseWithJWT.response.idToken).toBeDefined() const verifiedAuthResponseWithJWT = await rp.verifyAuthorizationResponse(authenticationResponseWithJWT.response.payload, { /*audience: EXAMPLE_REDIRECT_URL,*/ }) expect(verifiedAuthResponseWithJWT.idToken?.jwt).toBeDefined() expect(verifiedAuthResponseWithJWT.idToken?.payload.nonce).toMatch('qBrR7mqnY3Qr49dAZycPF8FzgE83m6H0c2l0bzP4xSg') }) it('fail when calling with presentation definitions and without verifiable presentation', async () => { const opMock = await mockedGetEnterpriseAuthToken('OP') const opMockEntity = { ...opMock, didKey: `${opMock.did}#controller`, } const rpMock = await mockedGetEnterpriseAuthToken('RP') const rpMockEntity = { ...rpMock, didKey: `${rpMock.did}#controller`, } // eslint-disable-next-line @typescript-eslint/no-unused-vars const presentationVerificationCallback: PresentationVerificationCallback = async (_args) => ({ verified: true }) const resolver = getResolver('ethr') const rp = RP.builder({ requestVersion: SupportedVersion.SIOPv2_ID1 }) .withClientId(WELL_KNOWN_OPENID_FEDERATION) .withScope('test') .withResponseType([ResponseType.ID_TOKEN, ResponseType.VP_TOKEN]) .withRedirectUri(EXAMPLE_REDIRECT_URL) .withPresentationVerification(presentationVerificationCallback) .withRevocationVerification(RevocationVerification.NEVER) .withRequestBy(PassBy.VALUE) .withCreateJwtCallback(internalSignature(rpMockEntity.hexPrivateKey, rpMockEntity.did, rpMockEntity.didKey, SigningAlgo.ES256K)) .withClientMetadata({ client_id: rpMockEntity.did, idTokenSigningAlgValuesSupported: [SigningAlgo.EDDSA], requestObjectSigningAlgValuesSupported: [SigningAlgo.EDDSA, SigningAlgo.ES256], responseTypesSupported: [ResponseType.ID_TOKEN, ResponseType.VP_TOKEN], vpFormatsSupported: { jwt_vc: { alg: [SigningAlgo.EDDSA] } }, scopesSupported: [Scope.OPENID_DIDAUTHN, Scope.OPENID], subjectTypesSupported: [SubjectType.PAIRWISE], subject_syntax_types_supported: ['did', 'did:ethr'], passBy: PassBy.VALUE, logo_uri: VERIFIER_LOGO_FOR_CLIENT, clientName: VERIFIER_NAME_FOR_CLIENT, 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100321', clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, }) .withPresentationDefinition({ definition: getPresentationDefinition() }) .withSupportedVersions(SupportedVersion.SIOPv2_ID1) .build() const op = OP.builder() .withExpiresIn(1000) .withVerifyJwtCallback(getVerifyJwtCallback(resolver)) .withCreateJwtCallback(internalSignature(opMockEntity.hexPrivateKey, opMockEntity.did, opMockEntity.didKey, SigningAlgo.ES256K)) .withRegistration({ authorizationEndpoint: 'www.myauthorizationendpoint.com', idTokenSigningAlgValuesSupported: [SigningAlgo.EDDSA], issuer: ResponseIss.SELF_ISSUED_V2, requestObjectSigningAlgValuesSupported: [SigningAlgo.EDDSA, SigningAlgo.ES256K], responseTypesSupported: [ResponseType.ID_TOKEN], vpFormats: { jwt_vc: { alg: [SigningAlgo.EDDSA] } }, scopesSupported: [Scope.OPENID_DIDAUTHN, Scope.OPENID], subjectTypesSupported: [SubjectType.PAIRWISE], subject_syntax_types_supported: [], passBy: PassBy.VALUE, logo_uri: VERIFIER_LOGO_FOR_CLIENT, clientName: VERIFIER_NAME_FOR_CLIENT, 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100321', clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, }) .withSupportedVersions(SupportedVersion.SIOPv2_ID1) .build() const requestURI = await rp.createAuthorizationRequestURI({ correlationId: '1234', nonce: { propertyValue: 'qBrR7mqnY3Qr49dAZycPF8FzgE83m6H0c2l0bzP4xSg' }, state: { propertyValue: 'b32f0087fc9816eb813fd11f' }, }) //The schema validation needs to be done here otherwise it fails because of JWT properties if (!op.verifyRequestOptions.supportedVersions) throw new Error('Supported versions not set') await checkSIOPSpecVersionSupported(requestURI.authorizationRequestPayload, op.verifyRequestOptions.supportedVersions) // Let's test the parsing const parsedAuthReqURI = await op.parseAuthorizationRequestURI(requestURI.encodedUri) expect(parsedAuthReqURI.authorizationRequestPayload).toBeDefined() expect(parsedAuthReqURI.requestObjectJwt).toBeDefined() // expect(parsedAuthReqURI.registration).toBeDefined(); if (!parsedAuthReqURI.requestObjectJwt) throw new Error('Request object JWT not found') const verifiedAuthReqWithJWT = await op.verifyAuthorizationRequest(parsedAuthReqURI.requestObjectJwt) expect(verifiedAuthReqWithJWT.issuer).toMatch(rpMockEntity.did) await expect(op.createAuthorizationResponse(verifiedAuthReqWithJWT, {})).rejects.toThrow( Error('vp_token is present, but no presentation definitions or dcql query provided'), ) expect(verifiedAuthReqWithJWT.payload?.['registration'].client_name).toEqual(VERIFIER_NAME_FOR_CLIENT) expect(verifiedAuthReqWithJWT.payload?.['registration']['client_name#nl-NL']).toEqual(VERIFIER_NAME_FOR_CLIENT_NL + '2022100321') }) it('succeed when calling with presentation definitions and right verifiable presentation', async () => { const opMock = await mockedGetEnterpriseAuthToken('OP') const opMockEntity = { ...opMock, didKey: `${opMock.did}#controller`, } const rpMock = await mockedGetEnterpriseAuthToken('RP') const rpMockEntity = { ...rpMock, didKey: `${rpMock.did}#controller`, } // eslint-disable-next-line @typescript-eslint/no-unused-vars const presentationVerificationCallback: PresentationVerificationCallback = async (_args) => ({ verified: true }) const resolver = getResolver('ethr') const eventEmitter = new EventEmitter() const replayRegistry = new InMemoryRPSessionManager(eventEmitter) const rp = RP.builder({ requestVersion: SupportedVersion.SIOPv2_ID1 }) .withEventEmitter(eventEmitter) .withSessionManager(replayRegistry) .withClientId(rpMockEntity.did) .withScope('test') .withResponseType([ResponseType.ID_TOKEN, ResponseType.VP_TOKEN]) .withRedirectUri(EXAMPLE_REDIRECT_URL) .withPresentationDefinition({ definition: getPresentationDefinition() }, [PropertyTarget.REQUEST_OBJECT, PropertyTarget.AUTHORIZATION_REQUEST]) .withPresentationVerification(presentationVerificationCallback) .withRevocationVerification(RevocationVerification.NEVER) .withRequestBy(PassBy.VALUE) .withCreateJwtCallback(internalSignature(rpMockEntity.hexPrivateKey, rpMockEntity.did, rpMockEntity.didKey, SigningAlgo.ES256K)) .withVerifyJwtCallback(getVerifyJwtCallback(resolver)) .withAuthorizationEndpoint('www.myauthorizationendpoint.com') .withClientMetadata({ client_id: WELL_KNOWN_OPENID_FEDERATION, idTokenSigningAlgValuesSupported: [SigningAlgo.EDDSA], requestObjectSigningAlgValuesSupported: [SigningAlgo.EDDSA, SigningAlgo.ES256], responseTypesSupported: [ResponseType.ID_TOKEN], vpFormatsSupported: { jwt_vc: { alg: [SigningAlgo.EDDSA] } }, scopesSupported: [Scope.OPENID_DIDAUTHN, Scope.OPENID], subjectTypesSupported: [SubjectType.PAIRWISE], subject_syntax_types_supported: ['did', 'did:ethr'], passBy: PassBy.VALUE, logo_uri: VERIFIER_LOGO_FOR_CLIENT, clientName: VERIFIER_NAME_FOR_CLIENT, 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100322', clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, }) .withSupportedVersions(SupportedVersion.SIOPv2_ID1) .build() const op = OP.builder() .withPresentationSignCallback(presentationSignCallback) .withExpiresIn(1000) .withVerifyJwtCallback(getVerifyJwtCallback(resolver)) .withCreateJwtCallback(internalSignature(opMockEntity.hexPrivateKey, opMockEntity.did, opMockEntity.didKey, SigningAlgo.ES256K)) .withRegistration({ authorizationEndpoint: 'www.myauthorizationendpoint.com', idTokenSigningAlgValuesSupported: [SigningAlgo.EDDSA], issuer: ResponseIss.SELF_ISSUED_V2, requestObjectSigningAlgValuesSupported: [SigningAlgo.EDDSA, SigningAlgo.ES256], responseTypesSupported: [ResponseType.ID_TOKEN, ResponseType.VP_TOKEN], vpFormats: { jwt_vc: { alg: [SigningAlgo.EDDSA] } }, scopesSupported: [Scope.OPENID_DIDAUTHN, Scope.OPENID], subjectTypesSupported: [SubjectType.PAIRWISE], subject_syntax_types_supported: [], passBy: PassBy.VALUE, logo_uri: VERIFIER_LOGO_FOR_CLIENT, clientName: VERIFIER_NAME_FOR_CLIENT, 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100323', clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, }) .withSupportedVersions(SupportedVersion.SIOPv2_ID1) .build() const requestURI = await rp.createAuthorizationRequestURI({ correlationId: '1234', nonce: 'qBrR7mqnY3Qr49dAZycPF8FzgE83m6H0c2l0bzP4xSg', state: 'b32f0087fc9816eb813fd11f', }) // Let's test the parsing const parsedAuthReqURI = await op.parseAuthorizationRequestURI(requestURI.encodedUri) expect(parsedAuthReqURI.authorizationRequestPayload).toBeDefined() expect(parsedAuthReqURI.requestObjectJwt).toBeDefined() // expect(parsedAuthReqURI.registration).toBeDefined(); if (!parsedAuthReqURI.requestObjectJwt) throw new Error('Supported versions not set') const verifiedAuthReqWithJWT = await op.verifyAuthorizationRequest(parsedAuthReqURI.requestObjectJwt) expect(verifiedAuthReqWithJWT.issuer).toMatch(rpMockEntity.did) const pex = new PresentationExchange({ allDIDs: [HOLDER_DID], allVerifiableCredentials: getVCs() }) const pd: PresentationDefinitionWithLocation[] = await PresentationExchange.findValidPresentationDefinitions( parsedAuthReqURI.authorizationRequestPayload, ) await pex.selectVerifiableCredentialsForSubmission(pd[0].definition) const verifiablePresentationResult = await pex.createVerifiablePresentation(pd[0].definition, getVCs(), presentationSignCallback, {}) const authenticationResponseWithJWT = await op.createAuthorizationResponse(verifiedAuthReqWithJWT, { presentationExchange: { verifiablePresentations: verifiablePresentationResult.verifiablePresentations, vpTokenLocation: VPTokenLocation.AUTHORIZATION_RESPONSE, presentationSubmission: verifiablePresentationResult.presentationSubmission, /*credentialsAndDefinitions: [ { presentation: vp, format: VerifiablePresentationTypeFormat.LDP_VP, vpTokenLocation: VPTokenLocation.AUTHORIZATION_RESPONSE, }, ],*/ }, }) expect(authenticationResponseWithJWT.response.payload).toBeDefined() expect(authenticationResponseWithJWT.response.idToken).toBeDefined() const verifiedAuthResponseWithJWT = await rp.verifyAuthorizationResponse(authenticationResponseWithJWT.response.payload, { /*audience: EXAMPLE_REDIRECT_URL,*/ presentationDefinitions: [{ definition: pd[0].definition, location: pd[0].location }], }) expect(verifiedAuthResponseWithJWT.idToken?.jwt).toBeDefined() expect(verifiedAuthResponseWithJWT.idToken?.payload.nonce).toMatch('qBrR7mqnY3Qr49dAZycPF8FzgE83m6H0c2l0bzP4xSg') }) it('succeed when calling with RevocationVerification.ALWAYS with ldp_vp', async () => { const opMock = await mockedGetEnterpriseAuthToken('OP') const opMockEntity = { ...opMock, didKey: `${opMock.did}#controller`, } const rpMock = await mockedGetEnterpriseAuthToken('RP') const rpMockEntity = { ...rpMock, didKey: `${rpMock.did}#controller`, } // eslint-disable-next-line @typescript-eslint/no-unused-vars const presentationVerificationCallback: PresentationVerificationCallback = async (_args) => ({ verified: true }) const resolver = getResolver('ethr') const eventEmitter = new EventEmitter() const replayRegistry = new InMemoryRPSessionManager(eventEmitter) const rp = RP.builder({ requestVersion: SupportedVersion.SIOPv2_ID1 }) .withEventEmitter(eventEmitter) .withSessionManager(replayRegistry) .withClientId('test_client_id') .withScope('test') .withResponseType([ResponseType.VP_TOKEN, ResponseType.ID_TOKEN]) .withRevocationVerification(RevocationVerification.ALWAYS) .withPresentationVerification(presentationVerificationCallback) .withRevocationVerificationCallback(async () => { return { status: RevocationStatus.VALID } }) .withRedirectUri(EXAMPLE_REDIRECT_URL) .withRequestBy(PassBy.VALUE) .withCreateJwtCallback(internalSignature(rpMockEntity.hexPrivateKey, rpMockEntity.did, rpMockEntity.didKey, SigningAlgo.ES256K)) .withVerifyJwtCallback(getVerifyJwtCallback(resolver)) .withAuthorizationEndpoint('www.myauthorizationendpoint.com') .withClientMetadata({ client_id: WELL_KNOWN_OPENID_FEDERATION, idTokenSigningAlgValuesSupported: [SigningAlgo.ES256K], requestObjectSigningAlgValuesSupported: [SigningAlgo.ES256K], responseTypesSupported: [ResponseType.ID_TOKEN], vpFormatsSupported: { jwt_vc: { alg: [SigningAlgo.EDDSA] }, jwt_vp: { alg: [SigningAlgo.EDDSA] }, ldp_vc: { proof_type: [IProofType.EcdsaSecp256k1Signature2019, IProofType.EcdsaSecp256k1Signature2019] }, ldp_vp: { proof_type: [IProofType.EcdsaSecp256k1Signature2019, IProofType.EcdsaSecp256k1Signature2019] }, ldp: { proof_type: [IProofType.EcdsaSecp256k1Signature2019, IProofType.EcdsaSecp256k1Signature2019] }, }, scopesSupported: [Scope.OPENID_DIDAUTHN, Scope.OPENID], subjectTypesSupported: [SubjectType.PAIRWISE], subject_syntax_types_supported: ['did', 'did:ion'], passBy: PassBy.VALUE, logo_uri: VERIFIER_LOGO_FOR_CLIENT, clientName: VERIFIER_NAME_FOR_CLIENT, 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100330', clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, }) .withPresentationDefinition({ definition: getPresentationDefinition() }, [PropertyTarget.REQUEST_OBJECT, PropertyTarget.AUTHORIZATION_REQUEST]) .withSupportedVersions(SupportedVersion.SIOPv2_ID1) .build() const op = OP.builder() .withPresentationSignCallback(presentationSignCallback) .withExpiresIn(1000) .withCreateJwtCallback(internalSignature(opMockEntity.hexPrivateKey, opMockEntity.did, opMockEntity.didKey, SigningAlgo.ES256K)) .withVerifyJwtCallback(getVerifyJwtCallback(resolver)) .withPresentationSignCallback(presentationSignCallback) .withRegistration({ authorizationEndpoint: 'www.myauthorizationendpoint.com', idTokenSigningAlgValuesSupported: [SigningAlgo.ES256K], issuer: ResponseIss.SELF_ISSUED_V2, requestObjectSigningAlgValuesSupported: [SigningAlgo.ES256K], responseTypesSupported: [ResponseType.ID_TOKEN], vpFormats: { jwt_vc: { alg: [SigningAlgo.EDDSA] }, jwt_vp: { alg: [SigningAlgo.EDDSA] }, ldp_vc: { proof_type: [IProofType.EcdsaSecp256k1Signature2019, IProofType.EcdsaSecp256k1Signature2019] }, ldp_vp: { proof_type: [IProofType.EcdsaSecp256k1Signature2019, IProofType.EcdsaSecp256k1Signature2019] }, ldp: { proof_type: [IProofType.EcdsaSecp256k1Signature2019, IProofType.EcdsaSecp256k1Signature2019] }, }, scopesSupported: [Scope.OPENID_DIDAUTHN, Scope.OPENID], subjectTypesSupported: [SubjectType.PAIRWISE], subject_syntax_types_supported: [], passBy: PassBy.VALUE, logo_uri: VERIFIER_LOGO_FOR_CLIENT, clientName: VERIFIER_NAME_FOR_CLIENT, 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100331', clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, }) .withSupportedVersions(SupportedVersion.SIOPv2_ID1) .build() const requestURI = await rp.createAuthorizationRequestURI({ correlationId: '1234', nonce: 'qBrR7mqnY3Qr49dAZycPF8FzgE83m6H0c2l0bzP4xSg', state: 'b32f0087fc9816eb813fd11f', }) if (!op.verifyRequestOptions.supportedVersions) throw new Error('Supported versions not set') await checkSIOPSpecVersionSupported(requestURI.authorizationRequestPayload, op.verifyRequestOptions.supportedVersions) // Let's test the parsing const parsedAuthReqURI = await op.parseAuthorizationRequestURI(requestURI.encodedUri) expect(parsedAuthReqURI.authorizationRequestPayload).toBeDefined() expect(parsedAuthReqURI.requestObjectJwt).toBeDefined() // expect(parsedAuthReqURI.registration).toBeDefined(); if (!parsedAuthReqURI.requestObjectJwt) throw new Error('Request object JWT not found') const verifiedAuthReqWithJWT = await op.verifyAuthorizationRequest(parsedAuthReqURI.requestObjectJwt) //, rp.authRequestOpts expect(verifiedAuthReqWithJWT.issuer).toMatch(rpMockEntity.did) const pex = new PresentationExchange({ allDIDs: [HOLDER_DID], allVerifiableCredentials: getVCs() }) const pd: PresentationDefinitionWithLocation[] = await PresentationExchange.findValidPresentationDefinitions( parsedAuthReqURI.authorizationRequestPayload, ) await pex.selectVerifiableCredentialsForSubmission(pd[0].definition) const verifiablePresentationResult = await pex.createVerifiablePresentation(pd[0].definition, getVCs(), presentationSignCallback, {}) const authenticationResponseWithJWT = await op.createAuthorizationResponse(verifiedAuthReqWithJWT, { presentationExchange: { verifiablePresentations: verifiablePresentationResult.verifiablePresentations, presentationSubmission: verifiablePresentationResult.presentationSubmission, vpTokenLocation: VPTokenLocation.AUTHORIZATION_RESPONSE, /*credentialsAndDefinitions: [ { presentation: vp, format: VerifiablePresentationTypeFormat.LDP_VP, vpTokenLocation: VPTokenLocation.AUTHORIZATION_RESPONSE, }, ],*/ }, }) expect(authenticationResponseWithJWT.response.payload).toBeDefined() expect(authenticationResponseWithJWT.response.idToken).toBeDefined() const DID_CONFIGURATION = { '@context': 'https://identity.foundation/.well-known/did-configuration/v1', linked_dids: [ 'eyJhbGciOiJSUzI1NiIsImtpZCI6ImRpZDprZXk6ejZNa29USHNnTk5yYnk4SnpDTlExaVJMeVc1UVE2UjhYdXU2QUE4aWdHck1WUFVNI3o2TWtvVEhzZ05OcmJ5OEp6Q05RMWlSTHlXNVFRNlI4WHV1NkFBOGlnR3JNVlBVTSJ9.eyJleHAiOjE3NjQ4NzkxMzksImlzcyI6ImRpZDprZXk6ejZNa29USHNnTk5yYnk4SnpDTlExaVJMeVc1UVE2UjhYdXU2QUE4aWdHck1WUFVNIiwibmJmIjoxNjA3MTEyNzM5LCJzdWIiOiJkaWQ6a2V5Ono2TWtvVEhzZ05OcmJ5OEp6Q05RMWlSTHlXNVFRNlI4WHV1NkFBOGlnR3JNVlBVTSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly9pZGVudGl0eS5mb3VuZGF0aW9uLy53ZWxsLWtub3duL2RpZC1jb25maWd1cmF0aW9uL3YxIl0sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImlkIjoiZGlkOmtleTp6Nk1rb1RIc2dOTnJieThKekNOUTFpUkx5VzVRUTZSOFh1dTZBQThpZ0dyTVZQVU0iLCJvcmlnaW4iOiJodHRwczovL2lkZW50aXR5LmZvdW5kYXRpb24ifSwiZXhwaXJhdGlvbkRhdGUiOiIyMDI1LTEyLTA0VDE0OjEyOjE5LTA2OjAwIiwiaXNzdWFuY2VEYXRlIjoiMjAyMC0xMi0wNFQxNDoxMjoxOS0wNjowMCIsImlzc3VlciI6ImRpZDprZXk6ejZNa29USHNnTk5yYnk4SnpDTlExaVJMeVc1UVE2UjhYdXU2QUE4aWdHck1WUFVNIiwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIkRvbWFpbkxpbmthZ2VDcmVkZW50aWFsIl19fQ.YZnpPMAW3GdaPXC2YKoJ7Igt1OaVZKq09XZBkptyhxTAyHTkX2Ewtew-JKHKQjyDyabY3HAy1LUPoIQX0jrU0J82pIYT3k2o7nNTdLbxlgb49FcDn4czntt5SbY0m1XwrMaKEvV0bHQsYPxNTqjYsyySccgPfmvN9IT8gRS-M9a6MZQxuB3oEMrVOQ5Vco0bvTODXAdCTHibAk1FlvKz0r1vO5QMhtW4OlRrVTI7ibquf9Nim_ch0KeMMThFjsBDKetuDF71nUcL5sf7PCFErvl8ZVw3UK4NkZ6iM-XIRsLL6rXP2SnDUVovcldhxd_pyKEYviMHBOgBdoNP6fOgRQ', 'eyJhbGciOiJSUzI1NiIsImtpZCI6ImRpZDprZXk6ejZNa29USHNnTk5yYnk4SnpDTlExaVJMeVc1UVE2UjhYdXU2QUE4aWdHck1WUFVNI3o2TWtvVEhzZ05OcmJ5OEp6Q05RMWlSTHlXNVFRNlI4WHV1NkFBOGlnR3JNVlBVTSJ9.eyJleHAiOjE3NjQ4NzkxMzksImlzcyI6ImRpZDprZXk6b3RoZXIiLCJuYmYiOjE2MDcxMTI3MzksInN1YiI6ImRpZDprZXk6b3RoZXIiLCJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vaWRlbnRpdHkuZm91bmRhdGlvbi8ud2VsbC1rbm93bi9kaWQtY29uZmlndXJhdGlvbi92MSJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJpZCI6ImRpZDprZXk6b3RoZXIiLCJvcmlnaW4iOiJodHRwczovL2lkZW50aXR5LmZvdW5kYXRpb24ifSwiZXhwaXJhdGlvbkRhdGUiOiIyMDI1LTEyLTA0VDE0OjEyOjE5LTA2OjAwIiwiaXNzdWFuY2VEYXRlIjoiMjAyMC0xMi0wNFQxNDoxMjoxOS0wNjowMCIsImlzc3VlciI6ImRpZDprZXk6b3RoZXIiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiRG9tYWluTGlua2FnZUNyZWRlbnRpYWwiXX19.rRuc-ojuEgyq8p_tBYK7BayuiNTBeXNyAnC14Rnjs-jsnhae4_E1Q12W99K2NGCGBi5KjNsBcZmdNJPxejiKPrjjcB99poFCgTY8tuRzDjVo0lIeBwfx9qqjKHTRTUR8FGM_imlOpVfBF4AHYxjkHvZn6c9lYvatYcDpB2UfH4BNXkdSVrUXy_kYjpMpAdRtyCAnD_isN1YpEHBqBmnfuVUbYcQK5kk6eiokRFDtWruL1OEeJMYPqjuBSd2m-H54tSM84Oic_pg2zXDjjBlXNelat6MPNT2QxmkwJg7oyewQWX2Ot2yyhSp9WyAQWMlQIe2x84R0lADUmZ1TPQchNw', ], } nock('https://ldtest.sphereon.com').get('/.well-known/did-configuration.json').times(3).reply(200, DID_CONFIGURATION) const verifiedAuthResponseWithJWT = await rp.verifyAuthorizationResponse(authenticationResponseWithJWT.response.payload, { presentationDefinitions: [{ definition: pd[0].definition, location: pd[0].location }], // audience: EXAMPLE_REDIRECT_URL, }) expect(verifiedAuthResponseWithJWT.idToken?.jwt).toBeDefined() expect(verifiedAuthResponseWithJWT.idToken?.payload.nonce).toMatch('qBrR7mqnY3Qr49dAZycPF8FzgE83m6H0c2l0bzP4xSg') }) it( 'should succeed when calling with CheckLinkedDomain.IF_PRESENT', async () => { const opMock = await mockedGetEnterpriseAuthToken('OP') const opMockEntity = { ...opMock, didKey: `${opMock.did}#controller`, } const rpMock = await mockedGetEnterpriseAuthToken('RP') const rpMockEntity = { ...rpMock, didKey: `${rpMock.did}#controller`, } // eslint-disable-next-line @typescript-eslint/no-unused-vars const presentationVerificationCallback: PresentationVerificationCallback = async (_args) => ({ verified: true }) const resolver = getResolver('ethr') const eventEmitter = new EventEmitter() const replayRegistry = new InMemoryRPSessionManager(eventEmitter) const rp = RP.builder({ requestVersion: SupportedVersion.SIOPv2_ID1 }) .withEventEmitter(eventEmitter) .withSessionManager(replayRegistry) .withClientId(rpMockEntity.did) .withScope('test') .withResponseType([ResponseType.ID_TOKEN, ResponseType.VP_TOKEN]) .withVerifyJwtCallback(getVerifyJwtCallback(resolver, { checkLinkedDomain: 'if_present' })) .withPresentationVerification(presentationVerificationCallback) .withRevocationVerification(RevocationVerification.NEVER) .withRedirectUri(EXAMPLE_REDIRECT_URL) .withRequestBy(PassBy.VALUE) .withCreateJwtCallback(internalSignature(rpMockEntity.hexPrivateKey, rpMockEntity.did, rpMockEntity.didKey, SigningAlgo.ES256K)) .withAuthorizationEndpoint('www.myauthorizationendpoint.com') .withClientMetadata({ client_id: WELL_KNOWN_OPENID_FEDERATION, idTokenSigningAlgValuesSupported: [SigningAlgo.EDDSA], requestObjectSigningAlgValuesSupported: [SigningAlgo.EDDSA, SigningAlgo.ES256], responseTypesSupported: [ResponseType.ID_TOKEN], vpFormatsSupported: { jwt_vc: { alg: [SigningAlgo.EDDSA] } }, scopesSupported: [Scope.OPENID_DIDAUTHN, Scope.OPENID], subjectTypesSupported: [SubjectType.PAIRWISE], subject_syntax_types_supported: ['did', 'did:ethr'], passBy: PassBy.VALUE, logo_uri: VERIFIER_LOGO_FOR_CLIENT, clientName: VERIFIER_NAME_FOR_CLIENT, 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100328', clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, }) .withPresentationDefinition({ definition: getPresentationDefinition() }, [ PropertyTarget.REQUEST_OBJECT, PropertyTarget.AUTHORIZATION_REQUEST, ]) .withSupportedVersions(SupportedVersion.SIOPv2_ID1) .build() const op = OP.builder() .withPresentationSignCallback(presentationSignCallback) .withExpiresIn(1000) .withCreateJwtCallback(internalSignature(opMockEntity.hexPrivateKey, opMockEntity.did, opMockEntity.didKey, SigningAlgo.ES256K)) .withVerifyJwtCallback(getVerifyJwtCallback(resolver, { checkLinkedDomain: 'never' })) .withRegistration({ authorizationEndpoint: 'www.myauthorizationendpoint.com', idTokenSigningAlgValuesSupported: [SigningAlgo.EDDSA], issuer: ResponseIss.SELF_ISSUED_V2, requestObjectSigningAlgValuesSupported: [SigningAlgo.EDDSA, SigningAlgo.ES256], responseTypesSupported: [ResponseType.ID_TOKEN], vpFormats: { jwt_vc: { alg: [SigningAlgo.EDDSA] } }, scopesSupported: [Scope.OPENID_DIDAUTHN, Scope.OPENID], subjectTypesSupported: [SubjectType.PAIRWISE], subject_syntax_types_supported: [], passBy: PassBy.VALUE, logo_uri: VERIFIER_LOGO_FOR_CLIENT, clientName: VERIFIER_NAME_FOR_CLIENT, 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100329', clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, }) .withSupportedVersions(SupportedVersion.SIOPv2_ID1) .build() const requestURI = await rp.createAuthorizationRequestURI({ correlationId: '1234', nonce: 'qBrR7mqnY3Qr49dAZycPF8FzgE83m6H0c2l0bzP4xSg', state: 'b32f0087fc9816eb813fd11f', }) // Let's test the parsing const parsedAuthReqURI = await op.parseAuthorizationRequestURI(requestURI.encodedUri) expect(parsedAuthReqURI.authorizationRequestPayload).toBeDefined() expect(parsedAuthReqURI.requestObjectJwt).toBeDefined() // expect(parsedAuthReqURI.registration).toBeDefined(); if (!parsedAuthReqURI.requestObjectJwt) throw new Error('Request object JWT not found') const verifiedAuthReqWithJWT = await op.verifyAuthorizationRequest(parsedAuthReqURI.requestObjectJwt) expect(verifiedAuthReqWithJWT.issuer).toMatch(rpMockEntity.did) const pex = new PresentationExchange({ allDIDs: [HOLDER_DID], allVerifiableCredentials: getVCs() }) const pd: PresentationDefinitionWithLocation[] = await PresentationExchange.findValidPresentationDefinitions( parsedAuthReqURI.authorizationRequestPayload, ) await pex.selectVerifiableCredentialsForSubmission(pd[0].definition) const verifiablePresentationResult = await pex.createVerifiablePresentation(pd[0].definition, getVCs(), presentationSignCallback, {}) const authenticationResponseWithJWT = await op.createAuthorizationResponse(verifiedAuthReqWithJWT, { presentationExchange: { verifiablePresentations: verifiablePresentationResult.verifiablePresentations, presentationSubmission: verifiablePresentationResult.presentationSubmission, vpTokenLocation: VPTokenLocation.AUTHORIZATION_RESPONSE, /*credentialsAndDefinitions: [ { presentation: vp, format: VerifiablePresentationTypeFormat.LDP_VP, vpTokenLocation: VPTokenLocation.AUTHORIZATION_RESPONSE, }, ],*/ }, }) expect(authenticationResponseWithJWT.response.payload).toBeDefined() expect(authenticationResponseWithJWT.response.idToken).toBeDefined() const verifiedAuthResponseWithJWT = await rp.verifyAuthorizationResponse(authenticationResponseWithJWT.response.payload, { presentationDefinitions: [{ definition: pd[0].definition, location: pd[0].location }], // audience: EXAMPLE_REDIRECT_URL, }) expect(verifiedAuthResponseWithJWT.idToken?.jwt).toBeDefined() expect(verifiedAuthResponseWithJWT.idToken?.payload.nonce).toMatch('qBrR7mqnY3Qr49dAZycPF8FzgE83m6H0c2l0bzP4xSg') }, UNIT_TEST_TIMEOUT, ) it('succeed when calling with RevocationVerification.ALWAYS with ldp_vp', async () => { const opMock = await mockedGetEnterpriseAuthToken('OP') const opMockEntity = { ...opMock, didKey: `${opMock.did}#controller`, } const rpMock = await mockedGetEnterpriseAuthToken('RP') const rpMockEntity = { ...rpMock, didKey: `${rpMock.did}#controller`, } // eslint-disable-next-line @typescript-eslint/no-unused-vars const presentationVerificationCallback: PresentationVerificationCallback = async (_args) => ({ verified: true }) const resolver = getResolver('ethr') const eventEmitter = new EventEmitter() const replayRegistry = new InMemoryRPSessionManager(eventEmitter) const rp = RP.builder({ requestVersion: SupportedVersion.SIOPv2_ID1 }) .withEventEmitter(eventEmitter) .withSessionManager(replayRegistry) .withClientId('test_client_id') .withScope('test') .withResponseType([ResponseType.VP_TOKEN, ResponseType.ID_TOKEN]) .withRevocationVerification(RevocationVerification.ALWAYS) .withPresentationVerification(presentationVerificationCallback) .withRevocationVerificationCallback(async () => { return { status: RevocationStatus.VALID } }) .withRedirectUri(EXAMPLE_REDIRECT_URL) .withRequestBy(PassBy.VALUE) .withCreateJwtCallback(internalSignature(rpMockEntity.hexPrivateKey, rpMockEntity.did, rpMockEntity.didKey, SigningAlgo.ES256K)) .withVerifyJwtCallback(getVerifyJwtCallback(resolver)) .withAuthorizationEndpoint('www.myauthorizationendpoint.com') .withClientMetadata({ client_id: WELL_KNOWN_OPENID_FEDERATION, idTokenSigningAlgValuesSupported: [SigningAlgo.ES256K], requestObjectSigningAlgValuesSupported: [SigningAlgo.ES256K], responseTypesSupported: [ResponseType.ID_TOKEN], vpFormatsSupported: { jwt_vc: { alg: [SigningAlgo.EDDSA] }, jwt_vp: { alg: [SigningAlgo.EDDSA] }, ldp_vc: { proof_type: [IProofType.EcdsaSecp256k1Signature2019, IProofType.EcdsaSecp256k1Signature2019] }, ldp_vp: { proof_type: [IProofType.EcdsaSecp256k1Signature2019, IProofType.EcdsaSecp256k1Signature2019] }, ldp: { proof_type: [IProofType.EcdsaSecp256k1Signature2019, IProofType.EcdsaSecp256k1Signature2019] }, }, scopesSupported: [Scope.OPENID_DIDAUTHN, Scope.OPENID], subjectTypesSupported: [SubjectType.PAIRWISE], subject_syntax_types_supported: ['did', 'did:ion'], passBy: PassBy.VALUE, logo_uri: VERIFIER_LOGO_FOR_CLIENT, clientName: VERIFIER_NAME_FOR_CLIENT, 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100330', clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, }) .withPresentationDefinition({ definition: getPresentationDefinition() }, [PropertyTarget.REQUEST_OBJECT, PropertyTarget.AUTHORIZATION_REQUEST]) .withSupportedVersions(SupportedVersion.SIOPv2_ID1) .build() const op = OP.builder() .withPresentationSignCallback(presentationSignCallback) .withExpiresIn(1000) .withVerifyJwtCallback(getVerifyJwtCallback(resolver)) .withCreateJwtCallback(internalSignature(opMockEntity.hexPrivateKey, opMockEntity.did, opMockEntity.didKey, SigningAlgo.ES256K)) .withPresentationSignCallback(presentationSignCallback) .withRegistration({ authorizationEndpoint: 'www.myauthorizationendpoint.com', idTokenSigningAlgValuesSupported: [SigningAlgo.ES256K], issuer: ResponseIss.SELF_ISSUED_V2, requestObjectSigningAlgValuesSupported: [SigningAlgo.ES256K], responseTypesSupported: [ResponseType.ID_TOKEN], vpFormats: { jwt_vc: { alg: [SigningAlgo.EDDSA] }, jwt_vp: { alg: [SigningAlgo.EDDSA] }, ldp_vc: { proof_type: [IProofType.EcdsaSecp256k1Signature2019, IProofType.EcdsaSecp256k1Signature2019] }, ldp_vp: { proof_type: [IProofType.EcdsaSecp256k1Signature2019, IProofType.EcdsaSecp256k1Signature2019] }, ldp: { proof_type: [IProofType.EcdsaSecp256k1Signature2019, IProofType.EcdsaSecp256k1Signature2019] }, }, scopesSupported: [Scope.OPENID_DIDAUTHN, Scope.OPENID], subjectTypesSupported: [SubjectType.PAIRWISE], subject_syntax_types_supported: [], passBy: PassBy.VALUE, logo_uri: VERIFIER_LOGO_FOR_CLIENT, clientName: VERIFIER_NAME_FOR_CLIENT, 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100331', clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, }) .withSupportedVersions(SupportedVersion.SIOPv2_ID1) .build() const requestURI = await rp.createAuthorizationRequestURI({ correlationId: '1234', nonce: 'qBrR7mqnY3Qr49dAZycPF8FzgE83m6H0c2l0bzP4xSg', state: 'b32f0087fc9816eb813fd11f', }) if (!op.verifyRequestOptions.supportedVersions) throw new Error('Supported versions not set') await checkSIOPSpecVersionSupported(requestURI.authorizationRequestPayload, op.verifyRequestOptions.supportedVersions) // Let's test the parsing const parsedAuthReqURI = await op.parseAuthorizationRequestURI(requestURI.encodedUri) expect(parsedAuthReqURI.authorizationRequestPayload).toBeDefined() expect(parsedAuthReqURI.requestObjectJwt).toBeDefined() // expect(parsedAuthReqURI.registration).toBeDefined();