Skip to main content
SocketFi provides strong security guarantees at the infrastructure level — passkey authentication, wallet authorization, policy enforcement, and replay protection. But the overall security posture of your application depends on how you integrate these capabilities. Mistakes in how you handle tokens, verify identity, communicate intent, or surface errors can undermine the security model even when the underlying platform is sound. This page covers the practices that matter most for building a secure SocketFi integration.

Authentication best practices

Always use authenticate() — never skip verification. If you’re accessing any user-specific data or gating any feature behind authentication, verify the session on your backend first. A client-side authenticated state is not a security control. Call verifyAuth() on your backend for every protected request. Don’t rely on a client-provided wallet address or session flag. The only way to confirm a user is genuinely authenticated is to verify the access token server-side.
Don’t log access tokens or session credentials. Access tokens grant impersonation ability. Log authentication events (sign-in, sign-out, failure) but never the token itself. Use HTTPS exclusively. Transmitting tokens over unencrypted connections exposes them to interception. Never make SocketFi API calls or forward tokens over plain HTTP, even in development environments. Treat credential rotation and recovery as high-privilege events. When a user rotates their passkey or initiates recovery, log the event, timestamp it, and notify the user through an out-of-band channel if possible. These are the highest-risk operations in the authentication lifecycle.

Backend security

Transaction security

Explain intent to users before they approve. The SocketFi approval screen surfaces what you give it. Your application should build UI context around every transaction — show the action in plain language, the assets involved, the destination, and the expected outcome — before the user even reaches the approval screen. Avoid:
Prefer:
Validate inputs before calling requestTransaction(). Confirm that addresses are valid, amounts are within expected ranges, and required arguments are present. Surface these errors in your UI before initiating the transaction workflow — don’t let malformed requests reach the approval screen. Handle rejections gracefully. A user who cancels the approval screen made an intentional, valid choice. Don’t show them an error. Reset the UI silently and let them try again at their own pace. Aggressive re-prompting erodes trust and trains users to approve without reading. Never auto-approve or chain approvals without visibility. Each transaction that modifies on-chain state must have a separate, explicit approval. Don’t construct flows that chain multiple approvals so quickly that users can’t review each one. Verify results before updating state. Only update balances, positions, or other application state after confirming result.success === true. Updating state optimistically before confirmation can create a false picture of reality if the transaction fails post-approval.

Wallet security

Treat the wallet address as the canonical user identity. The wallet address is stable across passkey rotations and device changes. Use the address returned by verifyAuth() — never trust a wallet address provided by the client without server-side verification. Don’t assume authorization will succeed. Policy violations, nonce conflicts, and fee failures can all cause wallet authorization to fail even after user approval. Build your application to handle these failures without creating dead ends. Monitor for unexpected authorization failures. A spike in TRANSACTION_REJECTED or POLICY_VIOLATION errors from a specific wallet may indicate an attack attempt, a misconfigured policy, or a bug in your transaction construction. Emit these failures to your monitoring system.

Recovery security

Recovery is the highest-risk operation in the SocketFi lifecycle. It replaces the passkey credential bound to a wallet — if misused, it could allow an attacker to take control of a user’s wallet. Treat it accordingly. Treat recovery initiation as a security event. Log every recovery request with timestamp, originating IP, and wallet address. Alert on unusual patterns (many recovery requests in a short window, requests from new geographies, etc.). Notify users out-of-band when recovery is initiated. If you have the user’s email or phone number, send a notification when a recovery request is started — not just when it completes. Unexpected notifications alert users to attempts they didn’t initiate. Test your recovery flow in staging before production. Recovery is rarely used but critical when needed. Broken recovery flows leave users locked out permanently. Maintain verified, tested recovery paths as part of your production readiness checklist. Review failed recovery attempts. Repeated failures may indicate fraud, brute-force attempts, or a misconfigured recovery setup. These deserve human review, not just automated logging.

Common security mistakes to avoid

Client-side code can be manipulated. A isAuthenticated: true flag in a React state store or localStorage proves nothing to your backend. Always call verifyAuth() for every protected server request.
Never use a wallet address supplied by the client as a trusted identity. An attacker could provide any wallet address. Always derive the wallet address from the verified access token via verifyAuth().
requestTransaction() resolves — not rejects — for many failure conditions. Checking result.success is mandatory. Updating state before this check can leave your UI in an inconsistent state.
Error codes like TRANSACTION_REJECTED or INVALID_SIGNATURE are useful for developers but confusing or alarming for users. Map error codes to friendly, actionable messages in your UI.
Sending a malformed contractId or invalid args type to requestTransaction() causes an error before any user interaction. Validate your inputs early, surface errors in the UI, and only call requestTransaction() when inputs are confirmed valid.
Credential rotations and recovery completions are security events. Users who don’t receive notifications can’t detect unauthorized access. Always surface these events, ideally through both in-app UI and an out-of-band channel.
localStorage is accessible to any JavaScript running on the page, making it a target for XSS attacks. Store session tokens in memory or use httpOnly cookies with appropriate security flags.

Production security checklist

Before deploying to production, verify the following:
Run through this checklist with a team member who wasn’t involved in implementation. Fresh eyes catch integration oversights — especially around token handling and error path coverage — that are easy to miss when you’ve been close to the code.