Auth Modes
Consenti's admin dashboard and API support four authentication modes. Local password auth works out of the box for development. For production you'll want to configure a proper secret, and for enterprise deployments you can delegate auth to your existing identity provider via OIDC or SAML.
Mode overview
| Mode | Best for | Requires |
|---|---|---|
| local | Development, small teams | Email + password in config |
| jwt | API-first, programmatic access | A stable jwtSecret env var |
| oidc | Auth0, Keycloak, Google Workspace | OIDC provider config |
| saml | Okta, Azure AD, Ping | SAML IdP config + cert |
| custom | Any other identity system | A validateUser function |
Local (default)
Consenti stores a scrypt-hashed password in the database. The admin logs in at /consenti/admin/auth/login, receives a JWT, and uses it as a Bearer token for all subsequent admin API calls.
createConsenti({
auth: {
mode: 'local',
adminEmail: '[email protected]',
adminPassword: process.env.CONSENTI_ADMIN_PASSWORD!,
// jwtSecret is auto-generated if omitted — sessions expire on restart
jwtSecret: process.env.CONSENTI_ADMIN_JWT_SECRET,
},
})jwtSecret (or the CONSENTI_ADMIN_JWT_SECRET env var) in production. Without it, Consenti generates a random secret on start — all admin sessions are invalidated on every restart, which is fine for dev but unacceptable in production.How to obtain and use a JWT
# 1. Log in
curl -X POST https://your-domain.com/consenti/admin/auth/login \
-H 'Content-Type: application/json' \
-d '{ "email": "[email protected]", "password": "your-password" }'
# → { "token": "eyJhbGci..." }
# 2. Use the token on admin routes
curl https://your-domain.com/consenti/admin/profiles \
-H 'Authorization: Bearer eyJhbGci...'OIDC (Auth0, Keycloak, Google)
OIDC mode redirects admin users to your identity provider for authentication. After a successful login, the IdP sends a code that Consenti exchanges for user info. Consenti maps IdP claims to admin roles using claimsMapping.
createConsenti({
auth: {
mode: 'oidc',
jwtSecret: process.env.CONSENTI_ADMIN_JWT_SECRET!,
oidc: {
issuer: 'https://your-tenant.auth0.com',
clientId: process.env.AUTH0_CLIENT_ID!,
clientSecret: process.env.AUTH0_CLIENT_SECRET!,
redirectUri: 'https://your-domain.com/consenti/admin/auth/oidc/callback',
claimsMapping: {
email: 'email',
roles: 'consenti_roles', // custom claim in your Auth0 token
},
},
},
})SAML (Okta, Azure AD)
createConsenti({
auth: {
mode: 'saml',
jwtSecret: process.env.CONSENTI_ADMIN_JWT_SECRET!,
saml: {
issuer: 'https://idp.example.com',
entryPoint: 'https://idp.example.com/sso/saml',
cert: process.env.SAML_IDP_CERT!, // IdP signing cert (PEM, no headers)
callbackUrl: 'https://your-domain.com/consenti/admin/auth/saml/callback',
},
},
})Custom auth
If your identity system doesn't fit OIDC or SAML, pass a validateUser function. It receives the raw request and must return an AdminUser object or null:
createConsenti({
auth: {
mode: 'custom',
jwtSecret: process.env.CONSENTI_ADMIN_JWT_SECRET!,
validateUser: async (req) => {
const token = req.headers.get('Authorization')?.replace('Bearer ', '')
if (!token) return null
const user = await myAuthSystem.verifyToken(token)
return user ? { email: user.email, role: user.role } : null
},
},
})