Skip to content
Draft
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
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<div align="center">
<h1>Lit Protocol Javascript/Typescript SDK V8.x.x</h1>


<img src="https://i.ibb.co/p2xfzK1/Screenshot-2022-11-15-at-09-56-57.png">
<br/>
<a href="https://twitter.com/LitProtocol"><img src="https://img.shields.io/twitter/follow/litprotocol?label=Follow&style=social"/></a>
Expand Down
93 changes: 91 additions & 2 deletions e2e/src/e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
createCustomAuthContext,
createPkpAuthContext,
createPkpAuthContextWithPreGeneratedMaterials,
} from './helper/auth-contexts';
import {
createExecuteJsTest,
Expand Down Expand Up @@ -154,9 +155,97 @@ describe('all', () => {
});
});

describe('EOA Native', () => {
console.log('🔐 Testing EOA native authentication and PKP minting');
describe('PKP Auth with Pre-generated Materials', () => {
console.log('🔐 Testing PKP auth with pre-generated session materials');

let preGeneratedAuthContext: any;

beforeAll(async () => {
try {
preGeneratedAuthContext =
await createPkpAuthContextWithPreGeneratedMaterials(ctx);
} catch (e) {
console.error('Failed to create pre-generated auth context:', e);
throw e;
}
});

describe('endpoints', () => {
it('pkpSign with pre-generated materials', () =>
createPkpSignTest(ctx, () => preGeneratedAuthContext)());

it('executeJs with pre-generated materials', () =>
createExecuteJsTest(ctx, () => preGeneratedAuthContext)());

it('pkpEncryptDecrypt with pre-generated materials', () =>
createPkpEncryptDecryptTest(ctx, () => preGeneratedAuthContext)());
});

describe('error handling', () => {
it('should reject when only sessionKeyPair is provided', async () => {
const tempAuthContext = await ctx.authManager.createPkpAuthContext({
authData: ctx.aliceViemAccountAuthData,
pkpPublicKey: ctx.aliceViemAccountPkp.publicKey,
authConfig: {
resources: [['pkp-signing', '*']],
expiration: new Date(Date.now() + 1000 * 60 * 15).toISOString(),
},
litClient: ctx.litClient,
});

const sessionKeyPair = tempAuthContext.sessionKeyPair;

await expect(
ctx.authManager.createPkpAuthContext({
authData: ctx.aliceViemAccountAuthData,
pkpPublicKey: ctx.aliceViemAccountPkp.publicKey,
authConfig: {
resources: [['pkp-signing', '*']],
expiration: new Date(Date.now() + 1000 * 60 * 15).toISOString(),
},
litClient: ctx.litClient,
sessionKeyPair, // Only providing sessionKeyPair
// delegationAuthSig is missing
})
).rejects.toThrow(
'Both sessionKeyPair and delegationAuthSig must be provided together, or neither should be provided'
);
});

it('should reject when only delegationAuthSig is provided', async () => {
const tempAuthContext = await ctx.authManager.createPkpAuthContext({
authData: ctx.aliceViemAccountAuthData,
pkpPublicKey: ctx.aliceViemAccountPkp.publicKey,
authConfig: {
resources: [['pkp-signing', '*']],
expiration: new Date(Date.now() + 1000 * 60 * 15).toISOString(),
},
litClient: ctx.litClient,
});

const delegationAuthSig = await tempAuthContext.authNeededCallback();

await expect(
ctx.authManager.createPkpAuthContext({
authData: ctx.aliceViemAccountAuthData,
pkpPublicKey: ctx.aliceViemAccountPkp.publicKey,
authConfig: {
resources: [['pkp-signing', '*']],
expiration: new Date(Date.now() + 1000 * 60 * 15).toISOString(),
},
litClient: ctx.litClient,
// sessionKeyPair is missing
delegationAuthSig, // Only providing delegationAuthSig
})
).rejects.toThrow(
'Both sessionKeyPair and delegationAuthSig must be provided together, or neither should be provided'
);
});
});
});

describe('EOA Native', () => {
console.log('🔐 Testing EOA native authentication and PKP minting');
it('eoaNativeAuthFlow', () => createEoaNativeAuthFlowTest(ctx)());
});
});
Expand Down
134 changes: 133 additions & 1 deletion e2e/src/helper/auth-contexts.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,70 @@
import { init } from '../init';

import { generateSessionKeyPair } from '@lit-protocol/auth';
import { hexToBigInt, keccak256, toBytes } from 'viem';

