Choose an authentication boundary
- Server-side SDK
- Browser or mobile SDK
Use API-key authentication only in a trusted server runtime:Store the key in a secret manager or a server-only environment variable. Never use a
NEXT_PUBLIC_*, VITE_*, or equivalent client-exposed variable for it.sdk-3.0.0-caucasus. Pin both to @rhinestone/sdk@3.0.0 when the release is available.
Secure sponsored intents
A valid client session must not authorize unlimited sponsorship. The extension-token callback runs during prepare/quote, not submission. The token binds the serialized approval input to the quote request; that cryptographic binding is not application authorization. The SDK’sshouldSponsor helper filters destination chain IDs, account addresses, and destination calls. It accepts the current contract and legacy inputs without a version identifier, and refuses unknown contract versions. It is not a complete runtime validator or funding, recipient, or budget policy. An EVM-only endpoint must explicitly reject legacy and other-VM requests.
Define the parsing boundary
Your application ownsparseApprovalBody(value: unknown): SerializedIntentInput. It must validate a body containing only intentInput, require contractVersion: 'sdk-3.0.0-caucasus', validate the complete per-VM account/source/destination/options union, and reject unknown fields at every level. Validate CAIP-2 chain IDs, addresses, hex calldata, decimal-string bigint amounts, and numeric bounds. Do not implement it as a type assertion or a catchall object schema. Preserve supplied spellings and optional fields: the JWT digest commits to the exact parsed approval input.
The following server example continues that schema and authenticated-session setup; it is not a standalone schema implementation. requireSession returns a server-verified wallet address and its previously authorized EVM approval-account configuration, not values from this request. reserveApprovalBudget atomically enforces per-user sponsorship/spend caps, rate limits, and replay policy before issuing a token. Enforce request-size limits and CSRF protection at the route boundary.
Apply a bounded EVM policy
This illustrative policy allows at most 10 USDC of selected Base funding, with either delivery of at most 1 USDC to the authenticated wallet or exactly one 1-USDC transfer call to that wallet. It allows only gas sponsorship; other virtual machines, source calls, auxiliary funds, custom fees, and routing options are denied. Explicitfalse sponsorship flags are allowed and remain in the input signed by the server. Configure a project-side sponsorship cap as well: a gas limit is not a monetary sponsorship budget.
maxAmount caps observed source funds; it is not a guaranteed exact-input spend. Auxiliary funds are added after that cap, so this policy refuses them. Broader policies must explicitly authorize source executions and every enabled option; do not add an allow-all fallback. See sponsorship setup and sponsorship policies and security.
Apply a bounded Solana delivery policy
Reuse the authentication, strict runtime schema, JWT signer, and atomic budget reservation above. The following server callback is a separate Solana-only endpoint:requireSession also returns solanaWalletAddress, approvedSolanaAccount, and approvedSolanaRecipient from previously verified server-side enrollment. The approved account contains the exact Swig wallet, state account (when present), and authorization role/key. The recipient is a separately authorized wallet, not the source wallet; never copy either identity from this request. Base58 identities, mint addresses, and recipients are case-sensitive. Do not lowercase them.
This illustrative policy allows same-chain devnet USDC delivery of at most 1 USDC to that authorized recipient, with a source cap of 10 USDC and gas sponsorship only. Network availability depends on your environment; neither the SDK descriptor nor this policy proves route availability. Keep the EVM policy on its own endpoint, or dispatch explicitly between these two bounded policies with no fallback.
getIntentExtensionToken(intentInput) callback to this authenticated endpoint. This is application authorization over the complete validated input, not a new createJwtSigner configuration callback. Its shouldSponsor option accepts only chain, account, and calls filters; the calls filter receives no Solana instructions and cannot authorize their programs, accounts, or recipients.
Reject all other envelopes: cross-chain routes, instructions, authority changes, deployment initialization, EVM account entries, alternate mints or recipients, and extra options. Deployment and authority management are gas-sponsored operations with takeover risk; they require a separately authenticated enrollment/management policy, not this delivery callback. maxAmount is a source-balance cap, not an exact-spend guarantee. Enforce monetary sponsorship caps, rate limits, and replay controls before signing.
Protect each credential
- Rhinestone API keys: create separate production and test keys in the Dashboard, grant only required scopes, rotate them, and revoke suspected leaks.
- JWT signing keys: register only the public key in the Dashboard. Keep the private JWK server-side, use distinct key IDs for rotation, and never return it from an API route.
- Wallet provider secrets: only publish values the provider labels publishable. Turnkey API private keys, Magic secret keys, and OIDC private keys belong on the server.
- Wallet keys: use provider policy controls or a secret manager. Do not log private keys, recovery material, signatures awaiting submission, or raw authentication tokens.
- RPC, bundler, and paymaster keys: server-side is safest. If a provider permits browser credentials, restrict them by origin, chain, method, and budget.
Validate signing requests
Display or independently validate the chain, recipient, token, amount, and call data before asking a user to sign. Inspect each ordered signing request’s account, authority, purpose, scope, validity, and payload; do not assume all requests are EIP-712. Treat provider callbacks and connected-wallet changes as untrusted state: confirm the active address before creating the account and clear cached account objects when the signer changes. For server wallets, authorize every signing request against the application session. Do not expose an endpoint that signs arbitrary hashes or typed data for any authenticated caller. For Solana, verify the saved Swig identity, active authority key and role, cluster, and instruction program/account/data before approval.all and manageAuthority can both install an all key and take over; the root cannot be removed. Do not interpret successful deployment or a single getAuthorityStatus check as global readiness.
For EIP-7702, verify the delegation target and chain scope before signing an authorization. The EOA remains a root authority after delegation; module-level controls do not make a compromised EOA safe.
Operational controls
- Separate production, staging, and development projects and credentials.
- Apply request-size limits, rate limits, abuse detection, and structured audit logs without sensitive payloads.
- Alert on sponsorship spikes, repeated authorization failures, and unexpected destination contracts.
- Rotate a credential immediately after suspected exposure and invalidate active sessions where supported.
- Test recovery and key-rotation procedures before an incident.