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

feat: remove did-resolver and did-jwt dependencies #82

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
400 changes: 58 additions & 342 deletions README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/services-class-diagram.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ RequestRegistrationOpts --|> RPRegistrationMetadataOpts

class VerifyAuthenticationRequestOpts {
<<interface>>
verification: InternalVerification | ExternalVerification;
verification: Verification
nonce?: string;
}

Expand Down Expand Up @@ -110,7 +110,7 @@ AuthenticationResponseWithJWT --> AuthenticationResponseOpts

class VerifyAuthenticationResponseOpts {
<<interface>>
verification: InternalVerification | ExternalVerification;
verification: Verification
nonce?: string;
state?: string;
audience: string;
Expand Down
2 changes: 1 addition & 1 deletion docs/services-class-diagram.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
111 changes: 57 additions & 54 deletions generator/schemaGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
FunctionType,
MutableTypeFormatter,
SchemaGenerator,
SubTypeFormatter
SubTypeFormatter,
} from 'ts-json-schema-generator';
import { Schema } from 'ts-json-schema-generator/dist/src/Schema/Schema';

Expand All @@ -26,9 +26,9 @@ class CustomTypeFormatter implements SubTypeFormatter {
properties: {
isFunction: {
type: 'boolean',
const: true
}
}
const: true,
},
},
};
}

Expand All @@ -49,59 +49,63 @@ function writeSchema(config: any): Schema {
schemaString = correctSchema(schemaString);

fs.writeFile(config.outputPath, `export const ${config.schemaId}Obj = ${schemaString};`, (err) => {
if (err) throw err;
if (err) {
throw err;
}
});
return schema;
}

function generateValidationCode(schemas: Schema[]) {
const ajv = new Ajv({ schemas, code: { source: true, lines: true, esm: false }, allowUnionTypes: true, strict: false });
const ajv = new Ajv({ schemas, code: { source: true, lines: true, esm: false }, allowUnionTypes: true, strict: false });
const moduleCode = standaloneCode(ajv);
fs.writeFileSync(path.join(__dirname, '../src/schemas/validation/schemaValidation.js'), moduleCode);
}

function correctSchema(schemaString: string) {
return schemaString.replace('"SuppliedSignature": {\n' +
' "type": "object",\n' +
' "properties": {\n' +
' "withSignature": {\n' +
' "properties": {\n' +
' "isFunction": {\n' +
' "type": "boolean",\n' +
' "const": true\n' +
' }\n' +
' }\n' +
' },\n' +
' "did": {\n' +
' "type": "string"\n' +
' },\n' +
' "kid": {\n' +
' "type": "string"\n' +
' }\n' +
' },\n' +
' "required": [\n' +
' "withSignature",\n' +
' "did",\n' +
' "kid"\n' +
' ],\n' +
' "additionalProperties": false\n' +
' },',
return schemaString.replace(
'"SuppliedSignature": {\n' +
' "type": "object",\n' +
' "properties": {\n' +
' "did": {\n' +
' "type": "string"\n' +
' },\n' +
' "kid": {\n' +
' "type": "string"\n' +
' }\n' +
' },\n' +
' "required": [\n' +
' "did",\n' +
' "kid"\n' +
' ],\n' +
' "additionalProperties": true\n' +
' },');
' "type": "object",\n' +
' "properties": {\n' +
' "withSignature": {\n' +
' "properties": {\n' +
' "isFunction": {\n' +
' "type": "boolean",\n' +
' "const": true\n' +
' }\n' +
' }\n' +
' },\n' +
' "did": {\n' +
' "type": "string"\n' +
' },\n' +
' "kid": {\n' +
' "type": "string"\n' +
' }\n' +
' },\n' +
' "required": [\n' +
' "withSignature",\n' +
' "did",\n' +
' "kid"\n' +
' ],\n' +
' "additionalProperties": false\n' +
' },',
'"SuppliedSignature": {\n' +
' "type": "object",\n' +
' "properties": {\n' +
' "did": {\n' +
' "type": "string"\n' +
' },\n' +
' "kid": {\n' +
' "type": "string"\n' +
' }\n' +
' },\n' +
' "required": [\n' +
' "did",\n' +
' "kid"\n' +
' ],\n' +
' "additionalProperties": true\n' +
' },',
);
}
/*
const requestOptsConf = {
Expand All @@ -114,15 +118,14 @@ const requestOptsConf = {
skipTypeCheck: true
};*/


