Skip to content

Commit d6cf985

Browse files
authored
Fix/issuer-integration (#235)
* Fix for the case when user wasn't able to authorize with jwz token after state transition
1 parent 856bf6d commit d6cf985

File tree

14 files changed

+243
-99
lines changed

14 files changed

+243
-99
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@0xpolygonid/js-sdk",
3-
"version": "1.14.1",
3+
"version": "1.15.0",
44
"description": "SDK to work with Polygon ID",
55
"main": "dist/node/cjs/index.js",
66
"module": "dist/node/esm/index.js",

src/iden3comm/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,6 @@ export const SUPPORTED_PUBLIC_KEY_TYPES = {
7272
'JsonWebKey2020'
7373
]
7474
};
75+
76+
export const DEFAULT_PROOF_VERIFY_DELAY = 1 * 60 * 60 * 1000; // 1 hour
77+
export const DEFAULT_AUTH_VERIFY_DELAY = 5 * 60 * 1000; // 5 minutes

src/iden3comm/handlers/auth.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { IProofService } from '../../proof/proof-service';
33
import { PROTOCOL_MESSAGE_TYPE } from '../constants';
44

55
import {
6+
StateVerificationOpts,
67
AuthorizationRequestMessage,
78
AuthorizationResponseMessage,
89
BasicMessage,
@@ -64,19 +65,17 @@ export function createAuthorizationRequestWithMessage(
6465
};
6566
return request;
6667
}
68+
6769
/**
6870
*
6971
* Options to pass to auth response handler
7072
*
7173
* @public
72-
* @interface AuthResponseHandlerOptions
7374
*/
74-
export interface AuthResponseHandlerOptions {
75-
// acceptedStateTransitionDelay is the period of time in milliseconds that a revoked state remains valid.
76-
acceptedStateTransitionDelay?: number;
75+
export type AuthResponseHandlerOptions = StateVerificationOpts & {
7776
// acceptedProofGenerationDelay is the period of time in milliseconds that a generated proof remains valid.
7877
acceptedProofGenerationDelay?: number;
79-
}
78+
};
8079

