@persona/sdk-node
v0.1.0
Published
The official Node.js server library for Persona integration
Downloads
266
Readme
Persona Node.js Server SDK
The official Node.js server library for Persona integration.
How it works
This package integrates with Persona's Privacy Pass token issuance and redemption flow using blind RSA signatures (RFC 9474 / RFC 9578). It handles both the Persona Relay lifecycle (session creation, claim redemption) and the full blind RSA issuance flow internally — blinding, submitting to Persona for signing, and unblinding — so your app never needs to implement the cryptography itself.
Your App This package Persona
| | |
|-- persona.relays.create() -----------> |------ POST /api/privacy/v1/relays --> |
|<- relayToken, relaySecret, ... |<----- relay session ----------------- |
| | |
|-- persona.relays.issuePrivacyPass() -> |--------- generate-claim ------------> |
| |<----- 401 challenge ----------------- |
| |---------- privacy-passes -----------> |
| |<-------- blind signature ------------ |
|<------- privacyPassToken ------------- | |
| | |
|-- persona.relays.generateClaim() ----> |----- generate-claim ----------------> |
|<---------- claimPayload -------------- |<---- claim-payload ------------------ |persona.relays.create— creates a relay session with Persona. ReturnsrelayToken,relaySecret, andrelaySessionAccessTokenyour app stores for subsequent calls.persona.relays.issuePrivacyPass— runs the full blind RSA issuance flow: fetches a challenge from Persona, blinds a token, submits it for signing, and unblinds the result. ReturnsprivacyPassTokenyour app holds onto.persona.relays.generateClaim— redeems theprivacyPassTokenagainst Persona and returns the claim payload.
Cryptography
Uses @cloudflare/blindrsa-ts, Cloudflare's implementation of RFC 9474 — RSA Blind Signatures. Suite: RSABSSA-SHA384-PSS-Randomized.
Token input is constructed per RFC 9578:
token_input = 0x0002 || SHA256(nonce) || SHA256(challenge_mac) || SHA256(key_id)Install
npm install @persona/sdk-node
# or
yarn add @persona/sdk-nodeQuick start
Construct a client with new Persona({ apiKey }):
import Persona from '@persona/sdk-node';
const persona = new Persona({ apiKey: process.env.PERSONA_API_KEY! });Relay flows are in the persona.relays namespace:
persona.relays.create(params)
Creates a Persona relay session. No authentication required.
CreateRelayParams
{
claimType: string;
encryptionKeyPem: string | null;
}encryptionKeyPem is optional. If provided, Persona will encrypt the claim payload on redemption. Must be a PEM-encoded RSA public key.
Returns CreateRelayResponse
{
relayToken: string;
relaySecret: string;
relaySessionAccessToken: string;
}Store all three values securely — they are required for subsequent calls.
persona.relays.issuePrivacyPass(params)
Runs the full blind RSA issuance flow and returns a Privacy Pass token.
IssuePrivacyPassParams
{
relayToken: string;
relaySecret: string;
}Returns IssuePrivacyPassResponse
{
privacyPassToken: string;
}persona.relays.generateClaim(params)
Redeems the Privacy Pass token against Persona and returns the claim.
GenerateClaimParams
{
privacyPassToken: string;
relayToken: string;
relaySecret: string;
}Returns GenerateClaimResponse
{
claimPayload: string; // json string or base64-encoded ciphertext
tokenConsumed: boolean;
}If you created the relay with an encryptionKeyPem, claimPayload will be an encrypted string. Decrypt it in your app using your corresponding private key (RSA-OAEP).
Errors
Persona API error responses and network failures throw subtypes of PersonaError:
{
"statusCode": "HTTP status code",
"title": "A short description of the error",
"details": "Optional longer description",
"code": "Optional machine-readable error code",
"meta": "Optional metadata"
}