const responseOptsConf = {
path: '../src/authorization-response/types.ts',
tsconfig: 'tsconfig.json',
type: 'AuthorizationResponseOpts', // Or <type-name> if you want to generate schema for that one type only
schemaId: 'AuthorizationResponseOptsSchema',
outputPath: 'src/schemas/AuthorizationResponseOpts.schema.ts',
// outputConstName: 'AuthorizationResponseOptsSchema',
skipTypeCheck: true
skipTypeCheck: true,
};

const rPRegistrationMetadataPayload = {
Expand All @@ -132,7 +135,7 @@ const rPRegistrationMetadataPayload = {
schemaId: 'RPRegistrationMetadataPayloadSchema',
outputPath: 'src/schemas/RPRegistrationMetadataPayload.schema.ts',
// outputConstName: 'RPRegistrationMetadataPayloadSchema',
skipTypeCheck: true
skipTypeCheck: true,
};

const discoveryMetadataPayload = {
Expand All @@ -142,7 +145,7 @@ const discoveryMetadataPayload = {
schemaId: 'DiscoveryMetadataPayloadSchema',
outputPath: 'src/schemas/DiscoveryMetadataPayload.schema.ts',
// outputConstName: 'DiscoveryMetadataPayloadSchema',
skipTypeCheck: true
skipTypeCheck: true,
};

const authorizationRequestPayloadVID1 = {
Expand All @@ -152,7 +155,7 @@ const authorizationRequestPayloadVID1 = {
schemaId: 'AuthorizationRequestPayloadVID1Schema',
outputPath: 'src/schemas/AuthorizationRequestPayloadVID1.schema.ts',
// outputConstName: 'AuthorizationRequestPayloadSchemaVID1',
skipTypeCheck: true
skipTypeCheck: true,
};

const authorizationRequestPayloadVD11 = {
Expand All @@ -162,7 +165,7 @@ const authorizationRequestPayloadVD11 = {
schemaId: 'AuthorizationRequestPayloadVD11Schema',
outputPath: 'src/schemas/AuthorizationRequestPayloadVD11.schema.ts',
// outputConstName: 'AuthorizationRequestPayloadSchemaVD11',
skipTypeCheck: true
skipTypeCheck: true,
};

const authorizationRequestPayloadVD12OID4VPD18 = {
Expand All @@ -172,7 +175,7 @@ const authorizationRequestPayloadVD12OID4VPD18 = {
schemaId: 'AuthorizationRequestPayloadVD12OID4VPD18Schema',
outputPath: 'src/schemas/AuthorizationRequestPayloadVD12OID4VPD18.schema.ts',
// outputConstName: 'AuthorizationRequestPayloadSchemaVD11',
skipTypeCheck: true
skipTypeCheck: true,
};

let schemas: Schema[] = [
Expand All @@ -182,7 +185,7 @@ let schemas: Schema[] = [
// writeSchema(requestOptsConf),
writeSchema(responseOptsConf),
writeSchema(rPRegistrationMetadataPayload),
writeSchema(discoveryMetadataPayload)
writeSchema(discoveryMetadataPayload),
];

generateValidationCode(schemas);
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@
"@sphereon/ssi-types": "0.22.0",
"@sphereon/wellknown-dids-client": "^0.1.3",
"cross-fetch": "^4.0.0",
"did-jwt": "6.11.6",
"did-resolver": "^4.1.0",
"jwt-decode": "^4.0.0",
"events": "^3.3.0",
"language-tags": "^1.0.9",
"multiformats": "^12.1.3",
Expand All @@ -49,6 +48,8 @@
"@babel/core": "^7.23.9",
"@babel/plugin-transform-runtime": "^7.16.0",
"@babel/preset-env": "^7.16.0",
"did-jwt": "6.11.6",
"did-resolver": "^4.1.0",
"@cef-ebsi/ebsi-did-resolver": "^3.2.0",
"@cef-ebsi/key-did-resolver": "^1.1.0",
"@cef-ebsi/oauth2-auth": "^3.0.0",
Expand All @@ -63,6 +64,7 @@
"@transmute/ed25519-key-pair": "0.7.0-unstable.82",
"@transmute/ed25519-signature-2018": "^0.7.0-unstable.82",
"@types/jest": "^29.5.11",
"@types/jwt-decode": "^3.1.0",
"@types/language-tags": "^1.0.4",
"@types/qs": "^6.9.11",
"@types/sha.js": "^2.4.4",
Expand All @@ -73,7 +75,6 @@
"bs58": "^5.0.0",
"codecov": "^3.8.3",
"cspell": "^6.26.3",
"did-resolver": "^4.1.0",
"dotenv": "^16.3.1",
"eslint": "^8.34.0",
"eslint-config-prettier": "^8.6.0",
Expand All @@ -84,7 +85,6 @@
"jest-junit": "^16.0.0",
"jest-resolver-enhanced": "^1.1.0",
"jose": "^4.15.5",
"jwt-decode": "^3.1.2",
"moment": "^2.30.1",
"nock": "^13.5.4",
"npm-run-all": "^4.1.5",
Expand Down
43 changes: 15 additions & 28 deletions src/authorization-request/AuthorizationRequest.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { JWTVerifyOptions } from 'did-jwt';

import { PresentationDefinitionWithLocation } from '../authorization-response';
import { PresentationExchange } from '../authorization-response/PresentationExchange';
import { getAudience, getResolver, parseJWT, verifyDidJWT } from '../did';
import { fetchByReferenceOrUseByValue, removeNullUndefined } from '../helpers';
import { authorizationRequestVersionDiscovery } from '../helpers/SIOPSpecVersion';
import { parseJWT } from '../helpers/jwtUtils';
import { RequestObject } from '../request-object';
import {
AuthorizationRequestPayload,
getJwtVerifierWithContext,
PassBy,
RequestObjectJwt,
RequestObjectPayload,
Expand All @@ -19,11 +18,10 @@ import {
SIOPErrors,
SupportedVersion,
VerifiedAuthorizationRequest,
VerifiedJWT,
} from '../types';

import { assertValidAuthorizationRequestOpts, assertValidVerifyAuthorizationRequestOpts } from './Opts';
import { assertValidRPRegistrationMedataPayload, checkWellknownDIDFromRequest, createAuthorizationRequestPayload } from './Payload';
import { assertValidRPRegistrationMedataPayload, createAuthorizationRequestPayload } from './Payload';
import { URI } from './URI';
import { CreateAuthorizationRequestOpts, VerifyAuthorizationRequestOpts } from './types';

Expand Down Expand Up @@ -117,30 +115,19 @@ export class AuthorizationRequest {
assertValidVerifyAuthorizationRequestOpts(opts);

let requestObjectPayload: RequestObjectPayload;
let verifiedJwt: VerifiedJWT;

const jwt = await this.requestObjectJwt();
if (jwt) {
const parsedJWT = parseJWT(jwt);
const payload = parsedJWT.payload;
const audience = getAudience(jwt);
const resolver = getResolver(opts.verification.resolveOpts);
const options: JWTVerifyOptions = {
...opts.verification?.resolveOpts?.jwtVerifyOpts,
resolver,
audience,
};

if (payload.client_id?.startsWith('http') && payload.iss.startsWith('http') && payload.iss === payload.client_id) {
console.error(`FIXME: The client_id and iss are not DIDs. We do not verify the signature in this case yet! ${payload.iss}`);
verifiedJwt = { payload, jwt, issuer: payload.iss };
} else {
verifiedJwt = await verifyDidJWT(jwt, resolver, options);
}
if (!verifiedJwt || !verifiedJwt.payload) {
const parsedJwt = jwt ? parseJWT(jwt) : undefined;

if (parsedJwt) {
requestObjectPayload = parsedJwt.payload as RequestObjectPayload;

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

if (!result) {
throw Error(SIOPErrors.ERROR_VERIFYING_SIGNATURE);
}
requestObjectPayload = verifiedJwt.payload as RequestObjectPayload;

if (this.hasRequestObject() && !this.payload.request_uri) {
// Put back the request object as that won't be present yet
Expand Down Expand Up @@ -186,14 +173,14 @@ export class AuthorizationRequest {
throw new Error(`${SIOPErrors.INVALID_REQUEST}, redirect_uri or response_uri is needed`);
}

await checkWellknownDIDFromRequest(mergedPayload, opts);

// TODO: we need to verify somewhere that if response_mode is direct_post, that the response_uri may be present,
// BUT not both redirect_uri and response_uri. What is the best place to do this?

const presentationDefinitions = await PresentationExchange.findValidPresentationDefinitions(mergedPayload, await this.getSupportedVersion());
return {
...verifiedJwt,
jwt,
payload: parsedJwt?.payload,
issuer: parsedJwt?.payload.iss,
responseURIType,
responseURI,
clientIdScheme: mergedPayload.client_id_scheme,
Expand Down
Loading
Loading