diff --git a/src/credentials/credential-wallet.ts b/src/credentials/credential-wallet.ts index 718894eb..7079eca4 100644 --- a/src/credentials/credential-wallet.ts +++ b/src/credentials/credential-wallet.ts @@ -192,7 +192,7 @@ export class CredentialWallet implements ICredentialWallet { }); if (!authBJJCredsOfIssuer.length) { - throw new Error('no auth credentials found'); + throw new Error(VerifiableConstants.ERRORS.NO_AUTH_CRED_FOUND); } for (let index = 0; index < authBJJCredsOfIssuer.length; index++) { diff --git a/src/identity/identity-wallet.ts b/src/identity/identity-wallet.ts index bd48a3f0..cb300875 100644 --- a/src/identity/identity-wallet.ts +++ b/src/identity/identity-wallet.ts @@ -626,6 +626,36 @@ export class IdentityWallet implements IIdentityWallet { rootOfRoots: ZERO_HASH }; + const identity = await this._storage.identity.getIdentity(did.string()); + if (!identity) { + await this._storage.identity.saveIdentity({ + did: did.string(), + state: currentState, + isStatePublished: false, + isStateGenesis: true + }); + } + + // check whether we have auth credential, if not - create a new one + const credentials = await this._credentialWallet.findByQuery({ + credentialSubject: { + x: { + $eq: pubKey.p[0].toString() + }, + y: { + $eq: pubKey.p[1].toString() + } + }, + allowedIssuers: [did.string()] + }); + + if (credentials.length) { + return { + did, + credential: credentials[0] + }; + } + const credential = await this.createAuthBJJCredential( did, pubKey, @@ -658,13 +688,6 @@ export class IdentityWallet implements IIdentityWallet { onChain: opts.revocationOpts.onChain }); - await this._storage.identity.saveIdentity({ - did: did.string(), - state: currentState, - isStatePublished: false, - isStateGenesis: true - }); - await this._credentialWallet.save(credential); return { @@ -1042,7 +1065,7 @@ export class IdentityWallet implements IIdentityWallet { } } - throw new Error('no auth credentials found'); + throw new Error(VerifiableConstants.ERRORS.NO_AUTH_CRED_FOUND); } /** {@inheritDoc IIdentityWallet.revokeCredential} */ diff --git a/src/verifiable/constants.ts b/src/verifiable/constants.ts index c5e3798d..827faf57 100644 --- a/src/verifiable/constants.ts +++ b/src/verifiable/constants.ts @@ -4,7 +4,8 @@ export const VerifiableConstants = Object.freeze({ FiELD_IS_EMPTY: 'fieldPath is empty', CONTEXT_TYPE_IS_EMPTY: 'ctxType is empty', // ErrStateNotFound issuer state is genesis state. - IDENTITY_DOES_NOT_EXIST: 'Identity does not exist' + IDENTITY_DOES_NOT_EXIST: 'Identity does not exist', + NO_AUTH_CRED_FOUND: 'no auth credentials found' }, CREDENTIAL_TYPE: { // VerifiableCredential is a W3C verifiable credential type diff --git a/tests/handlers/auth.test.ts b/tests/handlers/auth.test.ts index 2d79ae42..30a205ec 100644 --- a/tests/handlers/auth.test.ts +++ b/tests/handlers/auth.test.ts @@ -40,7 +40,8 @@ import { Sec256k1Provider, StateInfo, hexToBytes, - NativeProver + NativeProver, + VerifiableConstants } from '../../src'; import { Token } from '@iden3/js-jwz'; import { Blockchain, DID, DidMethod, NetworkId } from '@iden3/js-iden3-core'; @@ -2223,12 +2224,12 @@ describe('auth', () => { // check that we don't have auth credentials now await expect(idWallet.getActualAuthCredential(issuerDID)).to.rejectedWith( - 'no auth credentials found' + VerifiableConstants.ERRORS.NO_AUTH_CRED_FOUND ); // check that we can't issue new credential await expect(idWallet.issueCredential(issuerDID, claimReq)).to.rejectedWith( - 'no auth credentials found' + VerifiableConstants.ERRORS.NO_AUTH_CRED_FOUND ); // this should this work because we haven't revoked user keys @@ -2258,7 +2259,7 @@ describe('auth', () => { // this should not work because we revoked user keys await expect(handleAuthorizationRequest(userDID, authReqBody)).to.rejectedWith( - 'no auth credentials found' + VerifiableConstants.ERRORS.NO_AUTH_CRED_FOUND ); }); }); diff --git a/tests/identity/id.test.ts b/tests/identity/id.test.ts index 9f6c414f..155890b7 100644 --- a/tests/identity/id.test.ts +++ b/tests/identity/id.test.ts @@ -28,6 +28,7 @@ import { } from '../helpers'; import { expect } from 'chai'; import { Wallet } from 'ethers'; +import { getRandomBytes } from '@iden3/js-crypto'; describe('identity', () => { let credWallet: ICredentialWallet; @@ -318,4 +319,16 @@ describe('identity', () => { const afterRevokeProofNRcredential2 = await idWallet.generateNonRevocationMtp(did, credential2); expect(afterRevokeProofNRcredential2.proof.existence).to.equal(false); }); + + it("restore identity (doesn't create a new auth BJJ credential)", async () => { + const seed = getRandomBytes(32); + const { did, credential } = await createIdentity(idWallet, { seed }); + + // "restore" identity from the same seed + const { did: restoredDid, credential: restoredCredential } = await createIdentity(idWallet, { + seed + }); + expect(credential).to.be.deep.eq(restoredCredential); + expect(did.string()).to.be.eq(restoredDid.string()); + }); });