> ## Documentation Index
> Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Storage & Security

> What your application must persist for agent wallets, and the security model: key custody, signature encoding, and refresh limits.

The SDK is stateless: it persists nothing between calls. You own storage for every artifact in the agent wallet flow. This page lists what to store, where, and what happens if you lose it — and the security guarantees and obligations of the flow.

## What you must persist

For storage mechanics (KMS envelope encryption, schemas, checklists), see [Storage Best Practices](/node/wallets/server-wallets/storage-best-practices).

| Artifact                                                         | Storage class                                                                                                                           | Lifetime                                            | If you lose it                                                                                                                                                                                                                                   |
| ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Session private key (`privateKeyJwk` or KMS/HSM key)             | Secrets vault, KMS, or HSM — or keep the key non-extractable in KMS and never materialize a JWK. Never a plain file or database column. | Life of the agent session                           | Signed-session proofs can no longer be produced; backup and recovery calls fail. Generate a new key pair and sign the user in again to bind it.                                                                                                  |
| User JWT                                                         | Encrypted at rest in your app store, or memory only                                                                                     | Until refreshed or expired, bounded by `refreshExp` | The user signs in again. Update the stored value on **every** `refreshAuthToken()` call — the old token is superseded.                                                                                                                           |
| Backup password                                                  | Secrets vault. It is the PBKDF2 password for the key-share backup — never log it.                                                       | Life of the wallet                                  | Dynamic-stored backups encrypted with it are permanently undecryptable.                                                                                                                                                                          |
| `walletMetadata` (including `externalServerKeySharesBackupInfo`) | Durable app store (Redis, Postgres). Non-sensitive.                                                                                     | Life of the wallet                                  | `fetchWalletMetadata` recovers identity fields only — it does **not** return `externalServerKeySharesBackupInfo`, and no SDK endpoint does. Operations that need backup state (sign with auto-recovery, refresh, reshare, password checks) fail. |
| `externalServerKeyShares`                                        | Secrets vault or HSM. Sensitive.                                                                                                        | Life of the wallet                                  | Recoverable from Dynamic only if backed up with `backUpToDynamic: true`; otherwise signing is permanently impossible.                                                                                                                            |
| Agent signing token (autonomous mode only)                       | Secrets vault, KMS, or HSM                                                                                                              | Life of the agent's Dynamic user identity           | The Dynamic user is keyed to this key's public address. Once the current JWT can no longer be refreshed, the agent cannot sign in as that user again, and the user's wallets are unreachable through this flow.                                  |
| OTP codes, session nonces, decrypted key shares                  | Memory only — never persist                                                                                                             | Single use                                          | Nothing: request a new code or nonce.                                                                                                                                                                                                            |

<Warning>
  Mutating operations (`refreshWalletAccountShares`, `reshare`, `updatePassword`) return new `backupInfo`. Merge it into your stored `walletMetadata.externalServerKeySharesBackupInfo` immediately — subsequent operations read stale metadata and fail otherwise.
</Warning>

## Security

* The session private key never enters the SDK. You supply signatures through `getSessionSignature`; custody stays with you (file-backed JWK, KMS, HSM, or enclave).
* A leaked JWT alone does not authorize backup or recovery operations for a session-bound wallet. The keyshares relay requires the signed-session proof, which requires the session private key.
* `getSessionSignature` must return lowercase hex (raw ECDSA P-256 `r‖s`, 64 bytes). Base64 corrupts the proof.
* Do not log JWTs, OTP codes, backup passwords, or key material. The auth client surfaces error codes and messages only; your application must do the same.
* Refresh is bounded. The JWT `refreshExp` claim is a hard server-side limit; when it is reached, refresh fails with a 401 and only a new sign-in restores access. Design your agent to detect this and re-run the sign-in flow — for a human user this requires their re-approval; with an agent signing token it is programmatic.
* In autonomous mode, the agent signing token **is** the user identity. Anyone holding that key can sign in as that user and, with a new session key, operate its wallets. Custody it like the session private key: vault, KMS, or HSM — never source code or logs.

## Related pages

* [Agent Wallets overview](/node/agents/overview)
* [Use Agent Wallets](/node/agents/use-agent-wallets)
* [Storage Best Practices](/node/wallets/server-wallets/storage-best-practices)
