Default Authentication
The IDPass Data Collect system includes a built-in authentication mechanism that provides a simple username/password login system without requiring external authentication providers like Auth0 or Keycloak.
Overview
The default authentication system consists of:
- Backend: User management with JWT token generation
- Frontend: Login form and token management
- Mobile: Authentication integration with the mobile app
- Data Layer: User storage and password hashing
Architecture
Backend Components
User Store (UserStore.ts)
The UserStoreImpl class manages user data in a PostgreSQL database:
interface UserWithPasswordHash {
id: number;
email: string;
passwordHash: string;
role: Role;
}
Key Features:
- User CRUD operations (Create, Read, Update, Delete)
- Password hashing using bcrypt
- Role-based access control (ADMIN, USER)
- Database initialization with user table
User Routes (userRoutes.ts)
RESTful API endpoints for user authentication:
POST /api/users/login- User login with email/passwordGET /api/users/check-token- Validate JWT tokenGET /api/users/me- Get current user informationPOST /api/users- Create new user (admin only)PUT /api/users/:id- Update user (admin only)DELETE /api/users/:email- Delete user (admin only)
Authentication Middleware (authentication.ts)
JWT-based authentication middleware:
authenticateJWT- Validates JWT tokens for protected routescreateAuthAdminMiddleware- Ensures admin role accesscreateDynamicAuthMiddleware- Handles dynamic app authentication
Frontend Components
Auth Manager (AuthManager.ts)
The core authentication manager in the datacollect package:
class AuthManager {
constructor(
private configs: AuthConfig[],
private syncServerUrl: string,
private authStorage?: AuthStorageAdapter,
) {}
}
Key Methods:
defaultLogin(credentials: PasswordCredentials)- Handles username/password loginisAuthenticated()- Checks authentication status across all providerslogin()- Initiates login processlogout()- Clears all authentication tokens
Default Login Flow:
- Validates credentials against sync server
- Receives JWT token from backend
- Stores token in auth storage with "default" provider key
- Returns authentication status
Mobile Auth Manager Store (authManager.ts)
Pinia store for mobile authentication state management:
export const useAuthManagerStore = defineStore('authManager', () => {
// State management for authentication
const isAuthenticated = ref(false)
const currentProvider = ref<string | null>(null)
const authManager = ref<EntityDataManager | null>(null)
})
Key Features:
- Initializes authentication system with app-specific configuration
- Manages login/logout flows
- Handles OAuth callbacks
- Provides authentication state across the mobile app
Auth Screen (AuthScreen.vue)
Vue component for the authentication interface:
<template>
<form @submit.prevent="onLogin">
<input type="email" v-model="form.email" />
<input type="password" v-model="form.password" />
<button type="submit">Login</button>
</form>
</template>
Features:
- Email/password login form
- Error handling and display
- Loading states
- OAuth provider integration
- Callback processing for OAuth flows
Authentication Flow
1. User Login Process
2. Token Validation
Configuration
Environment Variables
# JWT Secret for token signing
JWT_SECRET=your-secret-key
# Database connection
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
User Roles
The system supports two user roles:
- ADMIN: Full access to user management and system configuration
- USER: Standard user access to data collection features
Password Security
- Passwords are hashed using bcrypt with 10 salt rounds
- Plain text passwords are never stored
- Password validation occurs on every login attempt
Usage Examples
Backend User Creation
import { UserStoreImpl } from './stores/UserStore';
import bcrypt from 'bcrypt';
const userStore = new UserStoreImpl(connectionString);
await userStore.initialize();
// Create admin user
const passwordHash = await bcrypt.hash('admin123', 10);
await userStore.saveUser({
email: 'admin@example.com',
passwordHash,
role: Role.ADMIN
});
Frontend Authentication
import { AuthManager } from 'idpass-data-collect';
const authManager = new AuthManager(configs, syncServerUrl, authStorage);
await authManager.initialize();
// Login with credentials
await authManager.login({
username: 'user@example.com',
password: 'password123'
});
// Check authentication status
const isAuth = await authManager.isAuthenticated();
Mobile App Integration
import { useAuthManagerStore } from '@/store/authManager';
const authStore = useAuthManagerStore();
// Initialize for specific app
await authStore.initialize('app-id');
// Login with default authentication
await authStore.login(null, {
username: 'user@example.com',
password: 'password123'
});
// Handle successful login
await authStore.handleDefaultLogin();
Integration with External Providers
The default authentication system can coexist with external providers:
- Multiple Auth Configs: Configure both default and external providers
- Fallback Mechanism: Use default auth when external providers fail
- Unified Interface: Same API regardless of authentication method
- Token Management: Centralized token storage and validation
Troubleshooting
Common Issues
-
JWT Secret Not Set
- Ensure
JWT_SECRETenvironment variable is configured - Restart the backend server after setting the variable
- Ensure
-
Database Connection Issues
- Verify
DATABASE_URLis correct - Ensure PostgreSQL is running and accessible
- Check database permissions
- Verify
-
Token Validation Failures
- Verify token format and signature
- Check token expiration
- Ensure consistent JWT secret across services
-
Mobile Authentication Issues
- Clear app storage and reinitialize
- Verify network connectivity
- Check app configuration and tenant settings