Server

Verify clients, build a SecurityContext, and rate-limit your APIs.

pnpm add @securelink/server

Production config

import {
  createSecureLinkServer,
  RedisCredentialStore,
  RedisRateLimitStore,
  formatSetCookie,
} from "@securelink/server";
 
const securelink = createSecureLinkServer({
  authMode: "both",
  tokenHashSecret: process.env.SECURELINK_TOKEN_SECRET!, // required
  credentialDelivery: "cookie", // recommended for web
  attestation: {
    enabled: true,
    appAttestVerifier: myAppleVerifier,
    playIntegrityVerifier: myGoogleVerifier,
  },
  authorizationValidator: myJwtValidator, // required for customAuth
  credentials: new RedisCredentialStore(redis),
  rateLimit: {
    enabled: true,
    store: new RedisRateLimitStore(redis),
    user: { max: 100, windowMs: 60_000 },
    ip: { max: 200, windowMs: 60_000 },
    endpoint: { max: 30, windowMs: 60_000 },
  },
  // NEVER set allowInsecureDevMode in production
});

What production mode enforces

  • Hashed access/refresh tokens at rest
  • Rate limits on bootstrap, refresh, register, and API verify
  • Server-minted anonymous identities (client ids ignored)
  • Installation proofs verified with public key only (Ed25519)
  • PROOF_REQUIRED when attestation is on (except web with no proof)
  • Refresh-token reuse detection
  • Explicit authorizationValidator for customAuth

Wire routes:

app.post("/securelink/anonymous/bootstrap", async (req, res) => {
  const result = await securelink.bootstrapAnonymous(req);
  for (const c of result.setCookies ?? []) res.append("Set-Cookie", formatSetCookie(c));
  res.json(result);
});
 
app.post("/securelink/attestation/register", async (req, res) => {
  res.json(await securelink.registerInstallation(req));
});
 
app.get("/api/hello", async (req, res) => {
  const ctx = await securelink.verify({
    headers: req.headers,
    body: req.body,
    ip: req.ip,
    method: req.method,
    path: req.path,
  });
  res.json({ ok: true, identity: ctx.identity });
});