Skip to content

Commit

Permalink
feat(taco): expose auth providers from taco - wip
Browse files Browse the repository at this point in the history
  • Loading branch information
piotr-roslaniec committed Jul 1, 2024
1 parent 4eea8e7 commit 51e5402
Show file tree
Hide file tree
Showing 11 changed files with 85 additions and 42 deletions.
1 change: 1 addition & 0 deletions examples/taco/nodejs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
},
"dependencies": {
"@nucypher/taco": "workspace:*",
"@nucypher/taco-auth": "workspace:*",
"dotenv": "^16.3.1",
"ethers": "^5.7.2"
}
Expand Down
11 changes: 8 additions & 3 deletions examples/taco/nodejs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { format } from 'node:util';

import {
conditions,
decrypt,
decrypt, decryptWithAuthProviders,
domains,
encrypt,
fromBytes,
Expand All @@ -14,6 +14,7 @@ import {
} from '@nucypher/taco';
import * as dotenv from 'dotenv';
import { ethers } from 'ethers';
import { makeAuthProviders } from '@nucypher/taco-auth';

dotenv.config();

Expand Down Expand Up @@ -84,12 +85,16 @@ const decryptFromBytes = async (encryptedBytes: Uint8Array) => {

const messageKit = ThresholdMessageKit.fromBytes(encryptedBytes);
console.log('Decrypting message ...');
return decrypt(
const authProviders = makeAuthProviders(provider, consumerSigner, {
domain: 'localhost',
uri: 'http://localhost:3000',
});
return decryptWithAuthProviders(
provider,
domain,
messageKit,
authProviders,
getPorterUri(domain),
consumerSigner,
);
};

Expand Down
3 changes: 3 additions & 0 deletions examples/taco/nodejs/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@
{
"path": "../../../packages/taco/tsconfig.cjs.json",
},
{
"path": "../../../packages/taco-auth/tsconfig.cjs.json",
}
],
}
1 change: 1 addition & 0 deletions packages/taco-auth/src/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { AuthProviders, EIP4361_AUTH_METHOD, EIP712_AUTH_METHOD } from './types'
export const makeAuthProviders = (
provider: ethers.providers.Provider,
signer?: ethers.Signer,
// TODO: Expose these parameters to the user in taco.ts
siweDefaultParams?: EIP4361AuthProviderParams
): AuthProviders => {
return {
Expand Down
45 changes: 21 additions & 24 deletions packages/taco-auth/src/providers/eip4361.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,33 @@ const ERR_MISSING_SIWE_PARAMETERS = 'Missing default SIWE parameters';

export class EIP4361AuthProvider {
private readonly storage: LocalStorage;
private readonly providerParams: EIP4361AuthProviderParams;

constructor(
// TODO: We only need the provider to fetch the chainId, consider removing it
private readonly provider: ethers.providers.Provider,
private readonly signer: ethers.Signer,
private readonly providerParams?: EIP4361AuthProviderParams,
providerParams?: EIP4361AuthProviderParams,
) {
this.storage = new LocalStorage();
if (providerParams) {
this.providerParams = providerParams;
} else {
this.providerParams = this.getDefaultParameters();
}
}

private getDefaultParameters() {
if (typeof window !== 'undefined') {
// If we are in a browser environment, we can get the domain and uri from the window object
const maybeOrigin = window?.location?.origin;
return {
domain: maybeOrigin.split('//')[1].split('.')[0],
uri: maybeOrigin,
};
}
// If not, we have no choice but to throw an error
throw new Error(ERR_MISSING_SIWE_PARAMETERS);
}

public async getOrCreateAuthSignature(): Promise<AuthSignature> {
Expand All @@ -43,7 +62,7 @@ export class EIP4361AuthProvider {

private async createSIWEAuthMessage(): Promise<AuthSignature> {
const address = await this.signer.getAddress();
const { domain, uri } = this.getParametersOrDefault();
const { domain, uri } = this.providerParams;
const version = '1';
const nonce = generateNonce();
const chainId = (await this.provider.getNetwork()).chainId;
Expand All @@ -61,26 +80,4 @@ export class EIP4361AuthProvider {
const signature = await this.signer.signMessage(message);
return { signature, address, scheme, typedData: message };
}

// TODO: Create a facility to set these parameters or expose them to the user
private getParametersOrDefault(): {
domain: string;
uri: string;
} {
// If we are in a browser environment, we can get the domain and uri from the window object
if (typeof window !== 'undefined') {
const maybeOrigin = window?.location?.origin;
return {
domain: maybeOrigin.split('//')[1].split('.')[0],
uri: maybeOrigin,
};
}
if (this.providerParams) {
return {
domain: this.providerParams.domain,
uri: this.providerParams.uri,
}
}
throw new Error(ERR_MISSING_SIWE_PARAMETERS);
}
}
2 changes: 1 addition & 1 deletion packages/taco/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ export {

export * as conditions from './conditions';
// Expose registerEncrypters from taco API (#324)
export { decrypt, encrypt, encryptWithPublicKey, isAuthorized } from './taco';
export { decrypt, decryptWithAuthProviders, encrypt, encryptWithPublicKey, isAuthorized } from './taco';
25 changes: 21 additions & 4 deletions packages/taco/src/taco.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
GlobalAllowListAgent,
toBytes,
} from '@nucypher/shared';
import { makeAuthProviders } from '@nucypher/taco-auth';
import { AuthProviders, makeAuthProviders } from '@nucypher/taco-auth';
import { ethers } from 'ethers';
import { keccak256 } from 'ethers/lib/utils';

Expand Down Expand Up @@ -143,6 +143,25 @@ export const decrypt = async (
porterUri?: string,
signer?: ethers.Signer,
customParameters?: Record<string, CustomContextParam>,
): Promise<Uint8Array> => {
const authProviders = makeAuthProviders(provider, signer);
return decryptWithAuthProviders(
provider,
domain,
messageKit,
authProviders,
porterUri,
customParameters,
);
};

export const decryptWithAuthProviders = async (
provider: ethers.providers.Provider,
domain: Domain,
messageKit: ThresholdMessageKit,
authProviders?: AuthProviders,
porterUri?: string,
customParameters?: Record<string, CustomContextParam>,
): Promise<Uint8Array> => {
if (!porterUri) {
porterUri = getPorterUri(domain);
Expand All @@ -154,8 +173,6 @@ export const decrypt = async (
messageKit.acp.publicKey,
);
const ritual = await DkgClient.getActiveRitual(provider, domain, ritualId);
// TODO: Temporary helper method to keep the external taco.ts decrypt function simple
const authProviders = makeAuthProviders(provider, signer);
return retrieveAndDecrypt(
provider,
domain,
Expand Down Expand Up @@ -188,7 +205,7 @@ export const isAuthorized = async (
domain: Domain,
messageKit: ThresholdMessageKit,
ritualId: number,
) =>
): Promise<boolean> =>
DkgCoordinatorAgent.isEncryptionAuthorized(
provider,
domain,
Expand Down
31 changes: 22 additions & 9 deletions packages/taco/test/taco.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
SessionStaticSecret,
} from '@nucypher/nucypher-core';
import { USER_ADDRESS_PARAM_DEFAULT } from '@nucypher/taco-auth';
import * as tacoAuth from '@nucypher/taco-auth';
import {
aliceSecretKeyBytes,
fakeDkgFlow,
Expand All @@ -13,9 +14,9 @@ import {
fakeTDecFlow,
mockGetRitualIdFromPublicKey,
mockTacoDecrypt,
TEST_CHAIN_ID,
TEST_CHAIN_ID, TEST_SIWE_PARAMS,
} from '@nucypher/test-utils';
import { beforeAll, describe, expect, it } from 'vitest';
import { beforeAll, describe, expect, it, vi } from 'vitest';

import * as taco from '../src';
import { conditions, domains, toBytes } from '../src';
Expand All @@ -36,6 +37,7 @@ const ownsNFT = new conditions.predefined.erc721.ERC721Ownership({
chain: TEST_CHAIN_ID,
});


describe('taco', () => {
beforeAll(async () => {
await initialize();
Expand Down Expand Up @@ -81,30 +83,41 @@ describe('taco', () => {
);
const getRitualSpy = mockGetActiveRitual(mockedDkgRitual);

const decryptedMessage = await taco.decrypt(
const authProviders = tacoAuth.makeAuthProviders(provider, signer,TEST_SIWE_PARAMS);
const decryptedMessage1 = await taco.decryptWithAuthProviders(
provider,
domains.DEVNET,
messageKit,
authProviders,
fakePorterUri,
signer,
);
expect(decryptedMessage1).toEqual(toBytes(message));
expect(getParticipantsSpy).toHaveBeenCalled();
expect(sessionKeySpy).toHaveBeenCalled();
expect(getRitualIdFromPublicKey).toHaveBeenCalled();
expect(getRitualSpy).toHaveBeenCalled();
expect(decryptSpy).toHaveBeenCalled();
expect(decryptedMessage).toEqual(toBytes(message));

const makeAuthProvidersSpy = vi.spyOn(tacoAuth, 'makeAuthProviders').mockImplementation(() => authProviders);
const decryptedMessage2 = await taco.decrypt(
provider,
domains.DEVNET,
messageKit,
fakePorterUri,
signer,
);
expect(makeAuthProvidersSpy).toHaveBeenCalled();
expect(decryptedMessage2).toEqual(toBytes(message));
});

it('exposes requested parameters', async ()=> {
it('exposes requested parameters', async () => {
const mockedDkg = fakeDkgFlow(FerveoVariant.precomputed, 0, 4, 4);
const mockedDkgRitual = fakeDkgRitual(mockedDkg);
const provider = fakeProvider(aliceSecretKeyBytes);
const signer = fakeSigner(aliceSecretKeyBytes);
const getFinalizedRitualSpy = mockGetActiveRitual(mockedDkgRitual);


const customParamKey = ":nftId";
const customParamKey = ':nftId';
const ownsNFTWithCustomParams = new conditions.predefined.erc721.ERC721Ownership({
contractAddress: '0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77',
parameters: [customParamKey],
Expand All @@ -123,5 +136,5 @@ describe('taco', () => {

const requestedParameters = taco.conditions.context.ConditionContext.requestedContextParameters(messageKit);
expect(requestedParameters).toEqual(new Set([customParamKey, USER_ADDRESS_PARAM_DEFAULT]));
})
});
});
1 change: 1 addition & 0 deletions packages/taco/test/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import { ReturnValueTestProps } from '../src/conditions/shared';
import { DkgClient, DkgRitual } from '../src/dkg';
import { encryptMessage } from '../src/tdec';


export const fakeDkgTDecFlowE2E: (
ritualId?: number,
variant?: FerveoVariant,
Expand Down
4 changes: 3 additions & 1 deletion packages/test-utils/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ import axios from 'axios';
import { ethers, providers, Wallet } from 'ethers';
import { expect, SpyInstance, vi } from 'vitest';

import { TEST_SIWE_PARAMS } from './variables';

export const bytesEqual = (first: Uint8Array, second: Uint8Array): boolean =>
first.length === second.length &&
first.every((value, index) => value === second[index]);
Expand Down Expand Up @@ -79,7 +81,7 @@ export const fakeSigner = (
} as unknown as ethers.providers.JsonRpcSigner;
};

export const fakeAuthProviders = () => makeAuthProviders(fakeProvider(), fakeSigner());
export const fakeAuthProviders = () => makeAuthProviders(fakeProvider(), fakeSigner(), TEST_SIWE_PARAMS);

export const fakeProvider = (
secretKeyBytes = SecretKey.random().toBEBytes(),
Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 51e5402

Please sign in to comment.