Skip to content

Commit c7d6fcd

Browse files
committed
chore: authorization_details tests passing
1 parent 294ad69 commit c7d6fcd

12 files changed

Lines changed: 449 additions & 57 deletions

File tree

packages/client/lib/AuthorizationCodeClient.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import {
22
AuthorizationChallengeCodeResponse,
3-
AuthorizationChallengeRequestOpts,
4-
AuthorizationDetails,
3+
AuthorizationChallengeRequestOpts, AuthorizationDetailsV1_0_15,
54
AuthorizationRequestOpts,
65
CodeChallengeMethod,
76
CommonAuthorizationChallengeRequest,
@@ -185,7 +184,7 @@ export const createAuthorizationRequestUrl = async ({
185184
...(format && { format }),
186185
...(vct && { vct, claims: cred.claims ? removeDisplayAndValueTypes(cred.claims) : undefined }),
187186
...(doctype && { doctype, claims: cred.claims ? removeDisplayAndValueTypes(cred.claims) : undefined })
188-
} as AuthorizationDetails
187+
} as AuthorizationDetailsV1_0_15
189188
})
190189
if (!authorizationDetails || authorizationDetails.length === 0) {
191190
throw Error(`Could not create authorization details from credential offer. Please pass in explicit details`)
@@ -278,8 +277,8 @@ const hasCredentialDefinition = (cred: any): cred is {
278277

279278
const handleAuthorizationDetails = (
280279
endpointMetadata: EndpointMetadataResultV1_0_15,
281-
authorizationDetails?: AuthorizationDetails | AuthorizationDetails[]
282-
): AuthorizationDetails | AuthorizationDetails[] | undefined => {
280+
authorizationDetails?: AuthorizationDetailsV1_0_15 | AuthorizationDetailsV1_0_15[]
281+
): AuthorizationDetailsV1_0_15 | AuthorizationDetailsV1_0_15[] | undefined => {
283282
if (authorizationDetails) {
284283
if (typeof authorizationDetails === 'string') {
285284
// backwards compat for older versions of the lib
@@ -298,7 +297,7 @@ const handleAuthorizationDetails = (
298297

299298
const handleLocations = (
300299
endpointMetadata: EndpointMetadataResultV1_0_15,
301-
authorizationDetails: AuthorizationDetails
300+
authorizationDetails: AuthorizationDetailsV1_0_15
302301
) => {
303302
if (typeof authorizationDetails === 'string') {
304303
// backwards compat for older versions of the lib

packages/client/lib/AuthorizationDetailsBuilder.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
import { AuthorizationDetails, AuthorizationDetailsJwtVcJson, OID4VCICredentialFormat } from '@sphereon/oid4vci-common'
1+
import {
2+
AuthorizationDetailsJwtVcJson,
3+
AuthorizationDetailsV1_0_15,
4+
OID4VCICredentialFormat
5+
} from '@sphereon/oid4vci-common'
26

37
//todo: refactor this builder to be able to create ldp details as well
48
export class AuthorizationDetailsBuilder {
5-
private readonly authorizationDetails: Partial<Exclude<AuthorizationDetails, string>>
9+
private readonly authorizationDetails: Partial<Exclude<AuthorizationDetailsV1_0_15, string>>
610

711
constructor() {
812
this.authorizationDetails = {}
913
}
1014

11-
withType(type: string): AuthorizationDetailsBuilder {
12-
this.authorizationDetails.type = type
13-
return this
14-
}
15-
1615
withFormats(format: OID4VCICredentialFormat): AuthorizationDetailsBuilder {
1716
this.authorizationDetails.format = format
1817
return this

packages/client/lib/CredentialRequestClient.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { createDPoP, CreateDPoPClientOpts, getCreateDPoPOptions } from '@sphereon/oid4vc-common'
22
import {
33
acquireDeferredCredential,
4-
AuthorizationDetails,
4+
AuthorizationDetailsV1_0_15,
5+
CredentialRequest,
56
CredentialRequestV1_0_15,
67
CredentialResponse,
78
DPoPResponseParams,
@@ -14,7 +15,6 @@ import {
1415
post,
1516
ProofOfPossession,
1617
supportedOID4VCICredentialFormat,
17-
CredentialRequest,
1818
URL_NOT_VALID
1919
} from '@sphereon/oid4vci-common'
2020
import { CredentialFormat, Loggers } from '@sphereon/ssi-types'
@@ -40,7 +40,7 @@ export interface CredentialRequestOpts {
4040
version: OpenId4VCIVersion
4141
subjectIssuance?: ExperimentalSubjectIssuance
4242
issuerState?: string
43-
authorizationDetails?: AuthorizationDetails[]
43+
authorizationDetails?: AuthorizationDetailsV1_0_15[]
4444
}
4545

4646
export type CreateCredentialRequestOpts = {
@@ -72,14 +72,14 @@ export async function buildProof(
7272
return await proofInput.build()
7373
}
7474

75-
function isOpenIdCredentialDetail(ad: AuthorizationDetails): ad is AuthorizationDetails {
75+
function isOpenIdCredentialDetail(ad: AuthorizationDetailsV1_0_15): ad is AuthorizationDetailsV1_0_15 {
7676
return typeof ad === 'object' && ad !== null && ad.type === 'openid_credential'
7777
}
7878

7979
function findAuthorizationDetail(
80-
authorizationDetails: AuthorizationDetails[] | undefined,
80+
authorizationDetails: AuthorizationDetailsV1_0_15[] | undefined,
8181
preferredConfigId?: string
82-
): AuthorizationDetails | undefined {
82+
): AuthorizationDetailsV1_0_15 | undefined {
8383
if (!authorizationDetails) {
8484
return undefined
8585
}

packages/issuer-rest/lib/oid4vci-api-functions.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,23 @@ export function getCredentialEndpoint(
313313
if('issuer_state' in tokenClaims && typeof tokenClaims.issuer_state === 'string') {
314314
issuerCorrelation.issuerState = tokenClaims.issuer_state
315315
}
316+
317+
// Handle credential_identifier from authorization_details flow
318+
if ('authorization_details' in tokenClaims && Array.isArray(tokenClaims.authorization_details)) {
319+
issuerCorrelation.authorizationDetails = tokenClaims.authorization_details
320+
321+
if (credentialRequest.credential_identifier) {
322+
const validIdentifiers = tokenClaims.authorization_details
323+
.flatMap((detail: any) => detail.credential_identifiers || [])
324+
325+
if (!validIdentifiers.includes(credentialRequest.credential_identifier)) {
326+
return sendErrorResponse(response, 400, {
327+
error: 'invalid_credential_request',
328+
error_description: 'credential_identifier not found in authorization_details'
329+
})
330+
}
331+
}
332+
}
316333
} catch (e) {
317334
LOG.warning(e)
318335
return sendErrorResponse(response, 400, {
@@ -727,8 +744,22 @@ export function pushedAuthorizationEndpoint(
727744
// TODO: Both UUID and requestURI need to be configurable for the server
728745
const uuid = uuidv4()
729746
const requestUri = `urn:ietf:params:oauth:request_uri:${uuid}`
730-
// The redirect_uri is created and set in a map, to keep track of the actual request
731-
authRequestsData.set(requestUri, req.body)
747+
748+
// Store authorization_details in the request for later retrieval
749+
let requestData = req.body
750+
if (req.body.authorization_details) {
751+
const authDetails = Array.isArray(req.body.authorization_details)
752+
? req.body.authorization_details
753+
: JSON.parse(req.body.authorization_details)
754+
755+
requestData = {
756+
...req.body,
757+
authorization_details: authDetails // Store parsed authorization details
758+
}
759+
}
760+
761+
authRequestsData.set(requestUri, requestData)
762+
732763
// Invalidates the request_uri removing it from the mapping after it is expired, needs to be refactored because
733764
// some of the properties will be needed in subsequent steps if the authorization succeeds
734765
// TODO in the /token endpoint the code_challenge must be matched against the hashed code_verifier

packages/issuer/lib/VcIssuer.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,17 @@ export class VcIssuer {
394394
throw Error(TokenErrorResponse.invalid_request)
395395
}
396396
}
397+
398+
// Validate credential_identifier against authorization_details if present
399+
if ('credential_identifier' in credentialRequest && credentialRequest.credential_identifier && issuerCorrelation.authorizationDetails) {
400+
const validIdentifiers = issuerCorrelation.authorizationDetails
401+
.flatMap((detail: any) => detail.credential_identifiers || [])
402+
403+
if (!validIdentifiers.includes(credentialRequest.credential_identifier)) {
404+
throw Error('credential_identifier not found in authorization_details')
405+
}
406+
}
407+
397408
let format = this.lookupCredentialFormat(credentialRequest)
398409
const validated = await this.validateCredentialRequestProof({
399410
...opts,

0 commit comments

Comments
 (0)