SETUP GUIDES · SIGN-IN

Sign-in with Claspine on the engine (Node.js, Python, Go)

Your backend hands the sign-in to the Claspine engine, gets a session back and checks it on every request.

⏱ About 20 minutes

With the Claspine engine, sign-in works the same as in Spring Boot, over HTTP. Your login page signs the person in with a sign-in provider; your backend sends the result to the engine with its service key and gets a session; your backend then keeps the session token in a cookie and asks the engine who it belongs to. Node.js has ready-made helpers in @grahmur-org/claspine-client; other languages call the same three endpoints.

Words you’ll see

Sign-in provider
The service that checks who a person is: Firebase Authentication (email and password, Google, Apple, phone), or Claspine’s own one-time codes sent by SMS, WhatsApp or email. Claspine trusts its answer and opens a session.
ID token
A short-lived signed message from the sign-in provider that says “this is user X”. Your app gets it after the person signs in and hands it to Claspine once, in exchange for a session.
Session
What keeps a person signed in. Claspine gives your app a session token after sign-in; every later request carries it. Claspine checks it, ends it at sign-out, and can end every session of a person at once.

Before you start

  • The engine running (see Run the Claspine engine) and a service key for your backend.
  • For email/password or Google: a Firebase project with those methods switched on. For codes: your own SMS/WhatsApp or email provider.

Steps

  1. Give the engine your Firebase project: SPINE_FIREBASE_PROJECT_ID=my-firebase-project. For codes add SPINE_PHONE_CODE_SIGN_IN=true and/or SPINE_EMAIL_CODE_SIGN_IN=true. Restart the engine.
  2. Your login page signs the person in with the Firebase SDK and sends the ID token to your backend (for example POST /login). The browser never talks to the engine.
  3. Your backend exchanges it: spine.auth.exchangeCredential({ provider: 'firebase-auth', credential: idToken }), or POST /api/v1/auth/sessions with the headers X-Spine-Api-Key and X-Spine-Host. Store the returned sessionToken in an httpOnly cookie named grahmur_session.
  4. Protect your routes: in Express add createClaspineMiddleware({ client: spine, publicPaths: ['/login'] }); every request then has req.spine.account, or answers 401. Other languages call GET /api/v1/auth/me with Authorization: Bearer <session token> and treat 401 as signed out.
  5. Sign out: DELETE /api/v1/auth/sessions/current with the session token, then clear the cookie.
  6. Codes instead of passwords: your backend calls spine.auth.requestCode({ provider: 'phone-code', destination: '+4912345678' }), the person types the code, then exchangeCredential({ provider: 'phone-code', credential: `${challengeId}:${code}` }).
Express: sign-in route and protected routes with the Node SDK.
import express from 'express';
import cookieParser from 'cookie-parser';
import { ClaspineClient, createClaspineMiddleware } from '@grahmur-org/claspine-client';

const spine = new ClaspineClient({
  baseUrl: process.env.SPINE_API_URL,   // the engine, on your private network
  apiKey: process.env.SPINE_API_KEY,    // service key: stays on the server
  tenantHost: 'app.example.com',        // one of SPINE_HOSTS
});

const app = express().use(express.json()).use(cookieParser());

app.post('/login', async (req, res) => {
  const session = await spine.auth.exchangeCredential({ provider: 'firebase-auth', credential: req.body.idToken });
  res.cookie('grahmur_session', session.sessionToken, { httpOnly: true, secure: true, sameSite: 'lax' });
  res.sendStatus(204);
});

app.use(createClaspineMiddleware({ client: spine, publicPaths: ['/login', '/health'] }));
app.get('/api/me', (req, res) => res.json(req.spine!.account));

What goes where in Claspine

Console fieldValue
SPINE_FIREBASE_PROJECT_IDFirebase console → Project settings → General → Project ID.
Session cookiegrahmur_session, httpOnly, secure, sameSite lax: the SDK middleware reads it (or an Authorization: Bearer header from mobile apps).

Keep it safe

  • The service key never leaves your backend; browsers and mobile apps only ever hold their own session token.
  • Keep the engine on a private network. Your backend is the only thing that calls it.
  • Set SPINE_ENVIRONMENT to PRODUCTION for real users: sandbox sign-in is then refused.

Claspine stores the values encrypted, never shows them again in full, and never sends them to your app or SDK.

If something goes wrong

exchangeCredential answers 404 HOST_NOT_AVAILABLE.
Set tenantHost (X-Spine-Host) to one of SPINE_HOSTS.
exchangeCredential answers 401.
The ID token is from another Firebase project or expired; check SPINE_FIREBASE_PROJECT_ID and get a fresh token.
Every route answers 401 UNAUTHENTICATED.
The cookie is not reaching your backend: add cookie-parser, and send fetch requests with credentials: 'include'.

← All setup guides