Skip to content

Commit

Permalink
feat: support for OIDVP 20 and client_id_schemes
Browse files Browse the repository at this point in the history
  • Loading branch information
auer-martin committed Jul 11, 2024
1 parent 70508a5 commit d0823e4
Show file tree
Hide file tree
Showing 18 changed files with 1,404 additions and 55 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ dist
node_modules
coverage
*.log
*.tsimp
/src/schemas/validation/schemaValidation.js
11 changes: 11 additions & 0 deletions generator/schemaGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,21 @@ const authorizationRequestPayloadVD12OID4VPD18 = {
skipTypeCheck: true,
};

const authorizationRequestPayloadVD12OID4VPD20 = {
path: '../src/types/SIOP.types.ts',
tsconfig: 'tsconfig.json',
type: 'AuthorizationRequestPayloadVD12OID4VPD20', // Or <type-name> if you want to generate schema for that one type only
schemaId: 'AuthorizationRequestPayloadVD12OID4VPD20Schema',
outputPath: 'src/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts',
// outputConstName: 'AuthorizationRequestPayloadSchemaVD11',
skipTypeCheck: true,
};

let schemas: Schema[] = [
writeSchema(authorizationRequestPayloadVID1),
writeSchema(authorizationRequestPayloadVD11),
writeSchema(authorizationRequestPayloadVD12OID4VPD18),
writeSchema(authorizationRequestPayloadVD12OID4VPD20),
// writeSchema(requestOptsConf),
writeSchema(responseOptsConf),
writeSchema(rPRegistrationMetadataPayload),
Expand Down
13 changes: 11 additions & 2 deletions src/authorization-request/AuthorizationRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { RequestObject } from '../request-object';
import {
AuthorizationRequestPayload,
getJwtVerifierWithContext,
getRequestObjectJwtVerifier,
PassBy,
RequestObjectJwt,
RequestObjectPayload,
Expand Down Expand Up @@ -122,13 +123,21 @@ export class AuthorizationRequest {
if (parsedJwt) {
requestObjectPayload = parsedJwt.payload as RequestObjectPayload;

const jwtVerifier = await getJwtVerifierWithContext(parsedJwt, 'request-object');
const jwtVerifier = await getRequestObjectJwtVerifier({ ...parsedJwt, payload: requestObjectPayload }, { type: 'request-object', raw: jwt });
const result = await opts.verifyJwtCallback(jwtVerifier, { ...parsedJwt, raw: jwt });

if (!result) {
throw Error(SIOPErrors.ERROR_VERIFYING_SIGNATURE);
}

// verify the verifier attestation
if (requestObjectPayload.client_id_scheme === 'verifier_attestation') {
const jwtVerifier = await getJwtVerifierWithContext(parsedJwt, { type: 'verifier-attestation' });
const result = await opts.verifyJwtCallback(jwtVerifier, { ...parsedJwt, raw: jwt });
if (!result) {
throw Error(SIOPErrors.ERROR_VERIFYING_SIGNATURE);
}
}

if (this.hasRequestObject() && !this.payload.request_uri) {
// Put back the request object as that won't be present yet
this.payload.request = jwt;
Expand Down
17 changes: 16 additions & 1 deletion src/helpers/SIOPSpecVersion.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { AuthorizationRequestPayloadVD11Schema, AuthorizationRequestPayloadVID1Schema } from '../schemas';
import { AuthorizationRequestPayloadVD12OID4VPD18Schema } from '../schemas/validation/schemaValidation';
import {
AuthorizationRequestPayloadVD12OID4VPD18Schema,
AuthorizationRequestPayloadVD12OID4VPD20Schema,
} from '../schemas/validation/schemaValidation';
import { AuthorizationRequestPayload, ResponseMode, SupportedVersion } from '../types';
import errors from '../types/Errors';

Expand Down Expand Up @@ -33,6 +36,18 @@ function isID1Payload(authorizationRequest: AuthorizationRequestPayload) {
export const authorizationRequestVersionDiscovery = (authorizationRequest: AuthorizationRequestPayload): SupportedVersion[] => {
const versions = [];
const authorizationRequestCopy: AuthorizationRequestPayload = JSON.parse(JSON.stringify(authorizationRequest));
const vd13Validation = AuthorizationRequestPayloadVD12OID4VPD20Schema(authorizationRequestCopy);
if (vd13Validation) {
if (
!authorizationRequestCopy.registration_uri &&
!authorizationRequestCopy.registration &&
!(authorizationRequestCopy.claims && 'vp_token' in authorizationRequestCopy.claims) &&
authorizationRequestCopy.response_mode !== ResponseMode.POST // Post has been replaced by direct post
) {
versions.push(SupportedVersion.SIOPv2_D12_OID4VP_D20);
}
}

// todo: We could use v11 validation for v12 for now, as we do not differentiate in the schema at this point\
const vd12Validation = AuthorizationRequestPayloadVD12OID4VPD18Schema(authorizationRequestCopy);
if (vd12Validation) {
Expand Down
2 changes: 1 addition & 1 deletion src/helpers/jwtUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { jwtDecode } from 'jwt-decode';

import { JwtHeader, JwtPayload, SIOPErrors } from '../types';

export type JwtType = 'id-token' | 'request-object';
export type JwtType = 'id-token' | 'request-object' | 'verifier-attestation';

export type JwtProtectionMethod = 'did' | 'x5c' | 'jwk' | 'custom';

Expand Down
8 changes: 4 additions & 4 deletions src/id-token/IDToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,22 +157,22 @@ export class IDToken {

const parsedJwt = parseJWT(this._jwt);
this.assertValidResponseJWT(parsedJwt);
const idTokenPayload = parsedJwt.payload as IDTokenPayload;

const jwtVerifier = await getJwtVerifierWithContext(parsedJwt, 'request-object');
const jwtVerifier = await getJwtVerifierWithContext(parsedJwt, { type: 'id-token' });
const verificationResult = await verifyOpts.verifyJwtCallback(jwtVerifier, { ...parsedJwt, raw: this._jwt });
if (!verificationResult) {
throw Error(SIOPErrors.ERROR_VERIFYING_SIGNATURE);
}

const verPayload = parsedJwt.payload as IDTokenPayload;
this.assertValidResponseJWT({ header: parsedJwt.header, verPayload: verPayload, audience: verifyOpts.audience });
this.assertValidResponseJWT({ header: parsedJwt.header, verPayload: idTokenPayload, audience: verifyOpts.audience });
// Enforces verifyPresentationCallback function on the RP side,
if (!verifyOpts?.verification.presentationVerificationCallback) {
throw new Error(SIOPErrors.VERIFIABLE_PRESENTATION_VERIFICATION_FUNCTION_MISSING);
}
return {
jwt: this._jwt,
payload: { ...verPayload },
payload: { ...idTokenPayload },
verifyOpts,
};
}
Expand Down
2 changes: 1 addition & 1 deletion src/request-object/Payload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const createRequestObjectPayload = async (opts: CreateAuthorizationReques
scope: payload.scope ?? Scope.OPENID,
//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: opts.clientMetadata.client_id_scheme,
client_id_scheme: opts.requestObject.payload.client_id_scheme,
...(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
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export const AuthorizationRequestPayloadVD12OID4VPD18SchemaObj = {
"type": "string"
},
"client_id_scheme": {
"$ref": "#/definitions/ClientIdScheme"
"$ref": "#/definitions/ClientIdSchemeOID4VPD18"
},
"response_uri": {
"type": "string"
Expand Down Expand Up @@ -1056,15 +1056,13 @@ export const AuthorizationRequestPayloadVD12OID4VPD18SchemaObj = {
],
"additionalProperties": false
},
"ClientIdScheme": {
"ClientIdSchemeOID4VPD18": {
"type": "string",
"enum": [
"pre-registered",
"redirect_uri",
"entity_id",
"did",
"x509_san_dns",
"x509_san_uri"
"did"
]
}
}
Expand Down
Loading

0 comments on commit d0823e4

Please sign in to comment.