1
0
Форкнуть 0

Add support for SIOP presenting a json ld VC

This commit is contained in:
Ronny Bjones 2020-10-14 14:51:12 +00:00
Родитель 2cf815acb0
Коммит 8bc4daee70
21 изменённых файлов: 188 добавлений и 151 удалений

Просмотреть файл

@ -34,7 +34,7 @@ console.log(`VCs claims: ${JSON.stringify(validationResult.claims.vcs[0].vc)}`);
```javascript
const vcValidator = new ValidationBuilder()
.inputIs(TokenType.verifiableCredential)
.inputIs(TokenType.verifiableCredentialJwt)
.build();
const validationResult = await validator.validate(vc: string, expectedAudience: string, expectedIssuers: string[]);
```
@ -42,7 +42,7 @@ const validationResult = await validator.validate(vc: string, expectedAudience:
## Example: Validate a Verifiable Presentation
```javascript
const vpValidator = new ValidationBuilder()
.inputIs(TokenType.verifiablePresentation)
.inputIs(TokenType.verifiablePresentationJwt)
.build();
const validationResult = await validator.validate(vp: string, expectedAudience: string, expectedIssuer: string);
```

Просмотреть файл

@ -104,13 +104,13 @@ export default class Validator {
claimToken = <ClaimToken>(<any>response.validationResult)?.idTokens;
}
break;
case TokenType.verifiableCredential:
case TokenType.verifiableCredentialJwt:
response = await validator.validate(queue, queueItem!, siopDid!);
if (response.result) {
claimToken = <ClaimToken>(<any>response.validationResult)?.verifiableCredentials;
}
break;
case TokenType.verifiablePresentation:
case TokenType.verifiablePresentationJwt:
response = await validator.validate(queue, queueItem!, siopDid!);
break;
case TokenType.siopIssuance:
@ -284,7 +284,7 @@ export default class Validator {
if (statusUrl) {
// send the payload
payload.aud = statusUrl;
const siop = await this.builder.crypto.signingProtocol.sign(payload);
const siop = await this.builder.crypto.signingProtocol('JOSE').sign(payload);
const serialized = await siop.serialize();
console.log(`verifiablePresentation status check on ${statusUrl} ====> ${serialized}`);
@ -348,7 +348,7 @@ export default class Validator {
return siop.validationResponse.did;
})[0];
if (!did) {
did = queue.items.filter((item) => item.validatedToken?.type === TokenType.verifiableCredential).map((vc) => {
did = queue.items.filter((item) => item.validatedToken?.type === TokenType.verifiableCredentialJwt).map((vc) => {
return vc.validatedToken?.decodedToken.aud;
})[0];
}
@ -380,7 +380,7 @@ export default class Validator {
}
// get verifiable credentials
tokens = queue.items.filter((item) => item.validatedToken?.type === TokenType.verifiableCredential)
tokens = queue.items.filter((item) => item.validatedToken?.type === TokenType.verifiableCredentialJwt)
if (tokens && tokens.length > 0) {
validationResult.verifiableCredentials = {};
for (let inx = 0; inx < tokens.length; inx++) {
@ -389,7 +389,7 @@ export default class Validator {
}
// get verifiable presentations
tokens = queue.items.filter((item) => item.validatedToken?.type === TokenType.verifiablePresentation)
tokens = queue.items.filter((item) => item.validatedToken?.type === TokenType.verifiablePresentationJwt)
if (tokens && tokens.length > 0) {
validationResult.verifiablePresentations = {};
for (let inx = 0; inx < tokens.length; inx++) {

Просмотреть файл

@ -138,8 +138,8 @@ export default class ValidatorBuilder {
this._tokenValidators = {
selfIssued: new SelfIssuedTokenValidator(validatorOptions, <IExpectedSelfIssued> {type: TokenType.selfIssued}),
idToken: new IdTokenTokenValidator(validatorOptions, <IExpectedIdToken> {type: TokenType.idToken, configuration: this._trustedIssuerConfigurationsForIdTokens}),
verifiableCredential: new VerifiableCredentialTokenValidator(validatorOptions, <IExpectedVerifiableCredential> {type: TokenType.verifiableCredential, contractIssuers: this._trustedIssuersForVerifiableCredentials}),
verifiablePresentation: new VerifiablePresentationTokenValidator(validatorOptions, this.crypto, <IExpectedVerifiablePresentation> {type: TokenType.verifiablePresentation, didAudience: this.crypto.builder.did}),
verifiableCredentialJwt: new VerifiableCredentialTokenValidator(validatorOptions, <IExpectedVerifiableCredential> {type: TokenType.verifiableCredentialJwt, contractIssuers: this._trustedIssuersForVerifiableCredentials}),
verifiablePresentationJwt: new VerifiablePresentationTokenValidator(validatorOptions, this.crypto, <IExpectedVerifiablePresentation> {type: TokenType.verifiablePresentationJwt, didAudience: this.crypto.builder.did}),
siopPresentationAttestation: new SiopTokenValidator(validatorOptions, <IExpectedSiop> {type: TokenType.siopPresentationAttestation, audience: this._audienceUrl}),
siop: new SiopTokenValidator(validatorOptions, <IExpectedSiop> {type: TokenType.siop, audience: this._audienceUrl}),
siopPresentationExchange: new SiopTokenValidator(validatorOptions, <IExpectedSiop> {type: TokenType.siopPresentationExchange, audience: this._audienceUrl}),
@ -175,14 +175,14 @@ export default class ValidatorBuilder {
this._trustedIssuersForVerifiableCredentials = issuers;
if (this._tokenValidators) {
// Make sure existing expected gets updated
const vcValidator = this._tokenValidators[TokenType.verifiableCredential];
const vcValidator = this._tokenValidators[TokenType.verifiableCredentialJwt];
if (vcValidator) {
const validatorOptions: IValidatorOptions = {
resolver: this.resolver,
crypto: this._crypto
};
const expected: IExpectedVerifiableCredential = {type: TokenType.verifiableCredential, contractIssuers: issuers};
this._tokenValidators[TokenType.verifiableCredential] = new VerifiableCredentialTokenValidator(validatorOptions, expected);
const expected: IExpectedVerifiableCredential = {type: TokenType.verifiableCredentialJwt, contractIssuers: issuers};
this._tokenValidators[TokenType.verifiableCredentialJwt] = new VerifiableCredentialTokenValidator(validatorOptions, expected);
}
}
return this;

Просмотреть файл

@ -33,7 +33,7 @@ export default class VerifiableCredentialTokenValidator implements ITokenValidat
* @param siopDid needs to be equal to audience of VC
*/
public async validate(_queue: ValidationQueue, queueItem: ValidationQueueItem, siopDid: string): Promise<IValidationResponse> {
const options = new ValidationOptions(this.validatorOption, TokenType.verifiableCredential);
const options = new ValidationOptions(this.validatorOption, TokenType.verifiableCredentialJwt);
const validator = new VerifiableCredentialValidation(options, this.expected);
const validationResult = await validator.validate(queueItem.tokenToValidate.rawToken, siopDid);
@ -53,7 +53,7 @@ export default class VerifiableCredentialTokenValidator implements ITokenValidat
* Gets the type of token to validate
*/
public get isType(): TokenType {
return TokenType.verifiableCredential;
return TokenType.verifiableCredentialJwt;
}
}

Просмотреть файл

@ -32,7 +32,7 @@ export default class VerifiablePresentationTokenValidator implements ITokenValid
* @param siopDid needs to be equal to audience of VP
*/
public async validate(queue: ValidationQueue, queueItem: ValidationQueueItem, siopDid: string): Promise<IValidationResponse> {
const options = new ValidationOptions(this.validatorOption, TokenType.verifiablePresentation);
const options = new ValidationOptions(this.validatorOption, TokenType.verifiablePresentationJwt);
const validator = new VerifiablePresentationValidation(options, this.expected, siopDid, queueItem.id);
let validationResult = await validator.validate(queueItem.tokenToValidate.rawToken);
@ -73,7 +73,7 @@ export default class VerifiablePresentationTokenValidator implements ITokenValid
* Gets the type of token to validate
*/
public get isType(): TokenType {
return TokenType.verifiablePresentation;
return TokenType.verifiablePresentationJwt;
}
}

Просмотреть файл

@ -76,4 +76,9 @@ export interface IValidationResponse extends IResponse {
* the Json Web Token Id of the incoming token
*/
jti?: string;
/**
* The used payload protection protocol
*/
payloadProtectionProtocol?: string;
}

Просмотреть файл

@ -1,9 +1,9 @@
import base64url from 'base64url';
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IExpectedSiop } from '../index';
import base64url from 'base64url';
const bs58 = require('bs58')
/**
* Class to model the Linked Data crypto suites public keys
@ -118,6 +118,6 @@ export default class LinkedDataCryptoSuitePublicKey {
* @param data to convert.
*/
private static decodeBase58To64Url(data: string): string {
return data;
return base64url.encode(bs58.decode(data));
}
}

Просмотреть файл

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { DidDocument, IDidResolveResult } from '@decentralized-identity/did-common-typescript';
import { IPayloadProtectionSigning } from 'verifiablecredentials-crypto-sdk-typescript';
import { IPayloadProtectionSigning, JoseBuilder } from 'verifiablecredentials-crypto-sdk-typescript';
import { IValidationOptions } from '../options/IValidationOptions';
import IValidatorOptions from '../options/IValidatorOptions';
import ValidationOptions from '../options/ValidationOptions';
@ -43,33 +43,49 @@ export class ValidationHelpers {
* @returns validationResponse.payloadObject The parsed payload
*/
public async getTokenObject(validationResponse: IValidationResponse, token: string): Promise<IValidationResponse> {
let tokenPayload: Buffer;
const self: any = this;
validationResponse.didSignature = undefined;
// check for json ld proofs
try {
validationResponse.didSignature = await (self as ValidationOptions).validatorOptions.crypto.signingProtocol.deserialize(token);
if (!validationResponse.didSignature) {
return {
result: false,
detailedError: `The signature in the ${(self as ValidationOptions).tokenType} has an invalid format`,
status: 403
};
}
JSON.parse(token);
const kid = validationResponse.didSignature.signatureProtectedHeader?.kid;
validationResponse.didKid = kid;
if (!validationResponse.didKid) {
// instantiate IPayloadProtectionSigning
validationResponse.didSignature = await (self as ValidationOptions).validatorOptions.crypto.signingProtocol(JoseBuilder.JSONLDProofs).deserialize(token);
validationResponse.payloadProtectionProtocol = JoseBuilder.JSONLDProofs;
} catch (exception) {
console.log('Failing to decode json ld proof');
}
if (!validationResponse.didSignature) {
// check for compact JWT tokens
try {
// instantiate IPayloadProtectionSigning
validationResponse.didSignature = await (self as ValidationOptions).validatorOptions.crypto.signingProtocol(JoseBuilder.JWT).deserialize(token);
validationResponse.payloadProtectionProtocol = JoseBuilder.JWT;
} catch (exception) {
return {
result: false,
detailedError: `The protected header in the ${(self as ValidationOptions).tokenType} does not contain the kid`,
status: 403
};
detailedError: `The ${(self as ValidationOptions).tokenType} could not be deserialized`,
status: 400
};
}
} catch (err) {
console.error(err);
}
if (!validationResponse.didSignature) {
return {
result: false,
detailedError: `The ${(self as ValidationOptions).tokenType} could not be deserialized`,
status: 400
detailedError: `The signature in the ${(self as ValidationOptions).tokenType} has an invalid format`,
status: 403
};
}
const kid = validationResponse.didSignature.signatureProtectedHeader?.kid;
validationResponse.didKid = kid;
if (!validationResponse.didKid) {
return {
result: false,
detailedError: `The protected header in the ${(self as ValidationOptions).tokenType} does not contain the kid`,
status: 403
};
}
try {
@ -538,8 +554,8 @@ export class ValidationHelpers {
validationResponse.result = true;
validationResponse.detailedError = '';
validationResponse.validationResult = {idTokens: <any>token};
validationResponse.validationResult = { idTokens: <any>token };
return validationResponse;
} catch (err) {
console.error(err);
@ -563,7 +579,7 @@ export class ValidationHelpers {
try {
// Get token and check signature
validationResponse = await (self as IValidationOptions).getTokenObjectDelegate(validationResponse, token.rawToken);
const validation = await (self as ValidationOptions).validatorOptions.crypto.signingProtocol.verify([key]);
const validation = await (self as ValidationOptions).validatorOptions.crypto.signingProtocol(validationResponse.payloadProtectionProtocol!).verify([key]);
if (!validation) {
return {
result: false,

Просмотреть файл

@ -44,12 +44,17 @@ export enum TokenType {
/**
* Token is verifiable presentation
*/
verifiablePresentation = 'verifiablePresentation',
verifiablePresentationJwt = 'verifiablePresentationJwt',
/**
* Token is verifiable credential
* Token is verifiable credential in JWT format
*/
verifiableCredential = 'verifiableCredential',
verifiableCredentialJwt = 'verifiableCredentialJwt',
/**
* Token is verifiable credential in json ld format
*/
verifiableCredentialjsonLd = 'verifiableCredentialjsonLd',
/**
* Token is verifiable credential
@ -139,36 +144,44 @@ export default class ClaimToken {
* Factory class to create a ClaimToken containing the token type, raw token and decoded payload
* @param token to check for type
*/
public static create(token: string, id?: string): ClaimToken {
// Deserialize the token
const payload = ClaimToken.getTokenPayload(token);
public static create(token: string | object, id?: string): ClaimToken {
// Check type of token
if (payload.iss === VerifiableCredentialConstants.TOKEN_SI_ISS) {
if (payload.contract) {
return new ClaimToken(TokenType.siopIssuance, token, id);
} else if (payload.presentation_submission) {
return new ClaimToken(TokenType.siopPresentationExchange, token, id);
} else if (payload.attestations) {
return new ClaimToken(TokenType.siopPresentationAttestation, token, id);
} else {
return new ClaimToken(TokenType.siop, token, id);
// check for json LD
if ((<any>token)['\@context']) {
throw new Error();
return new ClaimToken(TokenType.verifiableCredentialjsonLd, <any>'');
} else {
// compact jwt
// Deserialize the token
const payload = ClaimToken.getTokenPayload(<string>token);
// Check type of token
if (payload.iss === VerifiableCredentialConstants.TOKEN_SI_ISS) {
if (payload.contract) {
return new ClaimToken(TokenType.siopIssuance, <string>token, id);
} else if (payload.presentation_submission) {
return new ClaimToken(TokenType.siopPresentationExchange, <string>token, id);
} else if (payload.attestations) {
return new ClaimToken(TokenType.siopPresentationAttestation, <string>token, id);
} else {
return new ClaimToken(TokenType.siop, <string>token, id);
}
}
}
if (payload.vc) {
return new ClaimToken(TokenType.verifiableCredential, token, id);
}
if (payload.vp) {
return new ClaimToken(TokenType.verifiablePresentation, token, id);
}
if (payload.vc) {
return new ClaimToken(TokenType.verifiableCredentialJwt, <string>token, id);
}
if (payload.vp) {
return new ClaimToken(TokenType.verifiablePresentationJwt, <string>token, id);
}
// Check for signature
if (ClaimToken.tokenSignature(token)) {
return new ClaimToken(TokenType.idToken, token, id);
}
// Check for signature
if (ClaimToken.tokenSignature(<string>token)) {
return new ClaimToken(TokenType.idToken, <string>token, id);
}
return new ClaimToken(TokenType.selfIssued, token, id);
return new ClaimToken(TokenType.selfIssued, <string>token, id);
}
}
/**
@ -221,10 +234,14 @@ export default class ClaimToken {
const foundToken = tokenFinder[0];
const claimToken = ClaimToken.create(foundToken);
decodedTokens[item.id] = claimToken;
} else if (tokenFinder[0]['\@context']) {
const foundToken = tokenFinder[0];
const claimToken = ClaimToken.create(foundToken);
decodedTokens[item.id] = claimToken;
}
} else {
throw new Error(`The SIOP presentation exchange response has descriptor_map with id '${item.id}'. No path property found.`);
}
}
}
}
return decodedTokens;

Просмотреть файл

@ -28,7 +28,7 @@
"jasmine-spec-reporter": "^4.2.1",
"jasmine-ts": "0.3.0",
"node-fetch": "2.6.0",
"nyc": "^14.1.1",
"nyc": "^15.1.0",
"source-map-support": "0.5.12",
"ts-node": "8.1.0",
"tslint": "5.16.0",
@ -40,6 +40,7 @@
"@azure/identity": "1.0.0",
"@decentralized-identity/did-common-typescript": "0.1.19",
"base64url": "3.0.1",
"bs58": "4.0.1",
"clone": "2.1.2",
"deep-property-access": "1.0.1",
"es6-promise": "^4.2.8",
@ -47,7 +48,7 @@
"jsonpath": "1.0.2",
"multihashes": "0.4.14",
"uuid": "7.0.1",
"verifiablecredentials-crypto-sdk-typescript": "1.1.11-preview.5"
"verifiablecredentials-crypto-sdk-typescript": "1.1.11-preview.6"
},
"nyc": {
"extension": [

Просмотреть файл

@ -23,10 +23,10 @@ import base64url from 'base64url';
expect(claimToken.type).toEqual(TokenType.siopPresentationAttestation);
claimToken = new ClaimToken(TokenType.siopPresentationExchange, token, configuration);
expect(claimToken.type).toEqual(TokenType.siopPresentationExchange);
claimToken = new ClaimToken(TokenType.verifiableCredential, token, configuration);
expect(claimToken.type).toEqual(TokenType.verifiableCredential);
claimToken = new ClaimToken(TokenType.verifiablePresentation, token, configuration);
expect(claimToken.type).toEqual(TokenType.verifiablePresentation);
claimToken = new ClaimToken(TokenType.verifiableCredentialJwt, token, configuration);
expect(claimToken.type).toEqual(TokenType.verifiableCredentialJwt);
claimToken = new ClaimToken(TokenType.verifiablePresentationJwt, token, configuration);
expect(claimToken.type).toEqual(TokenType.verifiablePresentationJwt);
delete payload.vc;
token = base64url.encode(JSON.stringify(header)) + '.' + base64url.encode(JSON.stringify(payload)) + '.';
claimToken = new ClaimToken(TokenType.selfIssued, token, configuration);

Просмотреть файл

@ -2,7 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Subtle } from 'verifiablecredentials-crypto-sdk-typescript';
import { JoseBuilder, Subtle } from 'verifiablecredentials-crypto-sdk-typescript';
import TestSetup from './TestSetup';
import { DidDocument } from '@decentralized-identity/did-common-typescript';
import ClaimToken, { TokenType } from '../lib/verifiable_credential/ClaimToken';
@ -185,9 +185,9 @@ export class IssuanceHelpers {
const keyId = new KeyReference(jwkPrivate.kid);
await setup.keyStore.save(keyId, <any>jwkPrivate);
setup.validatorOptions.crypto.builder.useSigningKeyReference(keyId);
setup.validatorOptions.crypto.signingProtocol.builder.useKid(keyId.keyReference);
const signature = await setup.validatorOptions.crypto.signingProtocol.sign(payload);
const token = await setup.validatorOptions.crypto.signingProtocol.serialize();
setup.validatorOptions.crypto.signingProtocol(JoseBuilder.JWT).builder.useKid(keyId.keyReference);
const signature = await setup.validatorOptions.crypto.signingProtocol(JoseBuilder.JWT).sign(payload);
const token = await setup.validatorOptions.crypto.signingProtocol(JoseBuilder.JWT).serialize();
let claimToken = ClaimToken.create(token, configuration);
return claimToken;
}
@ -267,8 +267,8 @@ export class IssuanceHelpers {
<IExpectedIdToken>{ type: TokenType.idToken, configuration: idTokenConfiguration, audience: setup.AUDIENCE },
<IExpectedSiop>{ type: TokenType.siopIssuance, audience: setup.AUDIENCE },
<IExpectedSiop>{ type: TokenType.siopPresentationAttestation, audience: setup.AUDIENCE },
<IExpectedVerifiablePresentation>{ type: TokenType.verifiablePresentation, didAudience: setup.defaultIssuerDid },
<IExpectedVerifiableCredential>{ type: TokenType.verifiableCredential, contractIssuers: vcContractIssuers }
<IExpectedVerifiablePresentation>{ type: TokenType.verifiablePresentationJwt, didAudience: setup.defaultIssuerDid },
<IExpectedVerifiableCredential>{ type: TokenType.verifiableCredentialJwt, contractIssuers: vcContractIssuers }
];
const siopRequest = {

Просмотреть файл

@ -23,7 +23,7 @@ describe('LinkedDataCryptoSuitePublicKey', () => {
expect(jwk.crv).toEqual('ed25519');
expect(jwk.kty).toEqual('OKP');
expect(jwk.use).toEqual('sig');
expect(jwk.x).toEqual('H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV');
expect(jwk.x).toEqual('7kqc5NnojHJHZ11Ec5cGCLMIKgJVDBKhrAbu9YrfVFg');
didDocumentPublicKey = {
"@context": ["https://w3id.org/security/v1"],

Просмотреть файл

@ -6,7 +6,7 @@
import base64url from 'base64url';
import RequestorHelper from './RequestorHelper';
import ResponderHelper from './ResponderHelper';
import { ValidatorBuilder, PresentationDefinitionModel, IRequestorPresentationExchange } from '../lib';
import { ValidatorBuilder, PresentationDefinitionModel, IRequestorPresentationExchange, JoseBuilder } from '../lib';
import VerifiableCredentialConstants from '../lib/verifiable_credential/VerifiableCredentialConstants';
import TokenGenerator from './TokenGenerator';
import PresentationDefinition from './models/PresentationDefinitionSample1'
@ -45,7 +45,7 @@ describe('PresentationExchange', () => {
console.log(request.rawToken);
});
fit('should create a response and validate', async () => {
it('should create a response and validate', async () => {
const request: any = await requestor.createPresentationExchangeRequest();
expect(request.rawToken).toBeDefined();
@ -57,35 +57,33 @@ describe('PresentationExchange', () => {
.useTrustedIssuersForVerifiableCredentials({ IdentityCard: [responder.generator.crypto.builder.did!] })
.build();
let result = await validator.validate(response.rawToken);
expect(result.result).toBeTruthy();
expect(result.result).toBeTruthy(result.detailedError);
// Negative cases
//Remove presentation_submission
let responsePayload = clone(response.decodedToken);
delete responsePayload.presentation_submission;
let siop = await (await responder.crypto.signingProtocol.sign(responsePayload)).serialize();
let siop = await (await responder.crypto.signingProtocol(JoseBuilder.JWT).sign(responsePayload)).serialize();
result = await validator.validate(siop);
expect(result.result).toBeFalsy();
expect(result.detailedError).toEqual('siop does not has a TokenValidator');
expect(result.result).toBeFalsy('Remove presentation_submission');
expect(result.detailedError).toEqual(`Verifiable credential 'IdentityCard' is missing from the input request`);
//Remove tokens
responsePayload = clone(response.decodedToken);
delete responsePayload.presentation_submission.attestations;
siop = await (await responder.crypto.signingProtocol.sign(responsePayload)).serialize();
siop = await (await responder.crypto.signingProtocol(JoseBuilder.JWT).sign(responsePayload)).serialize();
result = await validator.validate(siop);
expect(result.result).toBeFalsy();
expect(result.result).toBeFalsy('Remove tokens');
expect(result.detailedError).toEqual(`The SIOP presentation exchange response has descriptor_map with id 'IdentityCard'. This path '$.presentation_submission.attestations.presentations.IdentityCard' did not return a token.`);
//Remove path
responsePayload = clone(response.decodedToken);
delete responsePayload.presentation_submission.descriptor_map[0].path;
siop = await (await responder.crypto.signingProtocol.sign(responsePayload)).serialize();
siop = await (await responder.crypto.signingProtocol(JoseBuilder.JWT).sign(responsePayload)).serialize();
result = await validator.validate(siop);
expect(result.result).toBeFalsy();
expect(result.result).toBeFalsy('Remove path');
expect(result.detailedError).toEqual(`The SIOP presentation exchange response has descriptor_map with id 'IdentityCard'. No path property found.`);
});
it('should populate the model', () => {

Просмотреть файл

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { CryptoBuilder, KeyReference, LongFormDid, KeyUse, TokenType, ClaimToken } from '../lib/index';
import { CryptoBuilder, KeyReference, LongFormDid, KeyUse, TokenType, ClaimToken, JoseBuilder } from '../lib/index';
import RequestorHelper from './RequestorHelper'
import TokenGenerator from './TokenGenerator';
import ITestModel from './models/ITestModel';
@ -66,8 +66,8 @@ export default class ResponderHelper {
this.responseDefinition.responseStatus[presentation].iss = this.generator.crypto.builder.did;
// Sign the receipts
await this.generator.crypto.signingProtocol.sign(this.responseDefinition.responseStatus[presentation]);
statusReceipts.receipt[jti] = await this.generator.crypto.signingProtocol.serialize();
await this.generator.crypto.signingProtocol(JoseBuilder.JWT).sign(this.responseDefinition.responseStatus[presentation]);
statusReceipts.receipt[jti] = await this.generator.crypto.signingProtocol(JoseBuilder.JWT).serialize();
const statusUrl = vcs.decodedToken.vc.credentialStatus.id;
TokenGenerator.fetchMock.post(statusUrl, statusReceipts, { overwriteRoutes: true });
@ -89,8 +89,8 @@ export default class ResponderHelper {
}
// Sign
await this.crypto.signingProtocol.sign(vpPayload);
presentations[presentation] = await this.crypto.signingProtocol.serialize();
await this.crypto.signingProtocol(JoseBuilder.JWT).sign(vpPayload);
presentations[presentation] = await this.crypto.signingProtocol(JoseBuilder.JWT).serialize();
}
}
@ -107,7 +107,7 @@ export default class ResponderHelper {
}
}
const token = await (await this.crypto.signingProtocol.sign(payload)).serialize();
const token = await (await this.crypto.signingProtocol(JoseBuilder.JWT).sign(payload)).serialize();
return new ClaimToken(TokenType.siopPresentationAttestation, token);
}

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -5,7 +5,7 @@
import { CryptoBuilder, KeyReference, LongFormDid, KeyUse, ClaimToken, DidDocument, TokenType } from '../lib/index';
import RequestorHelper from './RequestorHelper';
import { KeyStoreOptions, JsonWebKey, Crypto } from 'verifiablecredentials-crypto-sdk-typescript';
import { KeyStoreOptions, JsonWebKey, Crypto, JoseBuilder } from 'verifiablecredentials-crypto-sdk-typescript';
import ResponderHelper from './ResponderHelper';
import ITestModel from './models/ITestModel';
@ -97,8 +97,8 @@ export default class TokenGenerator {
payload.iss = `${this.crypto.builder.did}`;
// Sign
await this.crypto.signingProtocol.sign(payload);
idTokens[configuration] = await this.crypto.signingProtocol.serialize();
await this.crypto.signingProtocol(JoseBuilder.JWT).sign(payload);
idTokens[configuration] = await this.crypto.signingProtocol(JoseBuilder.JWT).serialize();
}
}
}
@ -111,8 +111,8 @@ export default class TokenGenerator {
vcPayload.iss = `${this.crypto.builder.did}`;
// Sign
await this.crypto.signingProtocol.sign(vcPayload);
const token = await this.crypto.signingProtocol.serialize();
await this.crypto.signingProtocol(JoseBuilder.JWT).sign(vcPayload);
const token = await this.crypto.signingProtocol(JoseBuilder.JWT).serialize();
return ClaimToken.create(token);
}
@ -144,7 +144,7 @@ export default class TokenGenerator {
for (let inx = 0; inx < vc.length; inx++) {
(vpTemplate.vp.verifiableCredential as string[]).push(vc[inx].rawToken);
}
const token = await (await this.responder.crypto.signingProtocol.sign(vpTemplate)).serialize();
return new ClaimToken(TokenType.verifiablePresentation, token, '');
const token = await (await this.responder.crypto.signingProtocol(JoseBuilder.JWT).sign(vpTemplate)).serialize();
return new ClaimToken(TokenType.verifiablePresentationJwt, token, '');
}
}

Просмотреть файл

@ -22,7 +22,7 @@ import { IExpectedSiop, IExpectedIdToken, IExpectedAudience, IdTokenValidationRe
});
it('should test getTokenObject', async () => {
let [request, options, siopRequest] = await IssuanceHelpers.createRequest(setup, TokenType.verifiableCredential, true);
let [request, options, siopRequest] = await IssuanceHelpers.createRequest(setup, TokenType.verifiableCredentialJwt, true);
const validationResponse: IValidationResponse = {
status: 200,
result: true
@ -37,7 +37,7 @@ import { IExpectedSiop, IExpectedIdToken, IExpectedAudience, IdTokenValidationRe
response = await options.getTokenObjectDelegate(validationResponse, splitToken[0]);
expect(response.result).toBeFalsy();
expect(response.status).toEqual(400);
expect(response.detailedError).toEqual('The verifiableCredential could not be deserialized');
expect(response.detailedError).toEqual('The verifiableCredentialJwt could not be deserialized');
// missing kid
const header: any = JSON.parse(base64url.decode(splitToken[0]));
@ -45,11 +45,11 @@ import { IExpectedSiop, IExpectedIdToken, IExpectedAudience, IdTokenValidationRe
response = await options.getTokenObjectDelegate(validationResponse, `${base64url.encode(JSON.stringify(header))}.${splitToken[1]}.${splitToken[2]}`);
expect(response.result).toBeFalsy();
expect(response.status).toEqual(403);
expect(response.detailedError).toEqual('The protected header in the verifiableCredential does not contain the kid');
expect(response.detailedError).toEqual('The protected header in the verifiableCredentialJwt does not contain the kid');
});
it('should test resolveDid', async () => {
let [request, options, siopRequest] = await IssuanceHelpers.createRequest(setup, TokenType.verifiableCredential, true);
let [request, options, siopRequest] = await IssuanceHelpers.createRequest(setup, TokenType.verifiableCredentialJwt, true);
const validationResponse: IValidationResponse = {
status: 200,
result: true,
@ -85,7 +85,7 @@ import { IExpectedSiop, IExpectedIdToken, IExpectedAudience, IdTokenValidationRe
});
it('should not resolve resolveDid', async () => {
let [request, options, siopRequest] = await IssuanceHelpers.createRequest(setup, TokenType.verifiableCredential, true);
let [request, options, siopRequest] = await IssuanceHelpers.createRequest(setup, TokenType.verifiableCredentialJwt, true);
const validationResponse: IValidationResponse = {
status: 200,
result: true
@ -98,7 +98,7 @@ import { IExpectedSiop, IExpectedIdToken, IExpectedAudience, IdTokenValidationRe
});
it('should test validateDidSignatureDelegate', async () => {
let [request, options, siopRequest] = await IssuanceHelpers.createRequest(setup, TokenType.verifiableCredential, true);
let [request, options, siopRequest] = await IssuanceHelpers.createRequest(setup, TokenType.verifiableCredentialJwt, true);
let validationResponse: IValidationResponse = {
status: 200,
result: true,
@ -117,7 +117,7 @@ import { IExpectedSiop, IExpectedIdToken, IExpectedAudience, IdTokenValidationRe
response = await options.validateDidSignatureDelegate(validationResponse, validationResponse.didSignature as IPayloadProtectionSigning);
expect(response.result).toBeFalsy();
expect(response.status).toEqual(403);
expect(response.detailedError).toEqual('The signature on the payload in the verifiableCredential is invalid');
expect(response.detailedError).toEqual('The signature on the payload in the verifiableCredentialJwt is invalid');
// No signature
const splitToken = request.rawToken.split('.');
@ -125,7 +125,7 @@ import { IExpectedSiop, IExpectedIdToken, IExpectedAudience, IdTokenValidationRe
response = await options.validateDidSignatureDelegate(validationResponse, validationResponse.didSignature as IPayloadProtectionSigning);
expect(response.result).toBeFalsy();
expect(response.status).toEqual(403);
expect(response.detailedError).toEqual('The signature on the payload in the verifiableCredential is invalid');
expect(response.detailedError).toEqual('The signature on the payload in the verifiableCredentialJwt is invalid');
// no header
validationResponse = await options.getTokenObjectDelegate(validationResponse, `.${splitToken[1]}.${splitToken[2]}`);
@ -143,7 +143,7 @@ import { IExpectedSiop, IExpectedIdToken, IExpectedAudience, IdTokenValidationRe
});
it('should test checkTimeValidityOnTokenDelegate', () => {
const options = new ValidationOptions(setup.validatorOptions, TokenType.verifiableCredential);
const options = new ValidationOptions(setup.validatorOptions, TokenType.verifiableCredentialJwt);
// Set the payload
const validationResponse: IValidationResponse = {
@ -154,36 +154,36 @@ import { IExpectedSiop, IExpectedIdToken, IExpectedAudience, IdTokenValidationRe
validationResponse.payloadObject = JSON.parse('{"jti": "abcdefg"}');
let response = options.checkTimeValidityOnTokenDelegate(validationResponse);
expect(response.result).toBeTruthy();
expect(response.result).toBeTruthy(response.detailedError);
// Add exp
let exp = new Date().getTime() / 1000;
validationResponse.payloadObject = JSON.parse(`{"jti": "abcdefg", "exp": ${exp}}`);
response = options.checkTimeValidityOnTokenDelegate(validationResponse, 5);
expect(response.result).toBeTruthy();
expect(response.result).toBeTruthy(response.detailedError);
exp = (new Date().getTime() / 1000) - 10;
validationResponse.payloadObject = JSON.parse(`{"jti": "abcdefg", "exp": ${exp}}`);
response = options.checkTimeValidityOnTokenDelegate(validationResponse, 5);
expect(response.result).toBeFalsy();
expect(response.result).toBeFalsy('expired');
expect(response.status).toEqual(403);
expect(response.detailedError?.startsWith('The presented verifiableCredential is expired')).toBeTruthy();
expect(response.detailedError?.startsWith('The presented verifiableCredentialJwt is expired')).toBeTruthy();
// Add nbf
let nbf = new Date().getTime() / 1000;
validationResponse.payloadObject = JSON.parse(`{"jti": "abcdefg", "nbf": ${nbf}}`);
response = options.checkTimeValidityOnTokenDelegate(validationResponse, 5);
expect(response.result).toBeTruthy();
expect(response.result).toBeTruthy(response.detailedError);
nbf = (new Date().getTime() / 1000) + 10;
validationResponse.payloadObject = JSON.parse(`{"jti": "abcdefg", "nbf": ${nbf}}`);
response = options.checkTimeValidityOnTokenDelegate(validationResponse, 5);
expect(response.result).toBeFalsy();
expect(response.result).toBeFalsy('not yet valid');
expect(response.status).toEqual(403);
expect(response.detailedError?.startsWith('The presented verifiableCredential is not yet valid')).toBeTruthy();
expect(response.detailedError?.startsWith('The presented verifiableCredentialJwt is not yet valid')).toBeTruthy();
});
it('should test checkScopeValidityOnIdTokenDelegate', () => {
const options = new ValidationOptions(setup.validatorOptions, TokenType.verifiableCredential);
const options = new ValidationOptions(setup.validatorOptions, TokenType.verifiableCredentialJwt);
const issuer = 'iss';
const audience = 'aud'

Просмотреть файл

@ -75,8 +75,8 @@ describe('Validator', () => {
});
it('should validate verifiable credentials', async () => {
const [request, options, siop] = await IssuanceHelpers.createRequest(setup, TokenType.verifiableCredential, true);
const expected: any = siop.expected.filter((token: IExpectedVerifiableCredential) => token.type === TokenType.verifiableCredential)[0];
const [request, options, siop] = await IssuanceHelpers.createRequest(setup, TokenType.verifiableCredentialJwt, true);
const expected: any = siop.expected.filter((token: IExpectedVerifiableCredential) => token.type === TokenType.verifiableCredentialJwt)[0];
const tokenValidator = new VerifiableCredentialTokenValidator(setup.validatorOptions, expected);
expect(()=> tokenValidator.getTokens(<any>undefined, <any>undefined)).toThrowError('Not implemented');
@ -91,9 +91,9 @@ describe('Validator', () => {
});
it('should validate verifiable presentations', async () => {
const [request, options, siop] = await IssuanceHelpers.createRequest(setup, TokenType.verifiablePresentation, true);
const vcExpected: IExpectedVerifiableCredential = siop.expected.filter((token: IExpectedVerifiableCredential) => token.type === TokenType.verifiableCredential)[0];
const vpExpected: IExpectedVerifiablePresentation = siop.expected.filter((token: IExpectedVerifiablePresentation) => token.type === TokenType.verifiablePresentation)[0];
const [request, options, siop] = await IssuanceHelpers.createRequest(setup, TokenType.verifiablePresentationJwt, true);
const vcExpected: IExpectedVerifiableCredential = siop.expected.filter((token: IExpectedVerifiableCredential) => token.type === TokenType.verifiableCredentialJwt)[0];
const vpExpected: IExpectedVerifiablePresentation = siop.expected.filter((token: IExpectedVerifiablePresentation) => token.type === TokenType.verifiablePresentationJwt)[0];
// the map gets its key from the created request
const vcAttestationName = Object.keys(siop.attestations.presentations)[0];
@ -110,8 +110,8 @@ describe('Validator', () => {
.build();
// Check validator types
expect(vpValidator.isType).toEqual(TokenType.verifiablePresentation);
expect(vcValidator.isType).toEqual(TokenType.verifiableCredential);
expect(vpValidator.isType).toEqual(TokenType.verifiablePresentationJwt);
expect(vcValidator.isType).toEqual(TokenType.verifiableCredentialJwt);
// Check VP validator
let queue = new ValidationQueue();
@ -143,7 +143,7 @@ describe('Validator', () => {
queue.enqueueToken('vp', siop.vp);
result = await validator.validate(queue.getNextToken()!.tokenToValidate);
expect(result.result).toBeFalsy();
expect(result.detailedError).toEqual('verifiablePresentation does not has a TokenValidator');
expect(result.detailedError).toEqual('verifiablePresentationJwt does not has a TokenValidator');
// Test validator with missing VC validator
validator = new ValidatorBuilder(crypto)
@ -154,13 +154,13 @@ describe('Validator', () => {
queue.enqueueToken('vp', siop.vp);
result = await validator.validate(queue.getNextToken()!.tokenToValidate);
expect(result.result).toBeFalsy();
expect(result.detailedError).toEqual('verifiableCredential does not has a TokenValidator');
expect(result.detailedError).toEqual('verifiableCredentialJwt does not has a TokenValidator');
});
it('should validate presentation siop', async () => {
const [request, options, siop] = await IssuanceHelpers.createRequest(setup, TokenType.verifiablePresentation, false);
const [request, options, siop] = await IssuanceHelpers.createRequest(setup, TokenType.verifiablePresentationJwt, false);
const siopExpected = siop.expected.filter((token: IExpectedSiop) => token.type === TokenType.siopPresentationAttestation)[0];
const vcExpected = siop.expected.filter((token: IExpectedVerifiableCredential) => token.type === TokenType.verifiableCredential)[0];
const vcExpected = siop.expected.filter((token: IExpectedVerifiableCredential) => token.type === TokenType.verifiableCredentialJwt)[0];
// Check validator, only VCs in presentations
@ -200,10 +200,10 @@ describe('Validator', () => {
it('should validate siop with default validators', async () => {
const [request, options, siop] = await IssuanceHelpers.createRequest(setup, TokenType.verifiablePresentation, true);
const [request, options, siop] = await IssuanceHelpers.createRequest(setup, TokenType.verifiablePresentationJwt, true);
const siopExpected = siop.expected.filter((token: IExpectedSiop) => token.type === TokenType.siopIssuance)[0];
const vpExpected = siop.expected.filter((token: IExpectedVerifiableCredential) => token.type === TokenType.verifiablePresentation)[0];
const vcExpected = siop.expected.filter((token: IExpectedVerifiableCredential) => token.type === TokenType.verifiableCredential)[0];
const vpExpected = siop.expected.filter((token: IExpectedVerifiableCredential) => token.type === TokenType.verifiablePresentationJwt)[0];
const vcExpected = siop.expected.filter((token: IExpectedVerifiableCredential) => token.type === TokenType.verifiableCredentialJwt)[0];
const idTokenExpected = siop.expected.filter((token: IExpectedIdToken) => token.type === TokenType.idToken)[0];
const siExpected = siop.expected.filter((token: IExpectedSelfIssued) => token.type === TokenType.selfIssued)[0];
@ -250,12 +250,13 @@ describe('Validator', () => {
const jsonldProofProtocol = new JoseBuilder(crypto)
.uselinkedDataProofsProtocol('JcsEd25519Signature2020')
.build();
crypto.useSigningProtocol(jsonldProofProtocol);
crypto.useSigningProtocol(JoseBuilder.JSONLDProofs, jsonldProofProtocol);
// Check validator
let validator = new ValidatorBuilder(crypto)
.useAudienceUrl('https://verify.vc.capptoso.com:443/presentation-response')
.enableFeatureVerifiedCredentialsStatusCheck(false)
.useResolver(new ManagedHttpResolver('https://resolver.identity.foundation/1.0/identifiers/'))
.build();
expect(validator.resolver).toBeDefined();
@ -267,7 +268,6 @@ describe('Validator', () => {
const result = await validator.validate(req);
expect(result.result).toBeTruthy();
expect(result.status).toEqual(200);
});

Просмотреть файл

@ -18,8 +18,8 @@ import { TokenType, IExpectedVerifiableCredential, Validator } from '../lib';
});
it('should test validate', async () => {
const [request, options, siop] = await IssuanceHelpers.createRequest(setup, TokenType.verifiableCredential, true);
const expected = siop.expected.filter((token: IExpectedVerifiableCredential) => token.type === TokenType.verifiableCredential)[0];
const [request, options, siop] = await IssuanceHelpers.createRequest(setup, TokenType.verifiableCredentialJwt, true);
const expected = siop.expected.filter((token: IExpectedVerifiableCredential) => token.type === TokenType.verifiableCredentialJwt)[0];
let validator = new VerifiableCredentialValidation(options, expected);
let response = await validator.validate(siop.vc.rawToken, setup.defaultUserDid);
@ -31,7 +31,7 @@ import { TokenType, IExpectedVerifiableCredential, Validator } from '../lib';
response = await validator.validate(siop.vc.rawToken + 'a', setup.defaultUserDid);
expect(response.result).toBeFalsy();
expect(response.status).toEqual(403);
expect(response.detailedError).toEqual('The signature on the payload in the verifiableCredential is invalid');
expect(response.detailedError).toEqual('The signature on the payload in the verifiableCredentialJwt is invalid');
// Missing vc
let payload: any = {

Просмотреть файл

@ -26,8 +26,8 @@ describe('VerifiablePresentationValidation', () => {
});
it('should test validate', async () => {
const [request, options, siop] = await IssuanceHelpers.createRequest(setup, TokenType.verifiablePresentation, true);
const expected = siop.expected.filter((token: IExpectedVerifiablePresentation) => token.type === TokenType.verifiablePresentation)[0];
const [request, options, siop] = await IssuanceHelpers.createRequest(setup, TokenType.verifiablePresentationJwt, true);
const expected = siop.expected.filter((token: IExpectedVerifiablePresentation) => token.type === TokenType.verifiablePresentationJwt)[0];
let validator = new VerifiablePresentationValidation(options, expected, setup.defaultUserDid, 'id');
let response = await validator.validate(siop.vp.rawToken);
@ -44,7 +44,7 @@ describe('VerifiablePresentationValidation', () => {
response = await validator.validate(siop.vp.rawToken + 'a');
expect(response.result).toBeFalsy();
expect(response.status).toEqual(403);
expect(response.detailedError).toEqual('The signature on the payload in the verifiablePresentation is invalid');
expect(response.detailedError).toEqual('The signature on the payload in the verifiablePresentationJwt is invalid');
// Missing iss
let payload: any = {