Implement SaaSKit
Add login, callback, session cookies, and logout. Then stop.
Guardrails
- MUST validate tokens server-side. MUST NOT trust raw JWT claims. MUST NOT put tokens in localStorage.
- MUST keep
redirectUriidentical to the dashboard Allowed callback URL. - MUST NOT write refresh middleware, remote revoke, or a session list. Name
manage-saaskit-sessionsinstead.
Gotchas
setup-saaskitalready wrote env and registered the redirect. Start there.- Read
SCALEKIT_ENVIRONMENT_URL,SCALEKIT_CLIENT_ID,SCALEKIT_CLIENT_SECRET, andSCALEKIT_REDIRECT_URI. NeverSCALEKIT_ENV_URL. - Default language is Node.
setup-saaskitalready printed a Node login URL. - Next.js App Router → name
implement-saaskit-nextjsand stop. - Django, FastAPI, or Flask → name
implement-saaskit-pythonand stop. - Go, Java, or Laravel → stay on this Node path. Open references/go.md, references/java.md, or references/laravel.md only when the repo is that stack.
- Mount
cookieParser()before the auth routes. Logout readsreq.cookies.idToken. - Cookies:
HttpOnly,Securein production,sameSite: 'lax'.strictbreaks the OAuth callback. - Path-scope access to
/apiand refresh to/auth/refreshif you set both. /dashboarddoes not receive the access cookie. Protect/api/*only. The page calls/api.getLogoutUrltakes one object:{ idTokenHint, postLogoutRedirectUri }. The URL is one-time.- Register that same post-logout URL in the dashboard: Authentication → Redirect URLs → Post logout URLs.
Step 1 — Pick the path
- Next.js App Router → name
implement-saaskit-nextjs. Stop. - Django, FastAPI, or Flask → name
implement-saaskit-python. Stop. - Anything else → stay here. Default snippets are Node.
If env is missing, collect the four values from app.scalekit.com → Developers → Settings → API Credentials. Register SCALEKIT_REDIRECT_URI under Authentication → Redirect URLs → Allowed callback URLs. Do not invent values.
Done when: this skill is the right path, and the four env names exist.
Step 2 — Init the SDK
Install @scalekit-sdk/node only when the repo has no Scalekit SDK yet. Install cookie-parser if Express has no cookie parser yet.
import { ScalekitClient } from '@scalekit-sdk/node';
import cookieParser from 'cookie-parser';
const scalekit = new ScalekitClient(
process.env.SCALEKIT_ENVIRONMENT_URL,
process.env.SCALEKIT_CLIENT_ID,
process.env.SCALEKIT_CLIENT_SECRET
);
const redirectUri = process.env.SCALEKIT_REDIRECT_URI;
app.use(cookieParser());
Done when: the client initializes from those env vars.
Step 3 — Login route
app.get('/auth/login', (req, res) => {
const authorizationUrl = scalekit.getAuthorizationUrl(redirectUri, {
scopes: ['openid', 'profile', 'email', 'offline_access']
});
res.redirect(authorizationUrl);
});
Done when: /auth/login redirects to that URL.
Step 4 — Callback and session cookies
Use the same redirectUri as Step 3. Then redirect off /auth/callback.
app.get('/auth/callback', async (req, res) => {
const { code } = req.query;
const { idToken, accessToken, refreshToken, expiresIn } =
await scalekit.authenticateWithCode(code, redirectUri);
res.cookie('accessToken', accessToken, {
maxAge: (expiresIn - 60) * 1000,
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
path: '/api',
});
res.cookie('refreshToken', refreshToken, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
path: '/auth/refresh',
});
res.cookie('idToken', idToken, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
path: '/',
});
res.redirect('/dashboard');
});
| Token | Purpose |
|---|---|
idToken |
User profile. Keep it for logout. |
accessToken |
Short-lived. Roles and permissions. |
refreshToken |
Long-lived. Used later to renew access. |
Do not validate or refresh here. That is manage-saaskit-sessions.
Done when: the callback exchanges code, sets the three cookies, and the browser leaves /auth/callback.
Step 5 — Logout
Clear the cookies from Step 4, then redirect to Scalekit. The logout URL is one-time.
app.get('/auth/logout', (req, res) => {
const idTokenHint = req.cookies.idToken;
res.clearCookie('accessToken', { path: '/api' });
res.clearCookie('refreshToken', { path: '/auth/refresh' });
res.clearCookie('idToken', { path: '/' });
const postLogoutRedirectUri = `${req.protocol}://${req.get('host')}`;
const logoutUrl = scalekit.getLogoutUrl({
idTokenHint,
postLogoutRedirectUri,
});
res.redirect(logoutUrl);
});
Register that same origin as a Post logout URL. Local default is http://localhost:3000.
Done when: cookies are gone and the browser hits the logout URL.
Step 6 — Name the next skill and stop
Name manage-saaskit-sessions for store, validate, refresh, and revoke.
Done when: manage-saaskit-sessions is named, and this skill has stopped.
Reach for
setup-saaskitif env or the redirect URI is missingmanage-saaskit-sessionsto store, validate, refresh, or revokeimplement-saaskit-nextjsfor Next.js App Routerimplement-saaskit-pythonfor Django, FastAPI, or Flask- references/go.md for Go
- references/java.md for Spring Boot
- references/laravel.md for Laravel
Live lookups
- Docs index: https://docs.scalekit.com/llms.txt
- Auth flow: https://docs.scalekit.com/authenticate/fsa/quickstart/
- Sessions: https://docs.scalekit.com/authenticate/fsa/sessions/
- MCP: https://mcp.scalekit.com