Skip to content

Authentication

Trokky uses JWT-based authentication with role-based access control (RBAC) to secure your content API.

The authentication system provides:

  • JWT token-based authentication
  • Role-based access control
  • Secure password hashing
  • Session management
  • Multi-environment crypto support
const trokky = await TrokkyExpress.create({
security: {
adminUser: {
username: 'admin',
password: 'secure-password',
},
jwtSecret: process.env.JWT_SECRET || 'development-secret',
tokenExpiry: '7d',
},
// ...
});

For production, use environment variables:

.env
TROKKY_ADMIN_USERNAME=admin
TROKKY_ADMIN_PASSWORD=your-secure-password
TROKKY_JWT_SECRET=your-random-secret-key
const trokky = await TrokkyExpress.create({
security: {
adminUser: {
username: process.env.TROKKY_ADMIN_USERNAME,
password: process.env.TROKKY_ADMIN_PASSWORD,
},
jwtSecret: process.env.TROKKY_JWT_SECRET,
},
// ...
});

Trokky includes four built-in roles:

RoleDescriptionPermissions
adminFull system accessAll operations
editorContent managementCRUD on all content
writerLimited content managementCreate/update own content
viewerRead-only accessRead content only
ActionAdminEditorWriterViewer
Read documentsYesYesYesYes
Create documentsYesYesYesNo
Update any documentYesYesNoNo
Update own documentsYesYesYesNo
Delete documentsYesYesNoNo
Manage usersYesNoNoNo
Access settingsYesNoNoNo
Upload mediaYesYesYesNo
Delete mediaYesYesNoNo
import { TrokkyCore } from '@trokky/core';
// After initialization
const user = await trokky.core.users.create({
username: 'editor@example.com',
password: 'user-password',
role: 'editor',
name: 'John Editor',
});

By default, users are stored alongside content using the configured storage adapter:

content/
└── _users/
├── admin.json
└── editor@example.com.json
{
"_id": "user-abc123",
"username": "editor@example.com",
"passwordHash": "$2b$10$...",
"role": "editor",
"name": "John Editor",
"createdAt": "2024-01-15T10:00:00Z",
"lastLogin": "2024-01-20T14:30:00Z"
}
Terminal window
POST /api/auth/login
Content-Type: application/json
{
"username": "admin",
"password": "your-password"
}

Response:

{
"token": "eyJhbGciOiJIUzI1NiIs...",
"user": {
"id": "user-abc123",
"username": "admin",
"role": "admin",
"name": "Administrator"
},
"expiresAt": "2024-01-22T10:00:00Z"
}

Include the token in subsequent requests:

Terminal window
GET /api/documents/post
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Terminal window
POST /api/auth/refresh
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Terminal window
POST /api/auth/logout
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
const trokky = await TrokkyExpress.create({
security: {
// Admin user (created on first startup)
adminUser: {
username: 'admin',
password: 'secure-password',
email: 'admin@example.com',
},
// JWT settings
jwtSecret: process.env.JWT_SECRET,
tokenExpiry: '7d', // Token lifetime
refreshTokenExpiry: '30d', // Refresh token lifetime
// Password requirements
passwordPolicy: {
minLength: 8,
requireUppercase: true,
requireLowercase: true,
requireNumbers: true,
requireSpecial: false,
},
// Rate limiting
rateLimit: {
login: {
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // 5 attempts
},
},
// Session settings
session: {
maxConcurrent: 5, // Max sessions per user
revokeOnPasswordChange: true,
},
},
// ...
});

By default:

  • GET /api/documents/* - Public (read access)
  • POST/PUT/DELETE /api/documents/* - Protected (requires authentication)
  • GET /api/media/* - Public
  • POST /api/media/* - Protected
  • /api/auth/* - Public (login/logout)
  • /api/users/* - Admin only
// In your Express app
import { requireAuth, requireRole } from '@trokky/express';
// Require any authenticated user
app.get('/api/custom', requireAuth(), (req, res) => {
res.json({ user: req.user });
});
// Require specific role
app.post('/api/admin-only', requireRole('admin'), (req, res) => {
res.json({ message: 'Admin access granted' });
});
// Require one of multiple roles
app.put('/api/editors', requireRole(['admin', 'editor']), (req, res) => {
res.json({ message: 'Editor access granted' });
});

Integrate with OAuth providers:

const trokky = await TrokkyExpress.create({
security: {
// ... other options
oauth: {
providers: [
{
name: 'google',
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackUrl: '/api/auth/google/callback',
},
],
},
},
// ...
});
const trokky = await TrokkyExpress.create({
security: {
// Custom validation before user creation
validateUser: async (userData) => {
// Check against external system
const isAllowed = await checkExternalAuth(userData.email);
if (!isAllowed) {
throw new Error('User not authorized');
}
return true;
},
// Custom role assignment
assignRole: async (userData) => {
// Assign role based on email domain
if (userData.email.endsWith('@admin.example.com')) {
return 'admin';
}
return 'editor';
},
},
// ...
});

Generate a strong secret for production:

Terminal window
# Generate a secure random secret
openssl rand -base64 64

Trokky uses bcrypt for password hashing with configurable cost factor:

security: {
bcryptRounds: 12, // Higher = more secure but slower
}

Always use HTTPS in production:

// Force HTTPS redirect
app.use((req, res, next) => {
if (req.headers['x-forwarded-proto'] !== 'https') {
return res.redirect(`https://${req.headers.host}${req.url}`);
}
next();
});

For cookie-based sessions:

security: {
cookie: {
secure: true, // HTTPS only
httpOnly: true, // No JavaScript access
sameSite: 'strict', // CSRF protection
maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
},
}

Track authentication events:

const trokky = await TrokkyExpress.create({
security: {
auditLog: {
enabled: true,
events: ['login', 'logout', 'loginFailed', 'passwordChange', 'userCreate'],
},
},
// ...
});
// Access audit logs
const logs = await trokky.core.audit.getEvents({
type: 'loginFailed',
since: new Date(Date.now() - 24 * 60 * 60 * 1000), // Last 24 hours
});