Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: openid4vp x509 #1984

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
DifPresentationExchangeService,
DifPresentationExchangeSubmissionLocation,
} from '@credo-ts/core'
import { OP, ResponseIss, ResponseMode, SupportedVersion, VPTokenLocation } from '@sphereon/did-auth-siop'
import { OP, ResponseIss, ResponseMode, ResponseType, SupportedVersion, VPTokenLocation } from '@sphereon/did-auth-siop'

import { getSphereonVerifiablePresentation } from '../shared/transform'
import { getCreateJwtCallback, getVerifyJwtCallback, openIdTokenIssuerToJwtIssuer } from '../shared/utils'
Expand Down Expand Up @@ -73,6 +73,8 @@ export class OpenId4VcSiopHolderService {
let openIdTokenIssuer = options.openIdTokenIssuer
let presentationExchangeOptions: PresentationExchangeResponseOpts | undefined = undefined

const wantsIdToken = await authorizationRequest.authorizationRequest.containsResponseType(ResponseType.ID_TOKEN)

// Handle presentation exchange part
if (authorizationRequest.presentationDefinitions && authorizationRequest.presentationDefinitions.length > 0) {
if (!presentationExchange) {
Expand Down Expand Up @@ -106,7 +108,7 @@ export class OpenId4VcSiopHolderService {
vpTokenLocation: VPTokenLocation.AUTHORIZATION_RESPONSE,
}

if (!openIdTokenIssuer) {
if (wantsIdToken && !openIdTokenIssuer) {
openIdTokenIssuer = this.getOpenIdTokenIssuerFromVerifiablePresentation(verifiablePresentations[0])
}
} else if (options.presentationExchange) {
Expand All @@ -115,19 +117,26 @@ export class OpenId4VcSiopHolderService {
)
}

if (!openIdTokenIssuer) {
throw new CredoError(
'Unable to create authorization response. openIdTokenIssuer MUST be supplied when no presentation is active.'
)
if (wantsIdToken) {
if (!openIdTokenIssuer) {
throw new CredoError(
'Unable to create authorization response. openIdTokenIssuer MUST be supplied when no presentation is active and the ResponseType includes id_token.'
)
}

this.assertValidTokenIssuer(authorizationRequest, openIdTokenIssuer)
}

this.assertValidTokenIssuer(authorizationRequest, openIdTokenIssuer)
const openidProvider = await this.getOpenIdProvider(agentContext)
const jwtIssuer =
wantsIdToken && openIdTokenIssuer
? await openIdTokenIssuerToJwtIssuer(agentContext, openIdTokenIssuer)
: undefined

const openidProvider = await this.getOpenIdProvider(agentContext)
const authorizationResponseWithCorrelationId = await openidProvider.createAuthorizationResponse(
authorizationRequest,
{
jwtIssuer: await openIdTokenIssuerToJwtIssuer(agentContext, openIdTokenIssuer),
jwtIssuer,
presentationExchange: presentationExchangeOptions,
// https://openid.net/specs/openid-connect-self-issued-v2-1_0.html#name-aud-of-a-request-object
audience: authorizationRequest.authorizationRequestPayload.client_id,
Expand Down
25 changes: 19 additions & 6 deletions packages/openid4vc/tests/openid4vc.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
W3cCredentialSubject,
w3cDate,
W3cIssuer,
X509Module,
KeyType,
} from '@credo-ts/core'
import express, { type Express } from 'express'

Expand Down Expand Up @@ -55,6 +57,7 @@ describe('OpenId4Vc', () => {
let issuer: AgentType<{
openId4VcIssuer: OpenId4VcIssuerModule
tenants: TenantsModule<{ openId4VcIssuer: OpenId4VcIssuerModule }>
x509: X509Module
}>
let issuer1: TenantType
let issuer2: TenantType
Expand All @@ -78,6 +81,7 @@ describe('OpenId4Vc', () => {
issuer = (await createAgentFromModules(
'issuer',
{
x509: new X509Module(),
openId4VcIssuer: new OpenId4VcIssuerModule({
baseUrl: issuanceBaseUrl,
endpoints: {
Expand Down Expand Up @@ -128,6 +132,7 @@ describe('OpenId4Vc', () => {
openId4VcHolder: new OpenId4VcHolderModule(),
askar: new AskarModule(askarModuleConfig),
tenants: new TenantsModule(),
x509: new X509Module(),
},
'96213c3d7fc8d4d6754c7a0fd969598e'
)) as unknown as typeof holder
Expand Down Expand Up @@ -684,10 +689,7 @@ describe('OpenId4Vc', () => {
const openIdVerifier = await verifier.agent.modules.openId4VcVerifier.createVerifier()

const signedSdJwtVc = await issuer.agent.sdJwtVc.sign({
holder: {
method: 'did',
didUrl: holder.kid,
},
holder: { method: 'did', didUrl: holder.kid },
issuer: {
method: 'did',
didUrl: issuer.kid,
Expand All @@ -703,8 +705,17 @@ describe('OpenId4Vc', () => {
},
})

const certificate = await verifier.agent.x509.createSelfSignedCertificate({
key: await verifier.agent.wallet.createKey({ keyType: KeyType.Ed25519 }),
extensions: [[{ type: 'dns', value: 'example.com' }]],
})

const rawCertificate = certificate.toString('base64')
await holder.agent.sdJwtVc.store(signedSdJwtVc.compact)

await holder.agent.x509.addTrustedCertificate(rawCertificate)
await verifier.agent.x509.addTrustedCertificate(rawCertificate)

const presentationDefinition = {
id: 'OpenBadgeCredential',
input_descriptors: [
Expand Down Expand Up @@ -737,9 +748,11 @@ describe('OpenId4Vc', () => {
const { authorizationRequest, verificationSession } =
await verifier.agent.modules.openId4VcVerifier.createAuthorizationRequest({
verifierId: openIdVerifier.verifierId,

requestSigner: {
method: 'did',
didUrl: verifier.kid,
method: 'x5c',
x5c: [rawCertificate],
issuer: 'https://example.com/hakuna/matadata',
},
presentationExchange: {
definition: presentationDefinition,
Expand Down
4 changes: 2 additions & 2 deletions packages/openid4vc/tests/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type {
OpenId4VcVerificationSessionState,
OpenId4VcVerificationSessionStateChangedEvent,
} from '../src'
import type { BaseEvent, ModulesMap } from '@credo-ts/core'
import type { BaseEvent, ModulesMap, X509Module } from '@credo-ts/core'
import type { TenantsModule } from '@credo-ts/tenants'
import type { Observable } from 'rxjs'

Expand Down Expand Up @@ -44,7 +44,7 @@ export async function createAgentFromModules<MM extends ModulesMap>(label: strin
export type AgentType<MM extends ModulesMap> = Awaited<ReturnType<typeof createAgentFromModules<MM>>>

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type AgentWithTenantsModule = Agent<{ tenants: TenantsModule<any> }>
type AgentWithTenantsModule = Agent<{ tenants: TenantsModule<any>; x509: X509Module }>

export async function createTenantForAgent(
// FIXME: we need to make some improvements on the agent typing. It'a quite hard
Expand Down
Loading