Skip to content

Commit

Permalink
Merge pull request #170 from Sphereon-Opensource/feature/SDK-39_well-…
Browse files Browse the repository at this point in the history
…known-oidf

Feature/sdk 39 well known oidf (SDK-44 also)
  • Loading branch information
sanderPostma authored Nov 22, 2024
2 parents 5082e0e + addbde5 commit 7be2c0d
Show file tree
Hide file tree
Showing 24 changed files with 116 additions and 885 deletions.
10 changes: 6 additions & 4 deletions packages/callback-example/lib/__tests__/issuerCallback.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,19 @@ import {
ProofOfPossession,
} from '@sphereon/oid4vci-common'
import { CredentialOfferSession } from '@sphereon/oid4vci-common'
import { CredentialSupportedBuilderV1_13, VcIssuer, VcIssuerBuilder } from '@sphereon/oid4vci-issuer'
import {
AuthorizationServerMetadataBuilder,
CredentialSupportedBuilderV1_13,
VcIssuer,
VcIssuerBuilder
} from '@sphereon/oid4vci-issuer'
import { MemoryStates } from '@sphereon/oid4vci-issuer'
import { CredentialDataSupplierResult } from '@sphereon/oid4vci-issuer/dist/types'
import { ICredential, IProofPurpose, IProofType, W3CVerifiableCredential } from '@sphereon/ssi-types'
import { DIDDocument } from 'did-resolver'
import * as jose from 'jose'

import { generateDid, getIssuerCallbackV1_0_11, getIssuerCallbackV1_0_13, verifyCredential } from '../IssuerCallback'
import {
AuthorizationServerMetadataBuilder
} from '@sphereon/oid4vci-issuer/dist/builder/AuthorizationServerMetadataBuilder'