8180
/**
8281
* Interface that allows the processing of the authorization request in the raw format for given identifier

src/iden3comm/handlers/credential-proposal.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { PROTOCOL_MESSAGE_TYPE } from '../constants';
2-
import { MediaType } from '../constants';
1+
import { PROTOCOL_MESSAGE_TYPE, MediaType } from '../constants';
32
import {
43
BasicMessage,
54
CredentialOffer,
@@ -214,17 +213,22 @@ export class CredentialProposalHandler
214213
throw new Error(`failed request. no 'credentials' in body`);
215214
}
216215

217-
const senderDID = DID.parse(proposalRequest.from);
218-
219216
let credOfferMessage: CredentialsOfferMessage | undefined = undefined;
220217
let proposalMessage: ProposalMessage | undefined = undefined;
218+
221219
for (let i = 0; i < proposalRequest.body.credentials.length; i++) {
222220
const cred = proposalRequest.body.credentials[i];
223221

224222
// check if there is credentials in the wallet
225223
let credsFromWallet: W3CCredential[] = [];
224+
226225
try {
227-
credsFromWallet = await this._identityWallet.findOwnedCredentialsByDID(senderDID, {
226+
credsFromWallet = await this._identityWallet.credentialWallet.findByQuery({
227+
credentialSubject: {
228+
id: {
229+
$eq: proposalRequest.from
230+
}
231+
},
228232
type: cred.type,
229233
context: cred.context
230234
});

src/iden3comm/handlers/message-handler.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import { AuthMessageHandlerOptions } from './auth';
33
import { RevocationStatusMessageHandlerOptions } from './revocation-status';
44
import { ContractMessageHandlerOptions } from './contract-request';
55
import { PaymentHandlerOptions, PaymentRequestMessageHandlerOptions } from './payment';
6+
import { MediaType } from '../constants';
7+
import { proving } from '@iden3/js-jwz';
8+
import { DID } from '@iden3/js-iden3-core';
69
/**
710
* iden3 Protocol message handler interface
811
*/
@@ -120,7 +123,7 @@ export class MessageHandler {
120123
| RevocationStatusMessageHandlerOptions
121124
| PaymentRequestMessageHandlerOptions
122125
| PaymentHandlerOptions
123-
| { [key: string]: unknown }
126+
| { senderDID?: DID; [key: string]: unknown }
124127
): Promise<Uint8Array | null> {
125128
const { unpackedMediaType, unpackedMessage: message } =
126129
await this._params.packageManager.unpack(bytes);
@@ -131,10 +134,20 @@ export class MessageHandler {
131134

132135
const response = await this.messageHandler.handle(message, context);
133136

134-
if (response) {
135-
return this._params.packageManager.packMessage(unpackedMediaType, response, {});
137+
if (!response) {
138+
return null;
136139
}
137140

138-
return null;
141+
let packerParams = {};
142+
const senderDID = (context as { senderDID?: DID })?.senderDID;
143+
if (unpackedMediaType === MediaType.ZKPMessage && senderDID) {
144+
packerParams = {
145+
senderDID,
146+
provingMethodAlg: proving.provingMethodGroth16AuthV2Instance.methodAlg
147+
};
148+
return this._params.packageManager.packMessage(unpackedMediaType, response, packerParams);
149+
}
150+
151+
return this._params.packageManager.packMessage(MediaType.PlainMessage, response, packerParams);
139152
}
140153
}

src/iden3comm/packers/zkp.ts

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
StateVerificationOpts,
23
AuthDataPrepareFunc,
34
BasicMessage,
45
IPacker,
@@ -9,7 +10,7 @@ import {
910
} from '../types';
1011
import { Token, Header, ProvingMethodAlg, proving } from '@iden3/js-jwz';
1112
import { AuthV2PubSignals, CircuitId } from '../../circuits/index';
12-
import { DID, Id } from '@iden3/js-iden3-core';
13+
import { BytesHelper, DID } from '@iden3/js-iden3-core';
1314
import { bytesToProtocolMessage } from '../utils/envelope';
1415
import {
1516
ErrNoProvingMethodAlg,
@@ -21,6 +22,7 @@ import {
2122
} from '../errors';
2223
import { MediaType } from '../constants';
2324
import { byteDecoder, byteEncoder } from '../../utils';
25+
import { DEFAULT_AUTH_VERIFY_DELAY } from '../constants';
2426

2527
const { getProvingMethod } = proving;
2628

@@ -70,8 +72,8 @@ export class VerificationHandlerFunc {
7072
* @param {Array<string>} pubSignals - signals that must contain user id and state
7173
* @returns `Promise<boolean>`
7274
*/
73-
verify(id: string, pubSignals: Array<string>): Promise<boolean> {
74-
return this.stateVerificationFunc(id, pubSignals);
75+
verify(id: string, pubSignals: Array<string>, opts?: StateVerificationOpts): Promise<boolean> {
76+
return this.stateVerificationFunc(id, pubSignals, opts);
7577
}
7678
}
7779

@@ -89,8 +91,11 @@ export class ZKPPacker implements IPacker {
8991
* @param {Map<string, VerificationParams>} verificationParamsMap - string is derived by JSON.parse(ProvingMethodAlg)
9092
*/
9193
constructor(
92-
public provingParamsMap: Map<string, ProvingParams>,
93-
public verificationParamsMap: Map<string, VerificationParams>
94+
public readonly provingParamsMap: Map<string, ProvingParams>,
95+
public readonly verificationParamsMap: Map<string, VerificationParams>,
96+
private readonly _opts: StateVerificationOpts = {
97+
acceptedStateTransitionDelay: DEFAULT_AUTH_VERIFY_DELAY
98+
}
9499
) {}
95100

96101
/**
@@ -150,8 +155,10 @@ export class ZKPPacker implements IPacker {
150155

151156
const verificationResult = await verificationParams?.verificationFn?.verify(
152157
token.circuitId,
153-
token.zkProof.pub_signals
158+
token.zkProof.pub_signals,
159+
this._opts
154160
);
161+
155162
if (!verificationResult) {
156163
throw new Error(ErrStateVerificationFailed);
157164
}
@@ -169,26 +176,31 @@ export class ZKPPacker implements IPacker {
169176
}
170177
}
171178

172-
const verifySender = (token: Token, msg: BasicMessage): void => {
179+
const verifySender = async (token: Token, msg: BasicMessage): Promise<void> => {
173180
switch (token.circuitId) {
174181
case CircuitId.AuthV2:
175-
if (!msg.from || !verifyAuthV2Sender(msg.from, token.zkProof.pub_signals)) {
176-
throw new Error(ErrSenderNotUsedTokenCreation);
182+
{
183+
if (!msg.from) {
184+
throw new Error(ErrSenderNotUsedTokenCreation);
185+
}
186+
const authSignals = new AuthV2PubSignals().pubSignalsUnmarshal(
187+
byteEncoder.encode(JSON.stringify(token.zkProof.pub_signals))
188+
);
189+
const did = DID.parseFromId(authSignals.userID);
190+
191+
const msgHash = await token.getMessageHash();
192+
const challenge = BytesHelper.bytesToInt(msgHash.reverse());
193+
194+
if (challenge !== authSignals.challenge) {
195+
throw new Error(ErrSenderNotUsedTokenCreation);
196+
}
197+
198+
if (msg.from !== did.string()) {
199+
throw new Error(ErrSenderNotUsedTokenCreation);
200+
}
177201
}
178202
break;
179203
default:
180204
throw new Error(ErrUnknownCircuitID);
181205
}
182206
};
183-
184-
const verifyAuthV2Sender = (from: string, pubSignals: Array<string>): boolean => {
185-
const authSignals = new AuthV2PubSignals();
186-
187-
const pubSig = authSignals.pubSignalsUnmarshal(byteEncoder.encode(JSON.stringify(pubSignals)));
188-
return pubSig.userID ? checkSender(from, pubSig.userID) : false;
189-
};
190-
191-
const checkSender = (from: string, id: Id): boolean => {
192-
const did = DID.parseFromId(id);
193-
return from === did.string();
194-
};

src/iden3comm/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ export * from './protocol/proposal-request';
88
export * from './protocol/payment';
99

1010
export * from './packer';
11+
export * from './models';
1112
export * from './packageManager';

src/iden3comm/types/models.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/**
2+
* State verification options
3+
*/
4+
export type StateVerificationOpts = {
5+
// acceptedStateTransitionDelay is the period of time in milliseconds that a revoked state remains valid.
6+
acceptedStateTransitionDelay?: number;
7+
};

src/iden3comm/types/packer.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { ProvingMethodAlg } from '@iden3/js-jwz';
44
import { CircuitId } from '../../circuits';
55
import { MediaType } from '../constants';
66
import { DIDDocument, VerificationMethod } from 'did-resolver';
7+
import { StateVerificationOpts } from './models';
78
/**
89
* Protocol message type
910
*/
@@ -79,7 +80,11 @@ export type AuthDataPrepareFunc = (
7980
/**
8081
* signature of state function verifier
8182
*/
82-
export type StateVerificationFunc = (id: string, pubSignals: Array<string>) => Promise<boolean>;
83+
export type StateVerificationFunc = (
84+
id: string,
85+
pubSignals: Array<string>,
86+
opts?: StateVerificationOpts
87+
) => Promise<boolean>;
8388

8489
/**
8590
* Defines method that must be implemented by any packer

src/identity/identity-wallet.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,14 @@ export interface IIdentityWallet {
140140
*/
141141
createIdentity(opts: IdentityCreationOptions): Promise<{ did: DID; credential: W3CCredential }>;
142142

143+
/**
144+
* Credential wallet getter
145+
*
146+
* @returns {ICredentialWallet}
147+
* @memberof IIdentityWallet
148+
*/
149+
get credentialWallet(): ICredentialWallet;
150+
143151
/**
144152
* Create Identity based in Ethereum address and it provides an identifier in DID form.
145153
*
@@ -496,6 +504,10 @@ export class IdentityWallet implements IIdentityWallet {
496504
this._transactionService = new TransactionService(_storage.states.getRpcProvider());
497505
}
498506

507+
get credentialWallet(): ICredentialWallet {
508+
return this._credentialWallet;
509+
}
510+
499511
private getCredentialStatusPublisherRegistry(
500512
_opts:
501513
| { credentialStatusPublisherRegistry?: CredentialStatusPublisherRegistry | undefined }

0 commit comments

Comments
 (0)