End-User Authentication
FLXBL provides complete authentication infrastructure for your application's end-users. By marking any entity as an Identity Entity, you enable registration, login, password reset, and JWT-based authentication — without writing auth code.
Important Distinction: This page covers authentication for your application's end-users (customers, members, etc.), not for FLXBL tenant users. For API keys and team management, see API Keys and User Management.
What is an Identity Entity?
An Identity Entity is any entity in your schema that you designate to represent your application's users. It's a regular entity with superpowers.
When you mark an entity as isIdentity: true:
- It remains a normal entity — Full CRUD via Dynamic API
- It gains auth endpoints — Register, login, reset password
- PASSWORD fields are special — Auto-hashed on write, auto-redacted on read
This dual nature gives you flexibility: use Identity endpoints for user-facing auth flows, and use Dynamic API for admin operations on user records.
The Dual-Access Pattern
Identity entities are unique in FLXBL: they're accessible through two different APIs:
| Access Method | Use Case | Authentication |
|---|---|---|
Identity API/api/v1/identity/:tenantId | End-user self-service: register, login, reset password | None (public) or end-user JWT |
Dynamic API/api/v1/dynamic/Customer | Admin operations: list users, bulk updates, reports | API key or tenant JWT |
This dual access means your admin dashboard can manage users via Dynamic API while your end-users register and log in via Identity API — all from the same entity.
Creating an Identity Entity
To enable end-user authentication, create an entity with a PASSWORD field
and mark it as your identity provider:
// Your schema with an identity entity
{
"entities": [
{
"name": "Customer",
"isIdentity": true, // Enables auth endpoints
"identifierField": "email", // Field used for login
"fields": [
{ "name": "email", "type": "STRING", "required": true },
{ "name": "password", "type": "PASSWORD", "required": true },
{ "name": "name", "type": "STRING", "required": false },
{ "name": "role", "type": "STRING", "required": false },
{ "name": "isActive", "type": "BOOLEAN", "required": false }
]
},
{
"name": "Product",
// Regular entity - no identity features
"fields": [
{ "name": "name", "type": "STRING", "required": true },
{ "name": "price", "type": "FLOAT", "required": true }
]
}
]
}Requirements
| Requirement | Description |
|---|---|
isIdentity: true | Marks this entity as the identity provider for your tenant |
identifierField | The field used for login (typically email). Must be type STRING. |
PASSWORD field | At least one field with type PASSWORD. Automatically hashed with bcrypt. |
Using Identity Endpoints
Once your schema has an identity entity, these endpoints become available:
Registration
# Your app's users register themselves
POST /api/v1/identity/{tenantId}/register
Content-Type: application/json
{
"email": "user@example.com",
"password": "SecurePassword123",
"name": "Jane Customer"
}
# Response
{
"id": "node_abc123",
"message": "Registration successful. Please check your email to verify your account."
}Login
# Your app's users log in
POST /api/v1/identity/{tenantId}/login
Content-Type: application/json
{
"identifier": "user@example.com",
"password": "SecurePassword123"
}
# Response
{
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "rf_abc123def456...",
"expiresIn": 900,
"user": {
"id": "node_abc123",
"email": "user@example.com",
"name": "Jane Customer",
"role": "member"
// Note: password field is automatically redacted
}
}Get Profile
# Authenticated user fetches their own profile
GET /api/v1/identity/{tenantId}/me
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
# Response
{
"id": "node_abc123",
"email": "user@example.com",
"name": "Jane Customer",
"role": "member",
"_isVerified": true
}Using Dynamic API for Admin Operations
Your backend can also manage identity entity records directly via the Dynamic API. This is useful for admin dashboards, bulk operations, and reporting:
# Your backend lists all users (with API key)
GET /api/v1/dynamic/Customer
Authorization: Bearer flxbl_your_api_key
# Response - password fields are always redacted
{
"data": [
{
"id": "node_abc123",
"email": "user@example.com",
"name": "Jane Customer",
"role": "member",
"isActive": true
}
]
}
# Your backend creates a user directly (bypassing registration)
POST /api/v1/dynamic/Customer
Authorization: Bearer flxbl_your_api_key
Content-Type: application/json
{
"email": "admin@example.com",
"password": "AdminPassword123",
"role": "admin",
"isActive": true
}Note: PASSWORD fields are automatically redacted in all API responses, whether accessed via Identity API or Dynamic API. They're also automatically hashed when written through either API.
What FLXBL Provides vs What You Build
FLXBL handles authentication (verifying identity), but for end-users, you implement authorization (what they can do):
| Feature | FLXBL Provides | You Implement |
|---|---|---|
| Password hashing | Automatic bcrypt | — |
| Token generation | Access + refresh JWTs | Token storage in your app |
| Email verification | Emails + token validation | Custom email templates (optional) |
| Password reset | Full flow with tokens | Custom UI for reset form |
| User roles | Storage on entity | Authorization logic |
| Permission checks | For your API keys only | For your end-users |
| Route protection | — | Middleware in your app |
Implementing End-User Authorization
Add a role field (or similar) to your identity entity, then enforce
permissions in your application code:
// Example: Checking roles in your server middleware
const user = await fetchUserFromFLXBL(accessToken);
// Define your role hierarchy
const ROLE_LEVELS = { viewer: 1, editor: 2, admin: 3 };
// Check permissions
function hasMinimumRole(userRole, requiredRole) {
return ROLE_LEVELS[userRole] >= ROLE_LEVELS[requiredRole];
}
// Protect routes
if (!hasMinimumRole(user.role, 'editor')) {
throw new Error('Forbidden: Insufficient permissions');
}Learn more about authorization patterns in Integration Patterns.
Identity API Endpoints Reference
| Endpoint | Method | Auth | Description |
|---|---|---|---|
/api/v1/identity/:tenantId/register | POST | None | Register a new end user |
/api/v1/identity/:tenantId/login | POST | None | Authenticate and get tokens |
/api/v1/identity/:tenantId/verify | POST | None | Verify email with token |
/api/v1/identity/:tenantId/forgot-password | POST | None | Request password reset email |
/api/v1/identity/:tenantId/reset-password | POST | None | Reset password with token |
/api/v1/identity/:tenantId/refresh | POST | None | Refresh access token |
/api/v1/identity/:tenantId/logout | POST | None | Revoke refresh token |
/api/v1/identity/:tenantId/me | GET | End-User JWT | Get authenticated user's profile |
Configuration Options
Customize token lifetimes, password requirements, and email verification settings:
| Option | Default | Description |
|---|---|---|
accessTokenExpiryMinutes | 15 | How long access tokens are valid |
refreshTokenExpiryDays | 7 | How long refresh tokens are valid |
minPasswordLength | 8 | Minimum password length requirement |
requireEmailVerification | true | Whether users must verify email before login |
Configure these settings via the MCP tool
(configure_identity) or the REST API.
Next Steps
- Integration Patterns — BFF, mobile, and serverless patterns
- Schema Design — Learn about field types including PASSWORD
- API Keys — Create keys for your backend operations
- Architecture Guide — Understand the two-plane model