Authentication Configuration¶
Overview¶
Readur supports multiple authentication methods to integrate with your existing identity infrastructure. This guide covers configuration for local authentication, OIDC/SSO, LDAP, and multi-factor authentication.
Authentication Methods¶
Local Authentication¶
Default authentication using Readur's built-in user management.
Basic Configuration¶
# In .env file
AUTH_METHOD=local
ENABLE_REGISTRATION=false # Disable public registration
REQUIRE_EMAIL_VERIFICATION=true
PASSWORD_MIN_LENGTH=12
PASSWORD_REQUIRE_SPECIAL=true
PASSWORD_REQUIRE_NUMBERS=true
SESSION_LIFETIME_HOURS=24
User Management¶
Create and manage users via the API:
# Create admin user via API
curl -X POST http://localhost:8000/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"username": "admin",
"email": "[email protected]",
"password": "SecurePass123!",
"role": "admin"
}'
# Create regular user via API
curl -X POST http://localhost:8000/api/users \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"username": "john",
"email": "[email protected]",
"password": "UserPass456!",
"role": "user"
}'
# Users can also self-register if enabled:
# Set ENABLE_REGISTRATION=true in environment
OIDC/OAuth2 (Recommended)¶
Integrate with enterprise identity providers for single sign-on.
Generic OIDC Configuration¶
# In .env file
AUTH_METHOD=oidc
OIDC_ISSUER=https://auth.company.com
OIDC_CLIENT_ID=readur-app
OIDC_CLIENT_SECRET=your-client-secret
OIDC_REDIRECT_URI=https://readur.company.com/auth/callback
OIDC_SCOPE=openid profile email
OIDC_USER_CLAIM=email
OIDC_GROUPS_CLAIM=groups
OIDC_ADMIN_GROUP=readur-admins
Keycloak Integration¶
AUTH_METHOD=oidc
OIDC_ISSUER=https://keycloak.company.com/realms/master
OIDC_CLIENT_ID=readur
OIDC_CLIENT_SECRET=abc123def456
OIDC_REDIRECT_URI=https://readur.company.com/auth/callback
OIDC_SCOPE=openid profile email roles
OIDC_USER_CLAIM=preferred_username
OIDC_GROUPS_CLAIM=realm_access.roles
OIDC_ADMIN_GROUP=readur-admin
OIDC_AUTO_CREATE_USERS=true
Auth0 Integration¶
AUTH_METHOD=oidc
OIDC_ISSUER=https://company.auth0.com/
OIDC_CLIENT_ID=your-client-id
OIDC_CLIENT_SECRET=your-client-secret
OIDC_REDIRECT_URI=https://readur.company.com/auth/callback
OIDC_SCOPE=openid profile email
OIDC_AUDIENCE=https://readur.company.com/api
OIDC_USER_CLAIM=email
OIDC_GROUPS_CLAIM=https://readur.com/groups
Azure AD Integration¶
AUTH_METHOD=oidc
OIDC_ISSUER=https://login.microsoftonline.com/{tenant-id}/v2.0
OIDC_CLIENT_ID=application-id
OIDC_CLIENT_SECRET=client-secret
OIDC_REDIRECT_URI=https://readur.company.com/auth/callback
OIDC_SCOPE=openid profile email User.Read
OIDC_USER_CLAIM=upn
OIDC_GROUPS_CLAIM=groups
OIDC_ADMIN_GROUP=readur-administrators
OIDC_TOKEN_ENDPOINT_AUTH_METHOD=client_secret_post
Google Workspace Integration¶
AUTH_METHOD=oidc
OIDC_ISSUER=https://accounts.google.com
OIDC_CLIENT_ID=your-client-id.apps.googleusercontent.com
OIDC_CLIENT_SECRET=your-client-secret
OIDC_REDIRECT_URI=https://readur.company.com/auth/callback
OIDC_SCOPE=openid profile email
OIDC_USER_CLAIM=email
OIDC_HOSTED_DOMAIN=company.com # Restrict to company domain
LDAP Authentication¶
Connect to Active Directory or OpenLDAP servers.
Basic LDAP Configuration¶
AUTH_METHOD=ldap
LDAP_SERVER=ldap://ldap.company.com:389
LDAP_BIND_DN=cn=readur,ou=services,dc=company,dc=com
LDAP_BIND_PASSWORD=bind-password
LDAP_BASE_DN=ou=users,dc=company,dc=com
LDAP_USER_FILTER=(uid={username})
LDAP_USER_ATTR_MAP={"email": "mail", "name": "cn"}
LDAP_GROUP_SEARCH_BASE=ou=groups,dc=company,dc=com
LDAP_GROUP_FILTER=(member={user_dn})
LDAP_ADMIN_GROUP=cn=readur-admins,ou=groups,dc=company,dc=com
Active Directory Configuration¶
AUTH_METHOD=ldap
LDAP_SERVER=ldaps://ad.company.com:636
LDAP_BIND_DN=[email protected]
LDAP_BIND_PASSWORD=service-account-password
LDAP_BASE_DN=DC=company,DC=com
LDAP_USER_FILTER=(&(objectClass=user)(sAMAccountName={username}))
LDAP_USER_ATTR_MAP={"email": "mail", "name": "displayName"}
LDAP_GROUP_SEARCH_BASE=DC=company,DC=com
LDAP_GROUP_FILTER=(&(objectClass=group)(member={user_dn}))
LDAP_ADMIN_GROUP=CN=Readur Admins,OU=Groups,DC=company,DC=com
LDAP_USE_TLS=true
LDAP_TLS_VERIFY=true
SAML2 Authentication¶
For organizations using SAML identity providers.
Configuration¶
AUTH_METHOD=saml2
SAML2_IDP_METADATA_URL=https://idp.company.com/metadata
SAML2_SP_ENTITY_ID=https://readur.company.com
SAML2_SP_ACS_URL=https://readur.company.com/saml/acs
SAML2_SP_X509_CERT=/etc/readur/saml/cert.pem
SAML2_SP_PRIVATE_KEY=/etc/readur/saml/key.pem
SAML2_ATTRIBUTE_MAPPING={"email": "EmailAddress", "name": "DisplayName"}
SAML2_ADMIN_GROUP=readur-administrators
Multi-Factor Authentication¶
TOTP (Time-based One-Time Password)¶
Enable 2FA using authenticator apps:
# Enable TOTP
MFA_ENABLED=true
MFA_METHOD=totp
MFA_ISSUER=Readur
MFA_ENFORCE_FOR_ADMINS=true
MFA_GRACE_PERIOD_DAYS=7 # Days before enforcement
WebAuthn/FIDO2¶
Hardware security key support:
MFA_ENABLED=true
MFA_METHOD=webauthn
WEBAUTHN_RP_ID=readur.company.com
WEBAUTHN_RP_NAME=Readur Document Management
WEBAUTHN_REQUIRE_ATTESTATION=direct
Role-Based Access Control (RBAC)¶
Role Configuration¶
Define roles and permissions:
# roles.yaml
roles:
admin:
permissions:
- documents.*
- users.*
- settings.*
- system.*
editor:
permissions:
- documents.create
- documents.read
- documents.update
- documents.delete.own
- ocr.*
viewer:
permissions:
- documents.read
- search.*
auditor:
permissions:
- documents.read
- audit.view
- reports.generate
Group Mapping¶
Map external groups to Readur roles:
# OIDC group mapping
OIDC_GROUP_ROLE_MAPPING='{
"readur-admins": "admin",
"readur-editors": "editor",
"readur-viewers": "viewer",
"compliance-team": "auditor"
}'
# LDAP group mapping
LDAP_GROUP_ROLE_MAPPING='{
"CN=Readur Admins,OU=Groups,DC=company,DC=com": "admin",
"CN=Readur Users,OU=Groups,DC=company,DC=com": "editor"
}'
Session Management¶
Session Configuration¶
# Session settings
SESSION_COOKIE_NAME=readur_session
SESSION_COOKIE_SECURE=true # HTTPS only
SESSION_COOKIE_HTTPONLY=true
SESSION_COOKIE_SAMESITE=Lax
SESSION_LIFETIME_HOURS=8
SESSION_IDLE_TIMEOUT_MINUTES=30
SESSION_REMEMBER_ME_DAYS=30
SESSION_MAX_CONCURRENT=3 # Max sessions per user
Session Storage¶
# Redis-backed sessions (recommended)
SESSION_BACKEND=redis
REDIS_SESSION_URL=redis://localhost:6379/1
# Database sessions
SESSION_BACKEND=database
SESSION_CLEANUP_INTERVAL_HOURS=24
Security Headers¶
Configure security headers for authentication:
# Security headers
SECURITY_HEADERS_ENABLED=true
SECURITY_CSP="default-src 'self'; script-src 'self' 'unsafe-inline'"
SECURITY_HSTS_SECONDS=31536000
SECURITY_HSTS_INCLUDE_SUBDOMAINS=true
SECURITY_X_FRAME_OPTIONS=DENY
SECURITY_X_CONTENT_TYPE_OPTIONS=nosniff
SECURITY_REFERRER_POLICY=strict-origin-when-cross-origin
API Authentication¶
API Key Authentication¶
For service-to-service communication:
Generate API keys via the API:
# Create API key for service (requires admin authentication)
curl -X POST http://localhost:8000/api/keys \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "backup-service",
"scope": ["documents.read"]
}'
JWT Tokens¶
For programmatic access:
# JWT configuration
JWT_ENABLED=true
JWT_SECRET_KEY=your-jwt-secret
JWT_ALGORITHM=HS256
JWT_EXPIRY_MINUTES=60
JWT_REFRESH_ENABLED=true
JWT_REFRESH_EXPIRY_DAYS=7
Troubleshooting¶
OIDC Issues¶
Discovery Failed¶
# Test OIDC discovery
curl https://auth.company.com/.well-known/openid-configuration
# Check network connectivity
docker-compose exec readur curl https://auth.company.com
Token Validation Errors¶
# Enable debug logging
OIDC_DEBUG=true
LOG_LEVEL=DEBUG
# Check token claims
docker-compose exec readur python manage.py debug_oidc_token
LDAP Issues¶
Connection Failed¶
# Test LDAP connection
ldapsearch -x -H ldap://ldap.company.com:389 \
-D "cn=readur,ou=services,dc=company,dc=com" \
-W -b "dc=company,dc=com" "(uid=testuser)"
# Test from container
docker-compose exec readur ldapsearch -x -H $LDAP_SERVER
User Not Found¶
# Debug LDAP queries
LDAP_DEBUG=true
LOG_LEVEL=DEBUG
# Test LDAP user filter directly
ldapsearch -x -H $LDAP_SERVER \
-D "$LDAP_BIND_DN" \
-w "$LDAP_BIND_PASSWORD" \
-b "$LDAP_BASE_DN" \
"(uid=testuser)"
Session Issues¶
Sessions Expiring Too Quickly¶
# Check Redis connectivity
docker-compose exec readur redis-cli -h redis ping
# Monitor session creation
docker-compose exec readur redis-cli monitor | grep session
Best Practices¶
Security Recommendations¶
- Always use HTTPS in production
- Enable MFA for administrative accounts
- Regular password rotation for service accounts
- Audit authentication logs regularly
- Use external IdP when possible
- Implement rate limiting on authentication endpoints
- Monitor failed login attempts
Integration Testing¶
Test authentication before production:
# Test OIDC flow via health endpoint
curl http://localhost:8000/api/health/auth/oidc
# Test LDAP connection
curl -X POST http://localhost:8000/api/auth/test \
-H "Content-Type: application/json" \
-d '{
"method": "ldap",
"username": "testuser",
"password": "testpass"
}'
# Verify user groups via API
curl http://localhost:8000/api/users/[email protected]/groups \
-H "Authorization: Bearer $ADMIN_TOKEN"
Monitoring¶
Set up authentication monitoring:
# Monitor failed login attempts via logs
docker-compose logs readur | grep -E "(auth|login|failed)" | tail -n 100
# Check active sessions in database
docker-compose exec readur psql -U readur -d readur -c \
"SELECT username, last_login, session_count FROM users WHERE last_login > NOW() - INTERVAL '24 hours';"
# Monitor authentication metrics (if metrics endpoint enabled)
curl http://localhost:8000/metrics | grep -E "(auth|login|session)"
Migration from Other Systems¶
Migrating Users¶
# Export users from old system
old_system_export_users > users.json
# Import to Readur via bulk API
curl -X POST http://localhost:8000/api/users/import \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d @users.json
# Or create users one by one via API
while IFS=, read -r username email role; do
curl -X POST http://localhost:8000/api/users \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"username\": \"$username\",
\"email\": \"$email\",
\"role\": \"$role\"
}"
done < users.csv