From 3f6ba955e6dde221c9d27de5e08f3282471a6245 Mon Sep 17 00:00:00 2001 From: vbasiuk Date: Tue, 14 Jan 2025 12:54:54 +0200 Subject: [PATCH 1/4] update js-sdk to 1.26.0 and verify response typ --- package-lock.json | 14 ++++++++++---- package.json | 2 +- src/auth/auth.ts | 17 ++++++----------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index cca4797..d77c05c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.6.0", "license": "MIT or Apache-2.0", "dependencies": { - "@0xpolygonid/js-sdk": "1.23.0", + "@0xpolygonid/js-sdk": "1.26.0", "@iden3/js-crypto": "1.1.0", "@iden3/js-iden3-core": "1.4.1", "@iden3/js-jsonld-merklization": "1.4.1", @@ -48,10 +48,11 @@ } }, "node_modules/@0xpolygonid/js-sdk": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/@0xpolygonid/js-sdk/-/js-sdk-1.23.0.tgz", - "integrity": "sha512-u1koslgRehLwSt1rZYk8tUcrg/ANOaIouZscqoZ24lIetj36UgUs7iXWEX0nudjMxUSlv3uwy53nds8TYsBqIQ==", + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@0xpolygonid/js-sdk/-/js-sdk-1.26.0.tgz", + "integrity": "sha512-bEfizdAHasGH05EKkEOrvTz8K62wD1Lk6d6UiBH9jjVzUpFPKfSHCciNAveo3BeVL2U/JId9y6hLcZo7yv9hhA==", "dependencies": { + "@iden3/onchain-non-merklized-issuer-base-abi": "^0.0.3", "@noble/curves": "^1.4.0", "ajv": "8.12.0", "ajv-formats": "2.1.1", @@ -2128,6 +2129,11 @@ "idb-keyval": "^6.2.0" } }, + "node_modules/@iden3/onchain-non-merklized-issuer-base-abi": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@iden3/onchain-non-merklized-issuer-base-abi/-/onchain-non-merklized-issuer-base-abi-0.0.3.tgz", + "integrity": "sha512-4Mt5iP54KEzh0vbyhwKINx8bdZDyDJ6At92dPi3VKbKvk4dN24MlOQx5BfRakkZYJe7xlvMo/QaOjc/zRAlADg==" + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", diff --git a/package.json b/package.json index 858ec89..d221cab 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "url": "https://github.com/iden3/js-iden3-auth" }, "dependencies": { - "@0xpolygonid/js-sdk": "1.23.0", + "@0xpolygonid/js-sdk": "1.26.0", "@iden3/js-crypto": "1.1.0", "@iden3/js-iden3-core": "1.4.1", "@iden3/js-jsonld-merklization": "1.4.1", diff --git a/src/auth/auth.ts b/src/auth/auth.ts index a8c07aa..ed893f9 100644 --- a/src/auth/auth.ts +++ b/src/auth/auth.ts @@ -419,6 +419,11 @@ export class Verifier { opts?: VerifyOpts ): Promise { const msg = await this.packageManager.unpack(byteEncoder.encode(tokenStr)); + + if (request.body.accept?.length && !request.body.accept.includes(msg.unpackedMediaType)) { + throw new Error('response media type is not accepted by request'); + } + const response = msg.unpackedMessage as AuthorizationResponseMessage; await this.verifyAuthResponse(response, request, opts); return response; @@ -438,17 +443,7 @@ export class Verifier { } const supportedMediaTypes: PROTOCOL_CONSTANTS.MediaType[] = []; for (const acceptProfile of profile) { - // 1. check protocol version - const { protocolVersion, env } = parseAcceptProfile(acceptProfile); - const messageTypeVersion = Number(messageType.split('/').at(-2)); - if ( - protocolVersion !== PROTOCOL_CONSTANTS.ProtocolVersion.V1 || - (protocolVersion === PROTOCOL_CONSTANTS.ProtocolVersion.V1 && - (messageTypeVersion < 1 || messageTypeVersion >= 2)) - ) { - continue; - } - // 2. check packer support + const { env } = parseAcceptProfile(acceptProfile); if (this.packageManager.isProfileSupported(env, acceptProfile)) { supportedMediaTypes.push(env); } From 5140e35a32dbda42aaec08376c6f85ef92a1c351 Mon Sep 17 00:00:00 2001 From: vbasiuk Date: Tue, 14 Jan 2025 12:57:51 +0200 Subject: [PATCH 2/4] parse accept and compare on env field --- src/auth/auth.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/auth/auth.ts b/src/auth/auth.ts index ed893f9..de32c48 100644 --- a/src/auth/auth.ts +++ b/src/auth/auth.ts @@ -420,8 +420,11 @@ export class Verifier { ): Promise { const msg = await this.packageManager.unpack(byteEncoder.encode(tokenStr)); - if (request.body.accept?.length && !request.body.accept.includes(msg.unpackedMediaType)) { - throw new Error('response media type is not accepted by request'); + if (request.body.accept?.length) { + const acceptedMediaTypes = request.body.accept.map(accept => parseAcceptProfile(accept).env); + if (!acceptedMediaTypes.includes(msg.unpackedMediaType)) { + throw new Error('response media type is not accepted by request'); + } } const response = msg.unpackedMessage as AuthorizationResponseMessage; From 57d6b69eaf5ae21f6ce320b69d9e2e7ea8c76de1 Mon Sep 17 00:00:00 2001 From: vbasiuk Date: Tue, 14 Jan 2025 13:00:21 +0200 Subject: [PATCH 3/4] sync messages --- src/auth/auth.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/auth/auth.ts b/src/auth/auth.ts index de32c48..754625c 100644 --- a/src/auth/auth.ts +++ b/src/auth/auth.ts @@ -423,7 +423,7 @@ export class Verifier { if (request.body.accept?.length) { const acceptedMediaTypes = request.body.accept.map(accept => parseAcceptProfile(accept).env); if (!acceptedMediaTypes.includes(msg.unpackedMediaType)) { - throw new Error('response media type is not accepted by request'); + throw new Error('response type is not in accept profiles of the request'); } } From f747d360d55ad411f565f4d518ad7235b0fb7920 Mon Sep 17 00:00:00 2001 From: vbasiuk Date: Tue, 14 Jan 2025 13:17:57 +0200 Subject: [PATCH 4/4] add unit test --- src/auth/auth.ts | 5 ++- test/auth.test.ts | 86 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 80 insertions(+), 11 deletions(-) diff --git a/src/auth/auth.ts b/src/auth/auth.ts index 754625c..c38e41b 100644 --- a/src/auth/auth.ts +++ b/src/auth/auth.ts @@ -82,6 +82,7 @@ export function createAuthorizationRequestWithMessage( typ: PROTOCOL_CONSTANTS.MediaType.PlainMessage, type: PROTOCOL_CONSTANTS.PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE, body: { + accept: opts?.accept, reason: reason, message: message, callbackUrl: callbackUrl, @@ -421,7 +422,9 @@ export class Verifier { const msg = await this.packageManager.unpack(byteEncoder.encode(tokenStr)); if (request.body.accept?.length) { - const acceptedMediaTypes = request.body.accept.map(accept => parseAcceptProfile(accept).env); + const acceptedMediaTypes = request.body.accept.map( + (accept) => parseAcceptProfile(accept).env + ); if (!acceptedMediaTypes.includes(msg.unpackedMediaType)) { throw new Error('response type is not in accept profiles of the request'); } diff --git a/test/auth.test.ts b/test/auth.test.ts index 41b57af..2e05622 100644 --- a/test/auth.test.ts +++ b/test/auth.test.ts @@ -9,6 +9,7 @@ import { NativeProver, PROTOCOL_CONSTANTS, PackageManager, + PlainPacker, ZeroKnowledgeProofRequest, buildAccept } from '@0xpolygonid/js-sdk'; @@ -25,13 +26,31 @@ import { getDateFromUnixTimestamp, getUnixTimestamp } from '@iden3/js-iden3-core describe('auth tests', () => { const connectionString = process.env.IPFS_URL ?? 'https://ipfs.io'; - const acceptProfile = buildAccept([ + const acceptProfileZKP = buildAccept([ { protocolVersion: PROTOCOL_CONSTANTS.ProtocolVersion.V1, env: PROTOCOL_CONSTANTS.MediaType.ZKPMessage, circuits: [PROTOCOL_CONSTANTS.AcceptAuthCircuits.AuthV2] } ]); + + const acceptProfileJWS = buildAccept([ + { + protocolVersion: PROTOCOL_CONSTANTS.ProtocolVersion.V1, + env: PROTOCOL_CONSTANTS.MediaType.SignedMessage, + alg: [ + PROTOCOL_CONSTANTS.AcceptJwsAlgorithms.ES256K, + PROTOCOL_CONSTANTS.AcceptJwsAlgorithms.ES256K + ] + } + ]); + + const acceptProfilePlain = buildAccept([ + { + protocolVersion: PROTOCOL_CONSTANTS.ProtocolVersion.V1, + env: PROTOCOL_CONSTANTS.MediaType.PlainMessage + } + ]); const expiresTime = getDateFromUnixTimestamp(getUnixTimestamp(new Date()) + 5 * 60); it('createAuthorizationRequest', () => { const sender = 'did:iden3:polygon:amoy:xCRp75DgAdS63W65fmXHz6p9DwdonuRU9e46DifhX'; @@ -76,7 +95,7 @@ describe('auth tests', () => { sender, callback, { - accept: acceptProfile, + accept: acceptProfilePlain, expires_time: expiresTime } ); @@ -94,12 +113,15 @@ describe('auth tests', () => { } }; + const packageManager = new PackageManager(); + packageManager.registerPackers([new PlainPacker()]); + const verifier = await Verifier.newVerifier({ stateResolver: resolvers, suite: { prover: new NativeProver(new FSCircuitStorage({ dirname: '' })), circuitStorage: new FSCircuitStorage({ dirname: '../' }), - packageManager: new PackageManager(), + packageManager: packageManager, documentLoader: schemaLoader } }); @@ -118,7 +140,6 @@ describe('auth tests', () => { sender, callback, { - accept: acceptProfile, expires_time: expiresTime } ); @@ -150,7 +171,7 @@ describe('auth tests', () => { const response: AuthorizationResponseMessage = { id: 'd61ca0e1-0fb4-42e1-9baf-10926d76588a', - typ: PROTOCOL_CONSTANTS.MediaType.ZKPMessage, + typ: PROTOCOL_CONSTANTS.MediaType.PlainMessage, type: PROTOCOL_CONSTANTS.PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_RESPONSE_MESSAGE_TYPE, thid: '3bfc628a-6d16-4af7-8358-59656ca30600', body: { @@ -287,7 +308,6 @@ describe('auth tests', () => { sender, callback, { - accept: acceptProfile, expires_time: expiresTime } ); @@ -469,7 +489,7 @@ describe('auth tests', () => { sender, callback, { - accept: acceptProfile, + accept: acceptProfileZKP, expires_time: expiresTime } ); @@ -521,7 +541,7 @@ describe('auth tests', () => { sender, callback, { - accept: acceptProfile, + accept: acceptProfileJWS, expires_time: expiresTime } ); @@ -563,6 +583,52 @@ describe('auth tests', () => { await expect(verifier.fullVerify(token, request, testOpts)).resolves.not.toThrow(); }); + it('TestFullVerify invalid accept', async () => { + const token = + 'eyJhbGciOiJFUzI1NkstUiIsImtpZCI6ImRpZDpwa2g6cG9seToweDcxNDFFNGQyMEY3NjQ0REM4YzBBZENBOGE1MjBFQzgzQzZjQUJENjUjUmVjb3ZlcnkyMDIwIiwidHlwIjoiYXBwbGljYXRpb24vaWRlbjNjb21tLXNpZ25lZC1qc29uIn0.eyJpZCI6IjJjOGQ5NzQ3LTQ0MTAtNGU5My1iZjg0LTRlYTNjZmY4MmY0MCIsInR5cCI6ImFwcGxpY2F0aW9uL2lkZW4zY29tbS1zaWduZWQtanNvbiIsInR5cGUiOiJodHRwczovL2lkZW4zLWNvbW11bmljYXRpb24uaW8vYXV0aG9yaXphdGlvbi8xLjAvcmVzcG9uc2UiLCJ0aGlkIjoiN2YzOGExOTMtMDkxOC00YTQ4LTlmYWMtMzZhZGZkYjhiNTQyIiwiYm9keSI6eyJzY29wZSI6W3siaWQiOjEsImNpcmN1aXRJZCI6ImNyZWRlbnRpYWxBdG9taWNRdWVyeVNpZ1YyIiwicHJvb2YiOnsicGlfYSI6WyIxMzI3Njk4Nzc5MjQ5MjM0OTA2MDcxMDc3NTEyOTUxMjYxNzY1NjMzODcxMDkxMzE3NDA0NzE0NTcyMDY4Mjk4NzU0MzUwNjY3NDY0IiwiMjA1NDcyOTI1MzQ0MDgxNzA4NDQwODc3MzY2MDQ0OTYyNjQ3MzI2NjUxNDkxMDEzMzMxNzk3NTg5NTAwMjM0NTgwMjA1Njg5NzMzNTYiLCIxIl0sInBpX2IiOltbIjcyNTI1MDEyNjE5ODM1NTYwMjM1NjA3MzI1MjIzODk2MjIxMDY4MTA5OTUxNzkxNjI0MjY2NzcyNDM2MjQwNTQ0Mzc2Nzc1ODI4MCIsIjgyNDU2MTQzMTExNjUzNTUyNzcyNTgyNTg1NTA0MTI5MTUzNjAzNTc2MjEyMDY5OTA0Mjk3NTE3ODk2NTgwNTI1ODY0Mjc2NjgyMDMiXSxbIjg0MjA4OTI3MTI5OTMyMTU5OTU3NjkwMDQ3MzU2Njc5MzY3MDk4MzY5MTY4MzU4MDM2Njc2NjI1NzQxMTcyNjEzNjI2OTgxMzI1MjkiLCIxMDgyOTQzMjI5MDkyODY3MjM1NjAzNjExMTgxNjE4NTQ0MDU3NTgwMDI1NDQzODAyMzUzNTA3MzUzNTY1ODMzOTE0MzMzODAzNDAyNyJdLFsiMSIsIjAiXV0sInBpX2MiOlsiMTIwNTc1NzM1NDQ2Mzc1NDA1MzE2MjIxNDc2NDg2NjE0MDc1NzM1MzY2MjU0MjM0MzY1ODE0MTk2OTY3NzYwOTMxOTY5Nzc5OTg2MzkiLCIxNTIwMzMwMjIxNjcyOTEzOTcwNjQyNjcyMzc5Mzk5Mjk0MjI5NjY1NTU0NDA4MTEwODkzMTE2MjIwMTQxOTcxNzI0MjU4NTQzOTg2NSIsIjEiXSwicHJvdG9jb2wiOiJncm90aDE2IiwiY3VydmUiOiJibjEyOCJ9LCJwdWJfc2lnbmFscyI6WyIxIiwiMjgwMTg1ODg4MjE0NzE5Mzk2MjQ3MTE0MjE5MjIwNzkzOTU0NTE1MDc3NTQzNzU5Nzg0MDgyMzA1MjQ3OTI3ODY4NjI5OTc1MDMiLCIxNDE5MzMwNDc0NzUwMTMzMTE4MTgwOTcxNTkxMjQ4NzIzNjUyNzAwMzkyNTA4MjEwNjc1MjM3Njc5NjA5OTg5MDIwMTkyODE4NTY5MCIsIjEiLCIyMjk0MjU5NDE1NjI2NjY2NTQyNjYxMzQ2Mjc3MTcyNTMyNzMxNDM4MjY0NzQyNjk1OTA0NDg2MzQ0Njg2NjYxMzAwMzc1MTkzOCIsIjEiLCIzMTY5NjEyMzY4MDg3OTA1MzQyNzg2NTE0MDk5NDQ5Mjk3NDA0MzgzODc0MzcxMzU2OTI0ODI4MDgyMTQzNjExOTUzNjIxODU5NzU5IiwiMTY4NzQzMzc0OCIsIjI2NzgzMTUyMTkyMjU1ODAyNzIwNjA4MjM5MDA0MzMyMTc5Njk0NCIsIjAiLCIyMDM3NjAzMzgzMjM3MTEwOTE3NzY4MzA0ODQ1NjAxNDUyNTkwNTExOTE3MzY3NDk4NTg0MzkxNTQ0NTYzNDcyNjE2NzQ1MDk4OTYzMCIsIjIiLCIyIiwiMjAwMDAxMDEiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiLCIwIiwiMCIsIjAiXX1dfSwiZnJvbSI6ImRpZDpwa2g6cG9seToweDcxNDFFNGQyMEY3NjQ0REM4YzBBZENBOGE1MjBFQzgzQzZjQUJENjUiLCJ0byI6ImRpZDpwb2x5Z29uaWQ6cG9seWdvbjptdW1iYWk6MnFMUHF2YXlOUXo5VEEycjVWUHhVdWdvRjE4dGVHVTU4M3pKODU5d2Z5In0.bWc2ECABj7nvHatD8AXWNJM2VtfhkIjNwz5BBIK9zBMsP0-UWLEWdAWcosiLkYoL0KWwZpgEOrPPepl6T5gC-AA'; + const sender = 'did:polygonid:polygon:mumbai:2qLPqvayNQz9TA2r5VPxUugoF18teGU583zJ859wfy'; + const callback = 'https://test.com/callback'; + const reason = 'reason'; + const request: AuthorizationRequestMessage = createAuthorizationRequest( + reason, + sender, + callback, + { + accept: acceptProfileZKP, + expires_time: expiresTime + } + ); + + const proofRequest: ZeroKnowledgeProofRequest = { + id: 1, + circuitId: CircuitId.AtomicQuerySigV2, + query: { + allowedIssuers: ['*'], + context: + 'https://raw.githubusercontent.com/iden3/claim-schema-vocab/main/schemas/json-ld/kyc-v4.jsonld', + type: 'KYCAgeCredential', + credentialSubject: { + birthday: { + $lt: 20000101 + } + } + } + }; + request.body.scope.push(proofRequest); + + const verifier = await Verifier.newVerifier({ + stateResolver: resolvers, + documentLoader: schemaLoader, + circuitsDir: path.join(__dirname, './testdata'), + didDocumentResolver: resolveDIDDocument + }); + verifier.setupJWSPacker(new KMS(), resolveDIDDocument); + + await expect(verifier.fullVerify(token, request, testOpts)).rejects.toThrow( + 'response type is not in accept profiles of the request' + ); + }); + it('registry: get existing circuit', () => { const type = Circuits.getCircuitPubSignals('authV2'); const instance = new type([ @@ -594,7 +660,7 @@ describe('auth tests', () => { sender, callback, { - accept: acceptProfile, + accept: acceptProfileZKP, expires_time: expiresTime } ); @@ -644,7 +710,7 @@ describe('auth tests', () => { sender, callback, { - accept: acceptProfile, + accept: acceptProfileZKP, expires_time: expiresTime } );