SuperTokens Cheat Sheet
Overview
SuperTokens is an open-source authentication solution that provides pre-built auth recipes for email/password, passwordless, social login, and multi-factor authentication. It can be self-hosted or used as a managed service, giving developers full control over their authentication infrastructure while reducing implementation complexity.
SuperTokens uses a unique architecture with a Core service (Java-based) that handles token management and session storage, and frontend/backend SDKs that integrate into your application. It supports React, Angular, Vue, Next.js, Node.js, Python, and Go, with automatic session management using rotating refresh tokens and anti-CSRF protection.
Installation
# Node.js backend SDK
npm install supertokens-node
# React frontend SDK
npm install supertokens-auth-react
# React Native
npm install supertokens-react-native
# Python backend SDK
pip install supertokens-python
# Go backend SDK
go get github.com/supertokens/supertokens-golang
# SuperTokens Core (Docker)
docker run -d \
--name supertokens \
-p 3567:3567 \
registry.supertokens.io/supertokens/supertokens-postgresql
Backend Setup (Node.js)
const supertokens = require("supertokens-node");
const Session = require("supertokens-node/recipe/session");
const EmailPassword = require("supertokens-node/recipe/emailpassword");
const ThirdParty = require("supertokens-node/recipe/thirdparty");
const Dashboard = require("supertokens-node/recipe/dashboard");
supertokens.init({
framework: "express",
supertokens: {
connectionURI: "https://try.supertokens.com",
// For self-hosted:
// connectionURI: "http://localhost:3567",
// apiKey: "your-api-key",
},
appInfo: {
appName: "My App",
apiDomain: "http://localhost:3001",
websiteDomain: "http://localhost:3000",
apiBasePath: "/auth",
websiteBasePath: "/auth",
},
recipeList: [
EmailPassword.init(),
ThirdParty.init({
signInAndUpFeature: {
providers: [
ThirdParty.Google({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
ThirdParty.Github({
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
}),
],
},
}),
Session.init(),
Dashboard.init(),
],
});
// Express middleware
const { middleware, errorHandler } = require("supertokens-node/framework/express");
app.use(middleware());
// ... routes
app.use(errorHandler());
Frontend Setup (React)
import SuperTokens from "supertokens-auth-react";
import EmailPassword from "supertokens-auth-react/recipe/emailpassword";
import ThirdParty from "supertokens-auth-react/recipe/thirdparty";
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
appName: "My App",
apiDomain: "http://localhost:3001",
websiteDomain: "http://localhost:3000",
apiBasePath: "/auth",
websiteBasePath: "/auth",
},
recipeList: [
EmailPassword.init(),
ThirdParty.init(),
Session.init(),
],
});
// Wrap your app
import { SuperTokensWrapper } from "supertokens-auth-react";
function App() {
return (
<SuperTokensWrapper>
<Routes />
</SuperTokensWrapper>
);
}
Route Protection
// Backend - protect API routes
const { verifySession } = require("supertokens-node/recipe/session/framework/express");
app.get("/api/user", verifySession(), async (req, res) => {
const userId = req.session.getUserId();
const accessTokenPayload = req.session.getAccessTokenPayload();
res.json({ userId, payload: accessTokenPayload });
});
// Require specific claims
const { UserRoleClaim } = require("supertokens-node/recipe/userroles");
app.get("/api/admin", verifySession({
overrideGlobalClaimValidators: async (globalValidators) => [
...globalValidators,
UserRoleClaim.validators.includes("admin"),
],
}), async (req, res) => {
res.json({ message: "Admin access granted" });
});
// Frontend - protected routes
import { SessionAuth } from "supertokens-auth-react/recipe/session";
function ProtectedPage() {
return (
<SessionAuth>
<Dashboard />
</SessionAuth>
);
}
Session Management
// Backend session operations
const Session = require("supertokens-node/recipe/session");
// Create session with custom payload
app.post("/login", async (req, res) => {
const session = await Session.createNewSession(req, res, "public", userId, {
role: "admin",
plan: "premium",
});
res.json({ status: "OK" });
});
// Update session claims
app.post("/upgrade", verifySession(), async (req, res) => {
await req.session.mergeIntoAccessTokenPayload({
plan: "enterprise",
});
res.json({ status: "OK" });
});
// Revoke session
app.post("/logout", verifySession(), async (req, res) => {
await req.session.revokeSession();
res.json({ status: "OK" });
});
// Revoke all sessions for a user
await Session.revokeAllSessionsForUser(userId);
// Frontend session access
import Session from "supertokens-auth-react/recipe/session";
import { useSessionContext } from "supertokens-auth-react/recipe/session";
function Profile() {
const session = useSessionContext();
if (session.loading) return <div>Loading...</div>;
if (!session.doesSessionExist) return <div>Not logged in</div>;
return (
<div>
<p>User ID: {session.userId}</p>
<p>Role: {session.accessTokenPayload.role}</p>
</div>
);
}
User Roles and Permissions
const UserRoles = require("supertokens-node/recipe/userroles");
// Add to recipe list
UserRoles.init();
// Create role
await UserRoles.createNewRoleOrAddPermissions("admin", [
"read:users", "write:users", "delete:users",
]);
// Assign role to user
await UserRoles.addRoleToUser("public", userId, "admin");
// Get user roles
const { roles } = await UserRoles.getRolesForUser("public", userId);
// Check permissions
const { permissions } = await UserRoles.getPermissionsForRole("admin");
Advanced Usage
Custom Email/Password Validation
EmailPassword.init({
signUpFeature: {
formFields: [
{
id: "email",
validate: async (value) => {
if (!value.endsWith("@company.com")) {
return "Only company emails allowed";
}
return undefined;
},
},
{
id: "password",
validate: async (value) => {
if (value.length < 12) return "Password must be at least 12 characters";
return undefined;
},
},
{
id: "name",
optional: false,
},
],
},
override: {
apis: (originalImplementation) => ({
...originalImplementation,
signUpPOST: async (input) => {
const response = await originalImplementation.signUpPOST(input);
if (response.status === "OK") {
// Post-signup actions (send welcome email, etc.)
await sendWelcomeEmail(response.user.email);
}
return response;
},
}),
},
});
Multi-Factor Authentication
const MultiFactorAuth = require("supertokens-node/recipe/multifactorauth");
const TOTP = require("supertokens-node/recipe/totp");
// Add to recipe list
MultiFactorAuth.init({
firstFactors: ["emailpassword", "thirdparty"],
});
TOTP.init();
Self-Hosted with PostgreSQL
docker run -d \
--name supertokens \
-p 3567:3567 \
-e POSTGRESQL_CONNECTION_URI="postgresql://user:pass@host:5432/supertokens" \
registry.supertokens.io/supertokens/supertokens-postgresql
Configuration
# Environment variables
SUPERTOKENS_CONNECTION_URI="http://localhost:3567"
SUPERTOKENS_API_KEY="your-api-key"
GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"
GITHUB_CLIENT_ID="your-github-client-id"
GITHUB_CLIENT_SECRET="your-github-client-secret"
Troubleshooting
| Issue | Solution |
|---|---|
| CORS errors | Ensure apiDomain and websiteDomain match; add CORS middleware before SuperTokens |
| Session not persisting | Check cookie domain; ensure frontend and backend share the same top-level domain |
| Core connection refused | Verify SuperTokens Core is running; check connectionURI |
| Social login redirect fails | Verify OAuth callback URLs match your apiDomain + apiBasePath |
| Token refresh failing | Ensure Session.init() interceptor is added to frontend HTTP client |
| Dashboard not loading | Add Dashboard.init() to recipe list; access at apiDomain/auth/dashboard |
| Role claims missing | Ensure UserRoles.init() is in recipe list and roles are assigned |
| Migration issues | Use the user migration APIs to import users from other providers |