/**
* Creates a PKP authentication context with pre-generated session materials
* This simulates a server-side use case where session key pair and delegation
* signature are generated once and reused for multiple requests
*/
export const createPkpAuthContextWithPreGeneratedMaterials = async (
ctx: Awaited<ReturnType<typeof init>>
) => {
console.log('🔁 Creating PKP Auth Context with Pre-generated Materials');
try {
// Step 1: Generate a session key pair directly
console.log(' 📝 Step 1: Generating session key pair...');
const sessionKeyPair = generateSessionKeyPair();

// Step 2: Generate PKP delegation signature for the session key pair
console.log(' 📝 Step 2: Generating PKP delegation signature...');
const delegationAuthSig =
await ctx.authManager.generatePkpDelegationAuthSig({
pkpPublicKey: ctx.aliceViemAccountPkp.publicKey,
authData: ctx.aliceViemAccountAuthData,
sessionKeyPair,
authConfig: {
resources: [
['pkp-signing', '*'],
['lit-action-execution', '*'],
['access-control-condition-decryption', '*'],
],
expiration: new Date(Date.now() + 1000 * 60 * 15).toISOString(),
},
litClient: ctx.litClient,
});

console.log(' 📝 Session materials generated:', {
hasSessionKeyPair: !!sessionKeyPair,
hasDelegationAuthSig: !!delegationAuthSig,
sessionKeyPublicKey: sessionKeyPair?.publicKey?.substring(0, 20) + '...',
});

// Step 3: Create auth context using the pre-generated materials
// Using the dedicated function for pre-generated materials with a clean, minimal signature
console.log(
' 📝 Step 3: Creating auth context with pre-generated materials...'
);
const authContextWithPreGenerated =
await ctx.authManager.createPkpAuthContextFromPreGenerated({
pkpPublicKey: ctx.aliceViemAccountPkp.publicKey,
sessionKeyPair,
delegationAuthSig,
// Optional: can provide authData if needed, otherwise minimal default is used
authData: ctx.aliceViemAccountAuthData,
});

console.log('✅ PKP Auth Context with Pre-generated Materials created');
return authContextWithPreGenerated;
} catch (e) {
console.error(
'❌ Error creating PKP Auth Context with Pre-generated Materials',
e
);
throw e;
}
};

/**
* Creates a PKP authentication context
*/
Expand Down Expand Up @@ -78,3 +141,72 @@ export const createCustomAuthContext = async (
throw e;
}
};

/**
* Creates an EOA authentication context with pre-generated session materials
* This demonstrates how to pre-generate EOA session materials for server-side use
*/
export const createEoaAuthContextWithPreGeneratedMaterials = async (
ctx: Awaited<ReturnType<typeof init>>
) => {
console.log('🔁 Creating EOA Auth Context with Pre-generated Materials');
try {
// Step 1: Generate a session key pair directly
console.log(' 📝 Step 1: Generating session key pair...');
const sessionKeyPair = generateSessionKeyPair();

// Step 2: Generate EOA delegation signature for the session key pair
console.log(' 📝 Step 2: Generating EOA delegation signature...');
const delegationAuthSig =
await ctx.authManager.generateEoaDelegationAuthSig({
account: ctx.aliceViemAccount,
sessionKeyPair,
authConfig: {
resources: [
['pkp-signing', '*'],
['lit-action-execution', '*'],
['access-control-condition-decryption', '*'],
],
expiration: new Date(Date.now() + 1000 * 60 * 15).toISOString(),
},
litClient: ctx.litClient,
});

console.log(' 📝 EOA session materials generated:', {
hasSessionKeyPair: !!sessionKeyPair,
hasDelegationAuthSig: !!delegationAuthSig,
sessionKeyPublicKey: sessionKeyPair?.publicKey?.substring(0, 20) + '...',
});

// Step 3: Create EOA auth context using the pre-generated materials
console.log(
' 📝 Step 3: Creating EOA auth context with pre-generated materials...'
);
const authContextWithPreGenerated =
await ctx.authManager.createEoaAuthContext({
authConfig: {
resources: [
['pkp-signing', '*'],
['lit-action-execution', '*'],
['access-control-condition-decryption', '*'],
],
expiration: new Date(Date.now() + 1000 * 60 * 15).toISOString(),
},
config: {
account: ctx.aliceViemAccount,
},
litClient: ctx.litClient,
// Note: EOA auth contexts don't currently support pre-generated materials
// This demonstrates the pattern for when it's implemented
});

console.log('✅ EOA Auth Context with Pre-generated Materials created');
return authContextWithPreGenerated;
} catch (e) {
console.error(
'❌ Error creating EOA Auth Context with Pre-generated Materials',
e
);
throw e;
}
};
26 changes: 26 additions & 0 deletions packages/auth/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,32 @@ export { getAuthIdByAuthMethod } from './lib/authenticators/helper/utils';
*/
export { generateSessionKeyPair } from './lib/AuthManager/utils/generateSessionKeyPair';

