Para’s Server SDK enables you to import and manage client-side sessions within your server environment. This allows your server to perform authenticated blockchain operations on behalf of users without requiring them to re-authenticate. The server can also validate existing client sessions using either the Para client or dedicated verification endpoints.
Importing Client Sessions
To use a client session on your server, you need to:
- Export the session from the client-side Para instance
- Transfer the session to your server securely
- Import the session into your server-side Para instance
Client-Side Session Export
First, have your client-side application export the active session:
// Client-side
const para = new Para(Environment.BETA, "YOUR_API_KEY");
// Export the current session
const serializedSession = await para.exportSession();
// Send this to your server endpoint
await fetch("/api/import-session", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ session: serializedSession }),
});
If signing on the server isn’t required, you can pass { excludeSigners: true }
as an argument to exportSession
to remove the signer data from the exported wallets, enhancing security:const serializedSession = await para.exportSession({ excludeSigners: true });
Server-Side Session Import
On your server, import the session into a Para Server SDK instance:
import { Para as ParaServer, Environment } from "@getpara/server-sdk";
// Initialize the Para Server SDK
const paraServer = new ParaServer(Environment.BETA, "YOUR_API_KEY");
app.post("/api/import-session", async (req, res) => {
try {
// Import the session from the client
await paraServer.importSession(req.body.session);
// Now you can use the paraServer instance for authenticated operations
// ...
res.status(200).json({ success: true });
} catch (error) {
res.status(500).json({ error: "Failed to import session" });
}
});
Create a new Para client instance for each request when handling multiple users. This prevents session conflicts between different users’ requests and ensures security isolation.
Session Validation
You can validate sessions on the server side to ensure they’re still active before performing operations.
Using the Para Client
import { Para as ParaServer, Environment } from "@getpara/server-sdk";
const paraServer = new ParaServer(Environment.BETA, "YOUR_API_KEY");
app.post("/api/authenticated-action", async (req, res) => {
try {
// Import the session
await paraServer.importSession(req.body.session);
// Check if the session is still active
const isActive = await paraServer.isSessionActive();
if (!isActive) {
return res.status(401).json({ error: "Session expired" });
}
// Proceed with authenticated operations
// ...
res.status(200).json({ success: true });
} catch (error) {
res.status(500).json({ error: "Operation failed" });
}
});
Using Verification Tokens
For non-Node.js servers or scenarios where you only need to validate a session without importing it, Para provides dedicated verification endpoints:
// Client-side: Get a verification token
const verificationToken = await para.getVerificationToken();
// Send to your server
await fetch("/api/verify-session", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ verificationToken }),
});
On your server, verify the token against Para’s API.
Use your Secret API Key from the Developer Portal to authenticate requests to the verification endpoints. This key is different from the public-facing API Key used in the Para client.
// Server-side verification
app.post("/api/verify-session", async (req, res) => {
const { verificationToken } = req.body;
if (!verificationToken) {
return res.status(400).json({ error: "Missing verification token" });
}
// Set the correct URL based on your environment
const verifyUrl = "https://api.beta.getpara.com/sessions/verify";
try {
const response = await fetch(verifyUrl, {
method: "POST",
headers: {
"content-type": "application/json",
"x-external-api-key": "YOUR_SECRET_API_KEY"
},
body: JSON.stringify({ verificationToken }),
});
if (response.status === 403) {
return res.status(403).json({ error: "Session expired" });
}
const userData = await response.json();
// userData contains { authType, identifier }
// Proceed with authenticated operations
res.status(200).json({ userData });
} catch (error) {
res.status(500).json({ error: "Verification failed" });
}
});
The verification endpoints are environment-specific:
Environment | Verification URL |
---|
SANDBOX | https://api.sandbox.getpara.com/sessions/verify |
BETA | https://api.beta.getpara.com/sessions/verify |
PROD | https://api.getpara.com/sessions/verify |
The verification response will contain the authentication type, identifier, and optionally the OAuth method used:
{
authType: "email" | "phone" | "farcaster" | "telegram" | "externalWallet";
identifier: string;
oAuthMethod?: "google" | "x" | "discord" | "facebook" | "apple";
}
Session Management
Maintaining Session Validity
To extend the validity of an imported session, you can use the keepSessionAlive
method:
try {
const success = await paraServer.keepSessionAlive();
if (!success) {
// Session couldn't be extended
// The client may need to re-authenticate
}
} catch (error) {
console.error("Failed to maintain session:", error);
}
You can configure session duration (up to 30 days) in the Para Developer Portal. This affects how long sessions remain valid without explicit extension.
Best Practices
-
Create new Para instances per request: Initialize a fresh Para Server SDK instance for each request to prevent session conflicts between users.
-
Secure session transport: Always use HTTPS and consider additional encryption when transferring sessions between client and server.
-
Exclude signers when possible: Use
{ excludeSigners: true }
when exporting sessions if server-side signing isn’t needed.
-
Validate before operations: Always check if a session is active before performing blockchain operations.
-
Handle expiration gracefully: Implement proper error handling for expired sessions, guiding users to re-authenticate when necessary.
-
Consider session verification tokens: For simple authentication checks without full session import, use verification tokens.
-
Set appropriate session duration: Configure session length in the developer portal based on your security requirements.
Verifying Wallet Ownership
To verify that a wallet address matches one of your users’ embedded wallets, you can send a request to one of the following endpoints:
Environment | URL |
---|
SANDBOX | https://api.sandbox.getpara.com/wallets/verify |
BETA | https://api.beta.getpara.com/wallets/verify |
PROD | https://api.getpara.com/wallets/verify |
Use your Secret API Key from the Developer Portal to authenticate requests to this endpoint. This key is different from the public-facing API Key used in the Para client.
Pass the address for the wallet in the POST request body:
// Server-side verification
app.post("/api/verify-wallet", async (req, res) => {
const { address } = req.body;
if (!address) {
return res.status(400).json({ error: "Missing address" });
}
// Set the correct URL based on your environment
const verifyUrl = "https://api.beta.getpara.com/wallets/verify";
try {
const response = await fetch(verifyUrl, {
method: "POST",
headers: {
"content-type": "application/json",
"x-external-api-key": "YOUR_SECRET_API_KEY"
},
body: JSON.stringify({ address }),
});
// No matching wallet found
if (response.status === 404) {
return res.status(404).json({ error: `Wallet not found with address: ${address}` });
}
const { walletId } = await response.json();
// Return the matched wallet ID:
res.status(200).json({ walletId });
} catch (error) {
res.status(500).json({ error: "Verification failed" });
}
});
Learn More
For more information about client-side session management and authentication, refer to our web documentation:
Examples
To learn more about using sessions on the server, check out this example. Each example route will have both pregen and session based routes for you to test with.