Authentication Guide
Tenrankai provides modern authentication with WebAuthn/Passkey support and fine-grained access control using a role-based permission system.
Authentication Overview
Tenrankai supports:
- Email-based Magic Links - Passwordless authentication via email
- WebAuthn/Passkeys - Biometric and security key authentication
- Role-Based Permissions - Fine-grained access control with custom roles
- Gallery Access Control - Per-gallery permission configuration
Enabling Authentication
1. Basic Setup
Enable authentication in your config.toml:
[app]
name = "My Gallery"
base_url = "https://yourdomain.com" # Required for WebAuthn
user_database = "users.db" # Enables authentication
cookie_secret = "your-32-character-secret-key-here" # Generate with: openssl rand -base64 32
When user_database is set:
- Authentication system is enabled
- WebAuthn/Passkeys are automatically configured
- User profiles are accessible at
/_login/profile
2. Email Configuration
Configure an email provider for magic link authentication:
[email]
# For development - logs emails to console
provider = "null"
from_address = "noreply@yourdomain.com"
# For production with Amazon SES
# provider = "ses"
# from_address = "noreply@yourdomain.com"
# from_name = "My Gallery" # Optional
# region = "us-east-1" # Optional, uses AWS credential chain
Note: SMTP provider is planned but not yet implemented.
3. Create Initial Admin User
Use the CLI to create your first admin user:
tenrankai user add admin@example.com --display-name "Admin User"
WebAuthn/Passkey Setup
WebAuthn enables passwordless authentication using:
- Biometric authentication - Touch ID, Face ID, Windows Hello
- Security keys - YubiKey, Google Titan, etc.
- Cross-device passkeys - Synced via iCloud Keychain, Google Password Manager
How It Works
- WebAuthn is automatically enabled when
user_databaseis configured - The system uses your
base_urlhostname as the Relying Party ID - Your
app.nameis used as the Relying Party name - No additional configuration needed!
User Registration Flow
- User requests login at
/_login - Enters email address
- Receives magic link via email
- Clicks link to authenticate
- Can then register passkeys at
/_login/profile
Managing Passkeys
Users can manage passkeys at /_login/profile:
- View all registered passkeys
- Register new passkeys (biometric or security key)
- Delete existing passkeys
- See last used timestamps
Role-Based Permissions
Tenrankai uses a flexible role-based permission system instead of simple access lists.
Understanding Roles
Each gallery can define custom roles with specific permissions:
[[galleries]]
name = "family"
url_prefix = "/family"
source_directory = "photos/family"
[galleries.permissions]
# Define which role unauthenticated users get
public_role = "viewer"
# Define which role authenticated users get by default
default_authenticated_role = "family_member"
# Define custom roles with specific permissions
[galleries.permissions.roles.viewer]
permissions = [
"can_view",
"can_browse_folders",
"can_see_metadata",
"can_download_thumbnail"
]
[galleries.permissions.roles.family_member]
permissions = [
"can_view",
"can_browse_folders",
"can_see_metadata",
"can_see_exact_dates",
"can_see_location",
"can_see_technical_details",
"can_download_thumbnail",
"can_download_gallery_size",
"can_download_medium",
"can_download_large",
"can_download_original"
]
Available Permissions
- can_view - View images in the gallery
- can_browse_folders - Navigate folder structure
- can_see_metadata - View basic image information
- can_see_exact_dates - See exact timestamps (vs approximate dates)
- can_see_location - View GPS coordinates and maps
- can_see_technical_details - See camera/EXIF data
- can_download_thumbnail - Download small images
- can_download_gallery_size - Download medium quality
- can_download_medium - Download larger images
- can_download_large - Download high resolution
- can_download_original - Access original files
Assigning Users to Roles
Assign specific users to custom roles:
[[galleries.permissions.user_roles]]
email = "grandma@family.com"
role = "family_member"
[[galleries.permissions.user_roles]]
email = "friend@example.com"
role = "viewer"
Gallery Access Patterns
1. Public Gallery
Anyone can view, but only see basic information:
[[galleries]]
name = "portfolio"
[galleries.permissions]
public_role = "viewer"
default_authenticated_role = "viewer"
[galleries.permissions.roles.viewer]
permissions = [
"can_view",
"can_browse_folders",
"can_see_metadata",
"can_see_technical_details", # Show camera info
"can_download_thumbnail",
"can_download_gallery_size"
]
2. Private Gallery
No public access, authenticated users only:
[[galleries]]
name = "private"
[galleries.permissions]
# No public_role defined = no public access
default_authenticated_role = "member"
[galleries.permissions.roles.member]
permissions = [
"can_view",
"can_browse_folders",
"can_see_metadata",
"can_see_exact_dates",
"can_see_location",
"can_download_thumbnail",
"can_download_gallery_size",
"can_download_original"
]
3. Client Gallery
Limited public preview, full access for clients:
[[galleries]]
name = "clients"
[galleries.permissions]
public_role = "preview"
default_authenticated_role = "preview"
[galleries.permissions.roles.preview]
permissions = ["can_view"] # View only, no downloads
[galleries.permissions.roles.client]
permissions = [
"can_view",
"can_browse_folders",
"can_see_metadata",
"can_download_thumbnail",
"can_download_gallery_size",
"can_download_medium",
"can_download_original"
]
# Assign specific client
[[galleries.permissions.user_roles]]
email = "client@company.com"
role = "client"
User Management
CLI Commands
# Add a new user
tenrankai user add user@example.com --display-name "User Name"
# List all users
tenrankai user list
# Remove a user
tenrankai user remove user@example.com
User Database Structure
Users are stored in the SQLite database specified by user_database. The system manages:
- User ID and email
- Display name
- Authentication timestamps
- WebAuthn credentials
- Role assignments
Authentication Flow
1. Email Login Flow
- User visits
/_login - Enters email address
- System sends magic link
- User clicks link in email
- Session created, redirected to original destination
2. Passkey Login Flow
- User visits
/_login - Clicks “Sign in with Passkey”
- Browser prompts for biometric/security key
- Direct authentication without email
- Session created, redirected
3. Session Management
Sessions are managed via secure cookies:
- Signed with
cookie_secret - HTTP-only and secure flags in production
- Expire on browser close by default
Authentication Endpoints
Tenrankai provides these authentication endpoints:
/_login- Login page/_login/profile- User profile and passkey management/_login/logout- Logout endpoint/_login/verify- Magic link verification/_login/api/webauthn/*- WebAuthn API endpoints
Security Best Practices
1. Configuration Security
[app]
# Generate strong secret
cookie_secret = "use-output-from: openssl rand -base64 32"
# Use HTTPS in production (required for WebAuthn)
base_url = "https://yourdomain.com"
2. Permission Design
- Start with minimal permissions and add as needed
- Use role inheritance to avoid repetition
- Regularly audit user role assignments
- Consider privacy implications of each permission
3. WebAuthn Security
- Passkeys are phishing-resistant
- Private keys never leave the device
- Support for attestation (device verification)
- Users should register multiple passkeys as backup
Troubleshooting
Common Issues
-
“WebAuthn not available”:
- Ensure HTTPS is enabled (required for WebAuthn)
- Check browser supports WebAuthn
- Verify
base_urlis correctly set
-
“Email not sent”:
- Check email provider configuration
- Verify
from_addressis valid - For development, use
provider = "null"to log emails
-
“Access denied”:
- Check user’s role assignment
- Verify permission configuration
- Ensure user is authenticated
-
“Invalid session”:
- Check
cookie_secrethasn’t changed - Verify cookies are enabled
- Clear browser cookies and try again
- Check
Debug Mode
Enable debug logging to troubleshoot:
[app]
log_level = "debug"
This will log:
- Authentication attempts
- Permission checks
- Email sending
- WebAuthn operations
Migration Notes
From Old Permission System
If you were using the old system with hide_location_from_public or require_auth:
Old:
hide_location_from_public = true
approximate_dates_for_public = true
New:
[galleries.permissions]
public_role = "viewer"
[galleries.permissions.roles.viewer]
permissions = [
"can_view",
"can_browse_folders",
"can_see_metadata"
# Note: No can_see_location or can_see_exact_dates
]
API Authentication
The API recognizes authenticated sessions:
# Login and save cookies
curl -c cookies.txt -X POST http://localhost:3000/_login \
-d "email=user@example.com"
# Use session for API calls
curl -b cookies.txt http://localhost:3000/api/galleries/main
Next Steps
- Configuration Reference - Full configuration options
- Permissions Guide - Detailed permission examples
- API Documentation - API authentication details