/**
* Utility function to generate a PKP delegation auth signature for a given session key pair.
* The PKP will sign the session key delegation message via Lit nodes.
* This function is useful for server-side scenarios where you want to pre-generate
* PKP session materials and reuse them across multiple requests.
*/
export { generatePkpDelegationAuthSig } from './lib/AuthManager/authAdapters/generatePkpDelegationAuthSig';

/**
* Utility function to generate an EOA delegation auth signature for a given session key pair.
* The EOA wallet will sign the session key delegation message directly.
* This function is useful for server-side scenarios where you want to pre-generate
* EOA session materials and reuse them across multiple requests.
*/
export { generateEoaDelegationAuthSig } from './lib/AuthManager/authAdapters/generateEoaDelegationAuthSig';

/**
* Utility function to create a PKP auth context from pre-generated session materials.
* This is a streamlined API for server-side scenarios where session materials
* are generated once and reused across multiple requests.
*
* This function only requires the essential parameters (pkpPublicKey, sessionKeyPair, delegationAuthSig)
* and extracts auth config information from the delegation signature automatically.
*/
export { getPkpAuthContextFromPreGeneratedAdapter } from './lib/AuthManager/authAdapters/getPkpAuthContextFromPreGeneratedAdapter';

// ============================== Authenticators ==============================
export {
DiscordAuthenticator,
Expand Down
37 changes: 32 additions & 5 deletions packages/auth/src/lib/AuthManager/auth-manager.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { getChildLogger } from '@lit-protocol/logger';
import { AuthData, HexPrefixedSchema } from '@lit-protocol/schemas';
// import { AuthSig, SessionKeyPair } from '@lit-protocol/types';
import { AuthSig, SessionKeyPair } from '@lit-protocol/types';
import { z } from 'zod';
import { AuthConfigV2 } from '../authenticators/types';
import type { LitAuthStorageProvider } from '../storage/types';
Expand All @@ -11,7 +11,9 @@ import {
import { getPkpAuthContextAdapter } from './authAdapters/getPkpAuthContextAdapter';
import { AuthConfigSchema } from './authContexts/BaseAuthContextType';
import { getCustomAuthContextAdapter } from './authAdapters/getCustomAuthContextAdapter';
import { hexToBigInt, keccak256, toBytes } from 'viem';
import { generatePkpDelegationAuthSig } from './authAdapters/generatePkpDelegationAuthSig';
import { generateEoaDelegationAuthSig } from './authAdapters/generateEoaDelegationAuthSig';
import { getPkpAuthContextFromPreGeneratedAdapter } from './authAdapters/getPkpAuthContextFromPreGeneratedAdapter';

export interface AuthManagerParams {
storage: LitAuthStorageProvider;
Expand Down Expand Up @@ -77,12 +79,20 @@ export const createAuthManager = (authManagerParams: AuthManagerParams) => {
cache?: {
delegationAuthSig?: boolean;
};
// Optional pre-generated auth materials for server-side usage
// sessionKeyPair?: SessionKeyPair;
// delegationAuthSig?: AuthSig;
}) => {
return getPkpAuthContextAdapter(authManagerParams, params);
},
createPkpAuthContextFromPreGenerated: (params: {
pkpPublicKey: z.infer<typeof HexPrefixedSchema>;
sessionKeyPair: SessionKeyPair;
delegationAuthSig: AuthSig;
authData?: AuthData;
}) => {
return getPkpAuthContextFromPreGeneratedAdapter(
authManagerParams,
params
);
},
createCustomAuthContext: (params: {
// authData: AuthData;
pkpPublicKey: z.infer<typeof HexPrefixedSchema>;
Expand All @@ -104,5 +114,22 @@ export const createAuthManager = (authManagerParams: AuthManagerParams) => {

return getCustomAuthContextAdapter(authManagerParams, params);
},
generatePkpDelegationAuthSig: (params: {
pkpPublicKey: z.infer<typeof HexPrefixedSchema>;
authData: AuthData;
sessionKeyPair: SessionKeyPair;
authConfig: AuthConfigV2;
litClient: BaseAuthContext<any>['litClient'];
}) => {
return generatePkpDelegationAuthSig(authManagerParams, params);
},
generateEoaDelegationAuthSig: (params: {
account: any; // ExpectedAccountOrWalletClient type
sessionKeyPair: SessionKeyPair;
authConfig: AuthConfigV2;
litClient: BaseAuthContext<any>['litClient'];
}) => {
return generateEoaDelegationAuthSig(authManagerParams, params);
},
};
};
Loading
Loading