From c4bf59b642b58e7bd81ab2dc1bebd4ce5edeba9a Mon Sep 17 00:00:00 2001 From: Wyatt Barnes Date: Thu, 30 May 2024 19:12:36 -1000 Subject: [PATCH 1/3] Init rewrite --- .../session-sigs/get-session-sigs.md | 372 ++++++++++++++---- 1 file changed, 287 insertions(+), 85 deletions(-) diff --git a/docs/sdk/authentication/session-sigs/get-session-sigs.md b/docs/sdk/authentication/session-sigs/get-session-sigs.md index a1138376..e596c9b5 100644 --- a/docs/sdk/authentication/session-sigs/get-session-sigs.md +++ b/docs/sdk/authentication/session-sigs/get-session-sigs.md @@ -1,113 +1,315 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + --- sidebar_position: 2 --- import FeedbackComponent from "@site/src/pages/feedback.md"; -# Generating SessionSigs +# Generating Session Signatures + +[Session signatures](./intro.md) can be obtained using the [getSessionSigs](https://v5.api-docs.getlit.dev/classes/lit_node_client_src.LitNodeClientNodeJs.html#getSessionSigs) method provided by the Lit SDK. This method will generate a _session keypair_ for you locally, and will use the `authNeededCallback` method you specify to sign the session keypair, authorizing it to use the specified [Lit Resources and Abilities](./resources-and-abilities.md) on the Lit network. + +Below we will walk through an example of generating session signatures, the full code implementation can be found [here](https://github.com/LIT-Protocol/developer-guides-code/blob/wyatt/get-session-sigs-via-auth-sig/get-session-sigs-via-auth-sig/nodejs). + +## Paying for Usage of the Lit Network + +The correct code implementation will depend on whether you're using the free-to-use `cayenne` network, or one of the "paid" networks: `habanero` or `manzano`. + +Usage of the `habanero` and `manzano` networks require the use of [Lit Capacity Credits](../../../sdk/capacity-credits.md). Currently, Capacity Credits are paid for using the `testLPX` token and don't require any real-world money. However, in the future you will need to pay real-world money for usage of Lit networks, and `habanero` and `manzano` are the Lit networks were this functionality is being tested and refined. + +So, some of the below code snippets will show different implementations based on whether you intend to use the code on `cayenne` or `habanero`/`manzano` networks. + +## Specifying an Ethereum Private Key + +Our first step will be to specify what Etheruem private key we will use to provide the Authorization Signature for our Session Keys: + +```ts +const ETHEREUM_PRIVATE_KEY = process.env.ETHEREUM_PRIVATE_KEY; +``` + +If you're intending to use the `cayenne` network, this can be any Ethereum wallet. + +If you're intending to use the `habanero` or `manzano` networks, the corresponding Ethereum address for the private key should have minted Capacity Credits to pay for the request to the Lit network to generate the Session Signatures (please see the [Capacity Credits](../../../sdk/capacity-credits.md) docs for more info on minting Capacity Credits). -You can use any wallet or auth method to generate session signatures with the `getSessionSigs()` function from the Lit SDK. This function generates a session keypair and uses a callback function that signs the generated session key to create an `AuthSig` that is scoped to specific capabilities. +## Instantiating an Ethers.js Wallet -In order to generate `SessionSigs`, you need a `capacityDelegationAuthSig` in signatures. This is because capacity credits are now required on both `Habanero` and `Manzano` networks. You can buy or [mint](../../capacity-credits.md#minting-capacity-credits) capacity credits centrally and [delegate](../../capacity-credits.md#delegating-access-to-your-capacity-credits-nft) them to your users. +Next we'll use our `ETHEREUM_PRIVATE_KEY` constant to instantiate an instance of `ethers.Wallet`: + +```ts +const ethersSigner = new ethers.Wallet(ETHEREUM_PRIVATE_KEY); +``` + +We will be using this wallet to sign the Authorization Signature for our Session Keys, granting our Session Keys the ability to use the [Lit Resources and Abilities](./resources-and-abilities.md) we'll specify when making the call to generation our Session Signatures. + +## Connecting to the Lit Network + +In order to make requests to the Lit network, we're going to instantiate an instance of `LitNodeClient` which is imported from the `@lit-protocol/lit-node-client` package: + +```ts +import { LitNodeClient } from "@lit-protocol/lit-node-client"; +``` + +The below code varies depending on the Lit network you want to connect to. For convenience, the `LitNetwork` `enum` can be imported from the `@lit-protocol/constants` to help you specify which network you'd like to use: + +```ts +import { LitNetwork } from "@lit-protocol/constants"; +``` + +Additionally, the below code makes use of `LocalStorage` imported from the `node-localstorage` package: + +```ts +import { LocalStorage } from "node-localstorage"; +``` -You can generate a `SessionSig` with the help of `capacityDelegationAuthSig` object in the following way: +In order to get Session Signatures from the Lit network, the Lit SDK must first generate Session Keys which will be the keys being authorized by the Session Signatures. -```javascript -import { LitNodeClient } from '@lit-protocol/lit-node-client'; -import { LitAccessControlConditionResource, LitAbility } from '@lit-protocol/auth-helpers'; +When running this code within the browser, the Session Keys are stored within the browser's local storage. The `LocalStorage` module is **not** required and therefore you do not need to install the `node-localstorage` package, and the package `import` and `storageProvider` object in the below code can be omitted. -// Create a new ethers.js Wallet instance -const wallet = new Wallet(process.env.YOUR_PRIVATE_KEY); +However, the browser local storage is not available when executing in an environment such as Node.js. To compensate for this we make use of the `LocalStorage` module to provide file based storage for our generated Session Keys and metadata. If you do not provide an instance of `LocalStorage` as the `provider` (as shown in the below code), then new Session Keys will be generated every time you run this code instead one set of keys being reused. -// Instantiate a LitNodeClient -const litNodeClient = new LitNodeClient({ - litNetwork: "manzano", - debug: true, +Now we'll use the imported `LitNodeClient` module to connect to the Lit network specified using the `LitNetwork` `enum`, and using in instance of `LocalStorage` for our `provider`: + + + +```ts +litNodeClient = new LitNodeClient({ + litNetwork: LitNetwork.Cayenne, + // This storageProvider object can be omitted if executing in a browser + storageProvider: { + provider: new LocalStorage("./lit_storage.db"), + }, +}); +``` + + + +```ts +litNodeClient = new LitNodeClient({ + litNetwork: LitNetwork.Habanero, + // This storageProvider object can be omitted if executing in a browser + storageProvider: { + provider: new LocalStorage("./lit_storage.db"), + }, +}); +``` + + + +```ts +litNodeClient = new LitNodeClient({ + litNetwork: LitNetwork.Manzano, + // This storageProvider object can be omitted if executing in a browser + storageProvider: { + provider: new LocalStorage("./lit_storage.db"), + }, }); +``` + + + +After you have an instance of `LitNodeClient`, you'll want to connect it to the Lit network using: + +```ts await litNodeClient.connect(); +``` -let nonce = await litNodeClient.getLatestBlockhash(); - -/** - * When the getSessionSigs function is called, it will generate a session key - * and sign it using a callback function. The authNeededCallback parameter - * in this function is optional. If you don't pass this callback, - * then the user will be prompted to authenticate with their wallet. - */ -const authNeededCallback = async ({ chain, resources, expiration, uri }) => { - const domain = "localhost:3000"; - const message = new SiweMessage({ - domain, - address: wallet.address, - statement: "Sign a session key to use with Lit Protocol", - uri, - version: "1", - chainId: "1", - expirationTime: expiration, - resources, - nonce, - }); - const toSign = message.prepareMessage(); - const signature = await wallet.signMessage(toSign); - - const authSig = { - sig: signature, - derivedVia: "web3.eth.personal.sign", - signedMessage: toSign, - address: wallet.address, - }; - - return authSig; -}; - -// Create an access control condition resource -const litResource = new LitAccessControlConditionResource( - hashedEncryptedSymmetricKeyString -); - -const sessionSigs = await litNodeClient.getSessionSigs({ - chain: "ethereum", - resourceAbilityRequests: [ +## Getting the Session Signatures + +Now that we're connecting to the Lit network, we can request Session Signatures for our Session Keys. We're going to cover each line of the below code, but for context here is the whole function call to get our Session Signatures: + +```ts +await litNodeClient.getSessionSigs({ + expiration: new Date(Date.now() + 1000 * 60 * 60 * 24).toISOString(), // 24 hours + resourceAbilityRequests: [ { - resource: litResource, - ability: LitAbility.AccessControlConditionDecryption - } - ], - authNeededCallback, - capacityDelegationAuthSig, // here is where we add the delegation to our session request + resource: new LitAccessControlConditionResource("*"), + ability: LitAbility.AccessControlConditionDecryption, + }, + ], + authNeededCallback: async ({ + uri, + expiration, + resourceAbilityRequests, + }) => { + const toSign = await createSiweMessage({ + uri, + expiration, + resources: resourceAbilityRequests, + walletAddress: await ethersSigner.getAddress(), + nonce: await litNodeClient.getLatestBlockhash(), + litNodeClient, + }); + + return await generateAuthSig({ + signer: ethersSigner, + toSign, + }); + }, +}); +``` + +### `expiration` + +Our `expiration` property specifies how long the Session Signatures for our Session Keys will be valid for. + +### `resourceAbilityRequests` + +As mentioned previously, [Lit Resources and Abilities](./resources-and-abilities.md) are used to define what our Session Signature is allowing our Session Keys to do on the Lit network. + +There are two parts to each ability request: + +#### `resource` + +This property is defining what Lit Resource we're granting the `ability` for. Each Lit Resource takes a resource identifier as an argument. You can pass `"*"` like so: + +```ts +new LitPKPResource("*") +``` + +to grant an `ability` to all resources owned by the Ethereum address that authorized the request to generate Session Signatures for the Session Keys. In the case of this example, that would be the address corresponding to our `ETHEREUM_PRIVATE_KEY` constant (that we created an Ethers.js wallet for). + +Or you can specify a specific identifier for each resource as shown in the code snippets below. + +The available Lit Resource options are: + +##### `LitAccessControlConditionResource` + +Imported from the `@lit-protocol/auth-helpers` package: + +```ts +import { LitAccessControlConditionResource } from "@lit-protocol/auth-helpers"; +``` + +This resource specifies a Lit Access Control Conditions (ACC) the `ability` is being granted for. Specifying `"*"` grants the `ability` to any ACC, regardless of what the conditions are. To grant the `ability` for a specific ACC, you can specify the hashed key value of the ACC in place of `"*"` like so: + + + +```ts +new LitAccessControlConditionResource("") +``` + +##### `LitPKPResource` + +Imported from the `@lit-protocol/auth-helpers` package: + +```ts +import { LitPKPResource } from "@lit-protocol/auth-helpers"; +``` + +This resource specifies what Lit Programmable Key Pair (PKP) the `ability` is being granted for. Specifying `"*"` grants the `ability` for all PKPs. To grant the `ability` for a specific PKP, you can specify the token ID of the PKP in place of `"*"` like so: + +```ts +new LitPKPResource("42") +``` + +##### `LitRLIResource` + +Imported from the `@lit-protocol/auth-helpers` package: + +```ts +import { LitRLIResource } from "@lit-protocol/auth-helpers"; +``` + +This resource specifies what Lit Capacity Credit the `ability` is being granted for. Specifying `"*"` grants the `ability` for all Capacity Credits. To grant the `ability` for a specific Capacity Credit, you can specify the token ID in place of `"*"` like so: + +```ts +new LitRLIResource("42") +``` + +##### `LitActionResource` + +Imported from the `@lit-protocol/auth-helpers` package: + +```ts +import { LitActionResource } from "@lit-protocol/auth-helpers"; +``` + +This resource specifies what Lit Actions the `ability` is being granted for. Specifying `"*"` grants the `ability` for all Lit Actions, regardless of who created them. To grant the `ability` for a specific Lit Action, you can specify an IPFS Content Identifier (CID) in place of `"*"` like so: + +```ts +new LitActionResource("QmX8bs6vhiFvwgYS39ZqDW421D1885n3KNzqqwRhTPTP8e") +``` + +#### `ability` + +`ability` is the second part of each Lit Resource Request, and it specifies what we're allowing the Session Keys to do with a Lit Resource. + +Each available ability can be specified using the `LitAbility` `enum` which can be imported from the `@lit-protocol/auth-helpers` package: + +```ts +import { LitAbility } from "@lit-protocol/auth-helpers"; +``` + +The abilities available to grant are: + +- `AccessControlConditionDecryption` This grants the ability to decrypt some Lit encrypted data if the Access Control Conditions are satisfied + +- `AccessControlConditionSigning` This grants the ability to sign data using threshold signing by the Lit nodes in the network if the Access Control Conditions is satisfied. +- `PKPSigning` This grants the ability to sign data using a PKP. +- `RateLimitIncreaseAuth` This grants the ability to increase the rate limit of a Capacity Credit. +- `LitActionExecution` This grants the ability to execute a Lit Action. + +### `authNeededCallback` + +This property specifies a function that returns an Authorization Signature signifying that we are granting the Session Keys with the abilities for the specified resources. You are free to customized the function as it suits your use case, but a standard implementation is as follows: + +```ts +authNeededCallback: async ({ +uri, +expiration, +resourceAbilityRequests, +}) => { +const toSign = await createSiweMessage({ + uri, + expiration, + resources: resourceAbilityRequests, + walletAddress: await ethersSigner.getAddress(), + nonce: await litNodeClient.getLatestBlockhash(), + litNodeClient, }); + +return await generateAuthSig({ + signer: ethersSigner, + toSign, +}); +}, ``` -**Note:** The nonce should be the latest Ethereum blockhash returned by the nodes during the handshake. +The parameters `uri`, `expiration`, and `resourceAbilityRequests` are automatically passed into our function by the Lit SDK. `expiration` and `resourceAbilityRequests` refer to the same properties we defined above. `uri` is going to be the `publicKey` of your Session Key. -:::note - If running the SDK in a Server environment, session signatures may *not* be cached unless you provide an instance of `Storage` to the runtime. - [Here](https://www.npmjs.com/package/node-localstorage) is an implementation of `LocalStorage` which creates local files to persist storage data. - If storage is not available, session keys *MUST* be persisted in an external data store. - ```javascript - const LocalStorage = require('node-localstorage').LocalStorage; - const litNodeClient = new LitNodeClient({ - litNetwork: "cayenne", - debug: true, - storageProvider: { - provider: new LocalStorage('./storage.test.db'), - } - }); - ``` -::: +Within our function, we're using the `createSiweMessage` that can be imported from the `@lit-protocol/auth-helpers` package: -The `getSessionSigs()` function will try to create a session key for you and store it in local storage. You can also generate the session key yourself using `generateSessionKeyPair()` function and store it however you like. You can then pass the generated session key to `getSessionSigs()` as the `sessionKey` param. +```ts +import { createSiweMessage } from "@lit-protocol/auth-helpers"; +``` -In the example above, we construct a SIWE message manually, but you can use the `checkAndSignAuthMessage` when in a browser context. +This helper function produces an [ERC-4361 Sign in With Ethereum (SIWE) message](https://eips.ethereum.org/EIPS/eip-4361) using the parameters we provide. The other properties we're providing to this helper functions are: -## Resources You Can Request +- `walletAddress` This is the corresponding address to the Ethereum private key that we will be using to sign the SIWE message. +- `nonce` Is an Ethereum block hash and the timestamp of the block needs to be within 5 minutes of the `issued at` timestamp of the SIWE message. +- `litNodeClient` Is the instance of `LitNodeClient` that was previously instantiated and connected to the Lit network. -You can pass an array of "resource ability requests" to the `getSessionSigs()` function, which will be presented to the user in the SIWE message - read more [here](resources-and-abilities) about Lit resources and abilities. The resources and abilities requested by the session key must be narrower or equal to the capabilities granted to it per the session capability object specified in the inner `AuthSig`. +The next helper function we make use of is `generateAuthSig` which can be imported from the `@lit-protocol/auth-helpers` package: -When session capability objects are omitted from the `getSessionSigs()` function call, the SDK will generate a session capability object with **wildcard permissions against all of the resources in that category by default**, i.e. ability to perform operations against all access control conditions. Read more [here](capability-objects) about how to create custom session capability objects. +```ts +import { generateAuthSig } from "@lit-protocol/auth-helpers"; +``` -## Clearing Local Storage +We pass our Ethers.js wallet that we instantiated early, and the result of our call to `createSiweMessage`: -If you want to clear the session key stored in the browser local storage, you can call the [`disconnectWeb3` method](https://js-sdk.litprotocol.com/functions/auth_browser_src.ethConnect.disconnectWeb3.html). +```ts +return await generateAuthSig({ + signer: ethersSigner, + toSign, +}); +``` - +`generateAuthSig` will use our Ethers.js wallet to sign our SIWE message, producing an Authorization Signature that authorizes our Session Key to use our Lit Resources with our specified abilities. From c1975839784b1879e4a9d5b96b5f0969693252aa Mon Sep 17 00:00:00 2001 From: Wyatt Barnes Date: Thu, 30 May 2024 19:18:39 -1000 Subject: [PATCH 2/3] Add prereqs section --- .../session-sigs/get-session-sigs.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/sdk/authentication/session-sigs/get-session-sigs.md b/docs/sdk/authentication/session-sigs/get-session-sigs.md index e596c9b5..012df9ce 100644 --- a/docs/sdk/authentication/session-sigs/get-session-sigs.md +++ b/docs/sdk/authentication/session-sigs/get-session-sigs.md @@ -13,6 +13,22 @@ import FeedbackComponent from "@site/src/pages/feedback.md"; Below we will walk through an example of generating session signatures, the full code implementation can be found [here](https://github.com/LIT-Protocol/developer-guides-code/blob/wyatt/get-session-sigs-via-auth-sig/get-session-sigs-via-auth-sig/nodejs). +## Prerequisites + +Before continuing with this guide, you should have an understanding of: + +- [Session Signatures](../../authentication/session-sigs/intro.md) +- [Lit Capacity Credits](../../../sdk/capacity-credits.md) +- [Lit Resources and Abilities](./resources-and-abilities.md) + +This guide also has a dependency on the following packages: + +- `"@lit-protocol/auth-helpers": "^6.0.0-beta.3"` +- `"@lit-protocol/constants": "^6.0.0-beta.3"` +- `"@lit-protocol/lit-node-client": "^6.0.0-beta.3"` +- `"ethers": "v5"` +- `"node-localstorage": "^3.0.5"` (Optional dependency depending on whether or not you're executing the Lit code within a browser. Explained further in the [Connecting to the Lit Network](#connecting-to-the-lit-network) section) + ## Paying for Usage of the Lit Network The correct code implementation will depend on whether you're using the free-to-use `cayenne` network, or one of the "paid" networks: `habanero` or `manzano`. From 30c8e836204d223a56ff44087c5efbd8a72bd5b9 Mon Sep 17 00:00:00 2001 From: Wyatt Barnes Date: Tue, 4 Jun 2024 17:35:34 -1000 Subject: [PATCH 3/3] Formatting --- .../authentication/session-sigs/get-session-sigs.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/sdk/authentication/session-sigs/get-session-sigs.md b/docs/sdk/authentication/session-sigs/get-session-sigs.md index 012df9ce..a72b290b 100644 --- a/docs/sdk/authentication/session-sigs/get-session-sigs.md +++ b/docs/sdk/authentication/session-sigs/get-session-sigs.md @@ -9,7 +9,7 @@ import FeedbackComponent from "@site/src/pages/feedback.md"; # Generating Session Signatures -[Session signatures](./intro.md) can be obtained using the [getSessionSigs](https://v5.api-docs.getlit.dev/classes/lit_node_client_src.LitNodeClientNodeJs.html#getSessionSigs) method provided by the Lit SDK. This method will generate a _session keypair_ for you locally, and will use the `authNeededCallback` method you specify to sign the session keypair, authorizing it to use the specified [Lit Resources and Abilities](./resources-and-abilities.md) on the Lit network. +[Session signatures](./intro.md) can be obtained using the [getSessionSigs](https://v5.api-docs.getlit.dev/classes/lit_node_client_src.LitNodeClientNodeJs.html#getSessionSigs) method provided by the Lit SDK. This method will generate a _session keypair_ for you locally, and will use the `authNeededCallback` method you specify to sign the Session Keypair, authorizing it to use the specified [Lit Resources and Abilities](./resources-and-abilities.md) on the Lit network. Below we will walk through an example of generating session signatures, the full code implementation can be found [here](https://github.com/LIT-Protocol/developer-guides-code/blob/wyatt/get-session-sigs-via-auth-sig/get-session-sigs-via-auth-sig/nodejs). @@ -27,19 +27,20 @@ This guide also has a dependency on the following packages: - `"@lit-protocol/constants": "^6.0.0-beta.3"` - `"@lit-protocol/lit-node-client": "^6.0.0-beta.3"` - `"ethers": "v5"` -- `"node-localstorage": "^3.0.5"` (Optional dependency depending on whether or not you're executing the Lit code within a browser. Explained further in the [Connecting to the Lit Network](#connecting-to-the-lit-network) section) +- `"node-localstorage": "^3.0.5"` + - (Optional dependency depending on whether or not you're executing the Lit code within a browser. Explained further in the [Connecting to the Lit Network](#connecting-to-the-lit-network) section) ## Paying for Usage of the Lit Network The correct code implementation will depend on whether you're using the free-to-use `cayenne` network, or one of the "paid" networks: `habanero` or `manzano`. -Usage of the `habanero` and `manzano` networks require the use of [Lit Capacity Credits](../../../sdk/capacity-credits.md). Currently, Capacity Credits are paid for using the `testLPX` token and don't require any real-world money. However, in the future you will need to pay real-world money for usage of Lit networks, and `habanero` and `manzano` are the Lit networks were this functionality is being tested and refined. +Usage of the `habanero` and `manzano` networks require the use of [Lit Capacity Credits](../../../sdk/capacity-credits.md). Currently, Capacity Credits are paid for using the `testLPX` token and don't require any real-world money. However, in the future you will need to pay real-world money for usage of Lit networks, and `habanero` and `manzano` are the Lit networks where this functionality is being tested and refined. So, some of the below code snippets will show different implementations based on whether you intend to use the code on `cayenne` or `habanero`/`manzano` networks. ## Specifying an Ethereum Private Key -Our first step will be to specify what Etheruem private key we will use to provide the Authorization Signature for our Session Keys: +Our first step will be to specify what Ethereum private key we will use to provide the Authorization Signature for our Session Keys: ```ts const ETHEREUM_PRIVATE_KEY = process.env.ETHEREUM_PRIVATE_KEY; @@ -57,7 +58,7 @@ Next we'll use our `ETHEREUM_PRIVATE_KEY` constant to instantiate an instance of const ethersSigner = new ethers.Wallet(ETHEREUM_PRIVATE_KEY); ``` -We will be using this wallet to sign the Authorization Signature for our Session Keys, granting our Session Keys the ability to use the [Lit Resources and Abilities](./resources-and-abilities.md) we'll specify when making the call to generation our Session Signatures. +We will be using this wallet to sign the Authorization Signature for our Session Keys, granting our Session Keys the ability to use the [Lit Resources and Abilities](./resources-and-abilities.md) we'll specify when making the call to generate our Session Signatures. ## Connecting to the Lit Network