# Auth Module Standalone authentication module for PocketBase OAuth2 + Microsoft Graph integration. ## Features - **Frontend**: PocketBase OAuth2 authentication with Microsoft provider - **Backend**: Microsoft Graph token management with automatic caching - **No dependencies on project-specific code** - Use in any project ## Installation Copy the `auth-module` folder to your project: ```bash cp -r auth-module /path/to/your/project/ ``` Install dependencies: ```bash bun add pocketbase @azure/msal-node ``` ## Frontend Usage ### Basic Setup ```typescript import { PocketBaseAuth } from './auth-module/frontend'; const auth = new PocketBaseAuth({ pbUrl: 'http://localhost:8090', collection: 'Users', provider: 'microsoft', loginContainerId: 'loginContainer', userDisplayNameId: 'userDisplayName', userEmailId: 'userEmailValue', loginBtnId: 'loginBtn', loginErrorId: 'loginError', }); ``` ### HTML Required ```html
``` ### Event Callbacks ```typescript const auth = new PocketBaseAuth(config, { onAuthSuccess: (state) => { console.log('Logged in:', state.user.email); // Initialize other systems here }, onAuthFailure: (error) => { console.error('Login failed:', error); }, onTokenUpdate: (state) => { console.log('Token refreshed'); }, onUiUpdate: (state) => { console.log('UI updated'); }, }); ``` ### Methods ```typescript // Get current auth state const state = auth.getAuthState(); console.log(state.isAuthenticated, state.user); // Check token status const status = await auth.checkTokenStatus(); // Logout auth.logout(); // Get raw PocketBase instance if needed const pb = auth.getPocketBase(); ``` ## Backend Usage ### Setup (server.ts) ```typescript import { GraphTokenManager, PocketBaseValidator, BackendAuth } from './auth-module/backend'; // Option 1: Use individual managers const graphMgr = new GraphTokenManager({ clientId: process.env.CLIENT_ID, tenantId: process.env.TENANT_ID, clientSecret: process.env.CLIENT_SECRET, }); const pbValidator = new PocketBaseValidator('http://127.0.0.1:8090'); // Option 2: Use combined manager const backendAuth = new BackendAuth({ clientId: process.env.CLIENT_ID, tenantId: process.env.TENANT_ID, clientSecret: process.env.CLIENT_SECRET, }); ``` ### Get Graph Token ```typescript // Get token string const token = await graphMgr.getToken(); // Get token with expiration const { token, expiresOnISO } = await graphMgr.getTokenWithExpiry(); // Check if cached and valid if (graphMgr.isTokenValid()) { console.log('Using cached token'); } // Clear cache (force refresh) graphMgr.clearCache(); ``` ### Validate PocketBase Token ```typescript // Validate token const isValid = await pbValidator.validateUserToken(token); // Get user record const user = await pbValidator.getUserRecord(token); // Get PocketBase instance const pb = pbValidator.getPocketBase(); ``` ### Endpoint Example ```typescript app.get('/api/graph/status', async (c) => { try { const { token, expiresOnISO } = await graphMgr.getTokenWithExpiry(); return c.json({ active: true, expiresOnISO, }); } catch (error) { return c.json( { active: false, error: error.message }, 500 ); } }); app.post('/api/submit', async (c) => { const body = await c.req.json(); const pbToken = body.pbToken; if (!pbToken) { return c.json({ error: 'Missing pbToken' }, 401); } const isValid = await pbValidator.validateUserToken(pbToken); if (!isValid) { return c.json({ error: 'Invalid token' }, 401); } // Token is valid, proceed with business logic // ... }); ``` ## Environment Variables Required in `.env` file: ```env CLIENT_ID=your-microsoft-app-id TENANT_ID=your-azure-tenant-id CLIENT_SECRET=your-microsoft-client-secret PB_DB=http://127.0.0.1:8090 # PocketBase URL ``` ## Configuration ### Frontend Config Options ```typescript interface AuthConfig { pbUrl?: string; // PocketBase URL (default: http://localhost:8090) collection?: string; // Auth collection (default: Users) provider?: string; // OAuth provider (default: microsoft) loginContainerId?: string; // ID of login container element userDisplayNameId?: string; // ID of user name display element userEmailId?: string; // ID of user email display element loginBtnId?: string; // ID of login button element loginErrorId?: string; // ID of error message element } ``` ### Backend Config Options ```typescript interface BackendAuthConfig { clientId?: string; // Microsoft app ID (or CLIENT_ID env var) tenantId?: string; // Azure tenant ID (or TENANT_ID env var) clientSecret?: string; // Client secret (or CLIENT_SECRET env var) } ``` ## TypeScript The module exports TypeScript types for type safety: ```typescript import { AuthState, AuthConfig, GraphTokenCache } from './auth-module/types'; const state: AuthState = auth.getAuthState(); ``` ## Notes - **Frontend** manages user authentication only - **Backend** manages Graph API tokens (never exposed to client) - Tokens are cached in-memory on backend with automatic refresh - Module does not include project-specific features (alerts, etc.) - Each project can implement its own business logic on top ## License Same as parent project