const INITIATION_TEST_URI =
'openid-credential-offer://?credential_offer=%7B%22credential_issuer%22:%22https://credential-issuer.example.com%22,%22credential_configuration_ids%22:%5B%22UniversityDegreeCredential%22%5D,%22grants%22:%7B%22urn:ietf:params:oauth:grant-type:pre-authorized_code%22:%7B%22pre-authorized_code%22:%22oaKazRN8I0IbtZ0C7JuMn5%22,%22tx_code%22:%7B%22input_mode%22:%22text%22,%22description%22:%22Please%20enter%20the%20serial%20number%20of%20your%20physical%20drivers%20license%22%7D%7D%7D%7D'
Expand Down
2 changes: 1 addition & 1 deletion packages/callback-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"@sphereon/oid4vci-client": "workspace:*",
"@sphereon/oid4vci-common": "workspace:*",
"@sphereon/oid4vci-issuer": "workspace:*",
"@sphereon/ssi-types": "0.30.1",
"@sphereon/ssi-types": "0.30.2-next.279",
"jose": "^4.10.0"
},
"devDependencies": {
Expand Down
1 change: 1 addition & 0 deletions packages/client/lib/MetadataClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ export class MetadataClient {
: (authMetadata as CredentialIssuerMetadataV1_0_13);
}
debug(`Issuer ${issuer} token endpoint ${token_endpoint}, credential endpoint ${credential_endpoint}`);

return {
issuer,
token_endpoint,
Expand Down
8 changes: 6 additions & 2 deletions packages/client/lib/__tests__/SdJwt.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ import {
import nock from 'nock';

import { OpenID4VCIClientV1_0_13 } from '..';
import { createAccessTokenResponse, IssuerMetadataBuilderV1_13, VcIssuerBuilder } from '../../../issuer';
import { AuthorizationServerMetadataBuilder } from '../../../issuer/lib/builder/AuthorizationServerMetadataBuilder'
import {
AuthorizationServerMetadataBuilder,
createAccessTokenResponse,
IssuerMetadataBuilderV1_13,
VcIssuerBuilder
} from '../../../issuer'

export const UNIT_TEST_TIMEOUT = 30000;

Expand Down
2 changes: 1 addition & 1 deletion packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"dependencies": {
"@sphereon/oid4vc-common": "workspace:*",
"@sphereon/oid4vci-common": "workspace:*",
"@sphereon/ssi-types": "0.30.1",
"@sphereon/ssi-types": "0.30.2-next.279",
"cross-fetch": "^3.1.8",
"debug": "^4.3.5"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"build:clean": "tsc --build --clean && tsc --build"
},
"dependencies": {
"@sphereon/ssi-types": "0.30.1",
"@sphereon/ssi-types": "0.30.2-next.279",
"jwt-decode": "^4.0.0",
"sha.js": "^2.4.11",
"uint8arrays": "3.1.1",
Expand Down
6 changes: 3 additions & 3 deletions packages/issuer-rest/lib/__tests__/ClientIssuerIT.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ import {
PRE_AUTH_CODE_LITERAL,
PRE_AUTH_GRANT_LITERAL
} from '@sphereon/oid4vci-common'
import { VcIssuer } from '@sphereon/oid4vci-issuer/dist/VcIssuer'
import { CredentialSupportedBuilderV1_13, VcIssuerBuilder } from '@sphereon/oid4vci-issuer/dist/builder'
import {
AuthorizationServerMetadataBuilder
} from '@sphereon/oid4vci-issuer/dist/builder/AuthorizationServerMetadataBuilder'
} from '@sphereon/oid4vci-issuer'
import { VcIssuer } from '@sphereon/oid4vci-issuer/dist/VcIssuer'
import { CredentialSupportedBuilderV1_13, VcIssuerBuilder } from '@sphereon/oid4vci-issuer/dist/builder'
import { MemoryStates } from '@sphereon/oid4vci-issuer/dist/state-manager'
import { ExpressBuilder, ExpressSupport } from '@sphereon/ssi-express-support'
import { IProofPurpose, IProofType } from '@sphereon/ssi-types'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
import { VcIssuer } from '@sphereon/oid4vci-issuer'
import {
AuthorizationServerMetadataBuilder
} from '@sphereon/oid4vci-issuer/dist/builder/AuthorizationServerMetadataBuilder'
} from '@sphereon/oid4vci-issuer'
import { MemoryStates } from '@sphereon/oid4vci-issuer/dist/state-manager'
import { ExpressBuilder, ExpressSupport } from '@sphereon/ssi-express-support'
import { DIDDocument } from 'did-resolver'
Expand Down
4 changes: 2 additions & 2 deletions packages/issuer-rest/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"@sphereon/oid4vc-common": "workspace:*",
"@sphereon/oid4vci-common": "workspace:*",
"@sphereon/oid4vci-issuer": "workspace:*",
"@sphereon/ssi-express-support": "0.30.1",
"@sphereon/ssi-types": "0.30.1",
"@sphereon/ssi-express-support": "0.30.2-next.279",
"@sphereon/ssi-types": "0.30.2-next.279",
"body-parser": "^1.20.2",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
Expand Down
34 changes: 26 additions & 8 deletions packages/issuer/lib/VcIssuer.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import { uuidv4 } from '@sphereon/oid4vc-common'
import {
ALG_ERROR,
AUD_ERROR, AuthorizationServerMetadata,
AUD_ERROR,
AuthorizationServerMetadata,
CNonceState,
CreateCredentialOfferURIResult,
CREDENTIAL_MISSING_ERROR,
CredentialConfigurationSupportedV1_0_13,
CredentialDataSupplierInput,
CredentialEventNames,
CredentialIssuerMetadata,
CredentialIssuerMetadataOptsV1_0_13,
CredentialOfferEventNames,
CredentialOfferSession,
CredentialOfferV1_0_13,
CredentialRequest,
CredentialRequestV1_0_13,
CredentialResponse,
DID_NO_DIDDOC_ERROR,
EVENTS,
IAT_ERROR,
ISSUER_CONFIG_ERROR,
IssueStatus,
Expand All @@ -35,13 +40,28 @@ import {
TYP_ERROR,
URIState
} from '@sphereon/oid4vci-common'
import { CredentialEventNames, CredentialOfferEventNames, EVENTS } from '@sphereon/oid4vci-common'
import { CredentialIssuerMetadataOptsV1_0_13 } from '@sphereon/oid4vci-common'
import { CompactSdJwtVc, CredentialMapper, InitiatorType, SubSystem, System, W3CVerifiableCredential } from '@sphereon/ssi-types'
import {
CompactSdJwtVc,
CredentialMapper,
InitiatorType,
SubSystem,
System,
W3CVerifiableCredential
} from '@sphereon/ssi-types'

import { assertValidPinNumber, createCredentialOfferObject, createCredentialOfferURIFromObject, CredentialOfferGrantInput } from './functions'
import {
assertValidPinNumber,
createCredentialOfferObject,
createCredentialOfferURIFromObject,
CredentialOfferGrantInput
} from './functions'
import { LookupStateManager } from './state-manager'
import { CredentialDataSupplier, CredentialDataSupplierArgs, CredentialIssuanceInput, CredentialSignerCallback } from './types'
import {
CredentialDataSupplier,
CredentialDataSupplierArgs,
CredentialIssuanceInput,
CredentialSignerCallback
} from './types'

export class VcIssuer<DIDDoc extends object> {
private readonly _issuerMetadata: CredentialIssuerMetadataOptsV1_0_13
Expand Down Expand Up @@ -667,6 +687,4 @@ export class VcIssuer<DIDDoc extends object> {
public get authorizationServerMetadata() {
return this._authorizationServerMetadata
}


}
3 changes: 1 addition & 2 deletions packages/issuer/lib/__tests__/VcIssuerBuilder.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { uuidv4 } from '@sphereon/oid4vc-common'
import { CredentialConfigurationSupportedV1_0_13, IssuerCredentialSubjectDisplay, IssueStatus, TokenErrorResponse } from '@sphereon/oid4vci-common'

import { AuthorizationServerMetadataBuilder } from '../builder/AuthorizationServerMetadataBuilder'
import { CredentialSupportedBuilderV1_13, VcIssuerBuilder } from '../index'
import { AuthorizationServerMetadataBuilder, CredentialSupportedBuilderV1_13, VcIssuerBuilder } from '../index'


const authorizationServerMetadata = new AuthorizationServerMetadataBuilder()
Expand Down
10 changes: 6 additions & 4 deletions packages/issuer/lib/builder/VcIssuerBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
AuthorizationServerMetadata,
CNonceState,
CredentialConfigurationSupportedV1_0_13,
CredentialIssuerMetadataOptsV1_0_13,
CredentialOfferSession,
IssuerMetadata,
IssuerMetadataV1_0_13,
Expand All @@ -12,7 +13,6 @@ import {
TxCode,
URIState
} from '@sphereon/oid4vci-common'
import { CredentialIssuerMetadataOptsV1_0_13 } from '@sphereon/oid4vci-common'

import { VcIssuer } from '../VcIssuer'
import { MemoryStates } from '../state-manager'
Expand Down Expand Up @@ -52,7 +52,7 @@ export class VcIssuerBuilder<DIDDoc extends object> {
this.issuerMetadataBuilder = builder
return this
}

public withDefaultCredentialOfferBaseUri(baseUri: string) {
this.defaultCredentialOfferBaseUri = baseUri
return this
Expand Down Expand Up @@ -184,8 +184,10 @@ export class VcIssuerBuilder<DIDDoc extends object> {
if (!metadata.credential_endpoint || !metadata.credential_issuer || !this.issuerMetadata.credential_configurations_supported) {
throw new Error(TokenErrorResponse.invalid_request)
}
return new VcIssuer(metadata as IssuerMetadataV1_0_13, this.authorizationServerMetadata as AuthorizationServerMetadata, {
//TODO: discuss this with Niels. I did not find this in the spec. but I think we should somehow communicate this
return new VcIssuer(metadata as IssuerMetadataV1_0_13,
this.authorizationServerMetadata as AuthorizationServerMetadata,
{
//TODO: discuss this with Niels. I did not find this in the spec. but I think we should somehow communicate this
...(this.txCode && { txCode: this.txCode }),
defaultCredentialOfferBaseUri: this.defaultCredentialOfferBaseUri,
credentialSignerCallback: this.credentialSignerCallback,
Expand Down
1 change: 1 addition & 0 deletions packages/issuer/lib/builder/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './CredentialSupportedBuilderV1_13'
export * from './VcIssuerBuilder'
export * from './IssuerMetadataBuilderV1_13'
export * from './DisplayBuilder'
export * from './AuthorizationServerMetadataBuilder'
2 changes: 1 addition & 1 deletion packages/issuer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"dependencies": {
"@sphereon/oid4vc-common": "workspace:*",
"@sphereon/oid4vci-common": "workspace:*",
"@sphereon/ssi-types": "0.30.1",
"@sphereon/ssi-types": "0.30.2-next.279",
"uuid": "^9.0.0"
},
"peerDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/oid4vci-common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
},
"dependencies": {
"@sphereon/oid4vc-common": "workspace:*",
"@sphereon/ssi-types": "0.30.1",
"@sphereon/ssi-types": "0.30.2-next.279",
"cross-fetch": "^3.1.8",
"debug": "^4.3.5",
"jwt-decode": "^4.0.0",
Expand Down
9 changes: 8 additions & 1 deletion packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,14 @@ export const assertValidVerifiablePresentations = async (args: {
if (!presentations || (Array.isArray(presentations) && presentations.length === 0)) {
return Promise.reject(Error('missing presentation(s)'))
}
const presentationsArray = Array.isArray(presentations) ? presentations : [presentations]

// Handle mdocs, keep them out of pex
let presentationsArray = (Array.isArray(presentations) ? presentations : [presentations])
if (presentationsArray.every(p => p.format === 'mso_mdoc')) {
return
}
presentationsArray = presentationsArray.filter((p) => p.format !== 'mso_mdoc')

if (
(!args.presentationDefinitions || args.presentationDefinitions.filter((a) => a.definition).length === 0) &&
(!presentationsArray || (Array.isArray(presentationsArray) && presentationsArray.filter((vp) => vp.presentation).length === 0))
Expand Down
3 changes: 2 additions & 1 deletion packages/siop-oid4vp/lib/request-object/Payload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ export const createRequestObjectPayload = async (opts: CreateAuthorizationReques
response_type: payload.response_type ?? ResponseType.ID_TOKEN,
scope: payload.scope,
//TODO implement /.well-known/openid-federation support in the OP side to resolve the client_id (URL) and retrieve the metadata
client_id: clientId,
client_id_scheme: payload.client_id_scheme,
...(clientId && { client_id: clientId }),
...(payload.entity_id && { entity_id: payload.entity_id }),
...(payload.redirect_uri && { redirect_uri: payload.redirect_uri }),
...(payload.response_uri && { response_uri: payload.response_uri }),
response_mode: payload.response_mode ?? ResponseMode.DIRECT_POST,
Expand Down
9 changes: 9 additions & 0 deletions packages/siop-oid4vp/lib/rp/RPBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export class RPBuilder {

clientMetadata?: ClientMetadataOpts = undefined
clientId: string
entityId: string
clientIdScheme: string

hasher: Hasher
Expand Down Expand Up @@ -83,6 +84,14 @@ export class RPBuilder {
return this
}

withEntityId(entityId: string, targets?: PropertyTargets): RPBuilder {
this._authorizationRequestPayload.entity_id = assignIfAuth({ propertyValue: entityId, targets }, false)
this._requestObjectPayload.entity_id = assignIfRequestObject({ propertyValue: entityId, targets }, true)
this.entityId = entityId
return this
}


withIssuer(issuer: ResponseIss, targets?: PropertyTargets): RPBuilder {
this._authorizationRequestPayload.iss = assignIfAuth({ propertyValue: issuer, targets }, false)
this._requestObjectPayload.iss = assignIfRequestObject({ propertyValue: issuer, targets }, true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,10 @@ export const AuthorizationRequestPayloadVD12OID4VPD20SchemaObj = {
"type": "string",
"const": "x509_san_uri"
},
{
"type": "string",
"const": "entity_id"
},
{
"type": "string",
"const": "verifier_attestation"
Expand Down
2 changes: 1 addition & 1 deletion packages/siop-oid4vp/lib/types/Errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ enum SIOPErrors {
MISSING_ATTESTATION_JWT_WITH_CLIENT_ID_SCHEME_ATTESTATION = `Missing jwt header jwt with client_id_scheme 'verifier_attestation'.`,
MISSING_ATTESTATION_JWT_TYP = `Attestation JWT missing typ 'verifier-attestation+jwt'.`,
INVALID_CLIENT_ID_SCHEME = 'Invalid client_id_scheme.',
INVALID_REQUEST_OBJECT_ENTITY_ID_SCHEME_CLIENT_ID = `Request Object uses client_id_scheme 'entity_id', but the client_id is not a string.`,
INVALID_REQUEST_OBJECT_ENTITY_ID_SCHEME_CLIENT_ID = `Request Object uses client_id_scheme 'entity_id', but the entity_id is missing or not an https endpoint.`,
EXPIRED = 'The token has expired',
INVALID_AUDIENCE = 'Audience is invalid. Should be a string value.',
NO_AUDIENCE = 'No audience found in JWT payload or not configured',
Expand Down
3 changes: 2 additions & 1 deletion packages/siop-oid4vp/lib/types/SIOP.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export interface RequestObjectPayload extends RequestCommonPayload, JWTPayload {
response_type: ResponseType | string // REQUIRED. Constant string value id_token.
client_id: string // REQUIRED. RP's identifier at the Self-Issued OP.
client_id_scheme?: ClientIdScheme // The client_id_scheme enables deployments of this specification to use different mechanisms to obtain and validate metadata of the Verifier beyond the scope of [RFC6749]. The term client_id_scheme is used since the Verifier is acting as an OAuth 2.0 Client.
entity_id?: string // OPTIONAL for OIDF
client_metadata: ClientMetadataOpts
redirect_uri?: string // REQUIRED before OID4VP v18, now optional because of response_uri. URI to which the Self-Issued OP Response will be sent
response_uri?: string // New since OID4VP18 OPTIONAL. The Response URI to which the Wallet MUST send the Authorization Response using an HTTPS POST request as defined by the Response Mode direct_post. The Response URI receives all Authorization Response parameters as defined by the respective Response Type. When the response_uri parameter is present, the redirect_uri Authorization Request parameter MUST NOT be present. If the redirect_uri Authorization Request parameter is present when the Response Mode is direct_post, the Wallet MUST return an invalid_request Authorization Response error.
Expand Down Expand Up @@ -101,7 +102,7 @@ export interface AuthorizationRequestPayloadVD12OID4VPD20
}

export type ClientIdSchemeOID4VPD18 = 'pre-registered' | 'redirect_uri' | 'entity_id' | 'did'
export type ClientIdSchemeOID4VPD20 = ClientIdSchemeOID4VPD18 | 'x509_san_dns' | 'x509_san_uri' | 'verifier_attestation'
export type ClientIdSchemeOID4VPD20 = ClientIdSchemeOID4VPD18 | 'x509_san_dns' | 'x509_san_uri' | 'entity_id' | 'verifier_attestation'
export type ClientIdScheme = ClientIdSchemeOID4VPD18 | ClientIdSchemeOID4VPD20

// https://openid.bitbucket.io/connect/openid-connect-self-issued-v2-1_0.html#section-10
Expand Down
6 changes: 3 additions & 3 deletions packages/siop-oid4vp/lib/types/VpJwtVerifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,11 @@ export const getRequestObjectJwtVerifier = async (
// If the Wallet cannot establish trust, it MUST refuse the request.
return { method: 'jwk', type, jwk: attestationPayload.cnf['jwk'] as JWK, alg }
} else if (clientIdScheme === 'entity_id') {
if (!clientId.startsWith('http')) {
const entityId = jwt.payload.entity_id
if (!entityId || !entityId.startsWith('https')) {
throw new Error(SIOPErrors.INVALID_REQUEST_OBJECT_ENTITY_ID_SCHEME_CLIENT_ID)
}

return { method: 'openid-federation', type, entityId: clientId }
return { method: 'openid-federation', type, entityId }
}

throw new Error(SIOPErrors.INVALID_CLIENT_ID_SCHEME)
Expand Down
2 changes: 1 addition & 1 deletion packages/siop-oid4vp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"@sphereon/oid4vc-common": "workspace:*",
"@sphereon/pex": "5.0.0-unstable.24",
"@sphereon/pex-models": "^2.3.1",
"@sphereon/ssi-types": "0.30.2-next.129",
"@sphereon/ssi-types": "0.30.2-next.279",
"cross-fetch": "^4.0.0",
"debug": "^4.3.5",
"events": "^3.3.0",
Expand Down
Loading

0 comments on commit 7be2c0d

Please sign in to comment.