692 lines
31 KiB
Markdown
692 lines
31 KiB
Markdown
================================================================================
|
|
AUTH FOLDER: COMPREHENSIVE ANALYSIS & TOKEN FLOW DOCUMENTATION
|
|
================================================================================
|
|
|
|
PROJECT: NewApproach
|
|
DATE: 2026-01-10
|
|
STATUS: In-depth analysis of auth module token acquisition, storage, and retrieval
|
|
|
|
================================================================================
|
|
FOLDER CONTENTS OVERVIEW
|
|
================================================================================
|
|
|
|
/NewApproach/auth/
|
|
├── auth.ts TypeScript implementation (source)
|
|
├── auth-universal.js JavaScript version (browser-compatible)
|
|
├── auth-test.html Interactive test interface for manual testing
|
|
└── README.md Documentation and quick-start guide
|
|
|
|
================================================================================
|
|
ARCHITECTURAL DESIGN
|
|
================================================================================
|
|
|
|
PATTERN-BASED CONFIGURATION:
|
|
- Auth system uses a "pattern" approach to enable only needed token types
|
|
- Patterns: 'pb', 'graph', 'pb+graph' (composable, can add more)
|
|
- This allows flexibility across different projects using different providers
|
|
|
|
SUPPORTED TOKEN TYPES (4 total):
|
|
1. 'pb-user' → PocketBase user authentication token
|
|
2. 'pb-agent' → PocketBase service account token (for server-to-server)
|
|
3. 'graph-user' → Microsoft Graph delegated token (on behalf of signed-in user)
|
|
4. 'graph-agent' → Microsoft Graph app-only token (service principal auth)
|
|
|
|
STORAGE MECHANISM:
|
|
- All tokens stored in browser localStorage (client-side storage)
|
|
- Storage keys use consistent naming pattern: 'auth:<token-type>'
|
|
- Examples:
|
|
* 'auth:pb-user' → stores PocketBase user token
|
|
* 'auth:graph-user' → stores Microsoft Graph delegated token
|
|
|
|
================================================================================
|
|
TOKEN ACQUISITION FLOW (WHERE & WHEN)
|
|
================================================================================
|
|
|
|
CRITICAL DISTINCTION: This module does NOT acquire tokens itself.
|
|
It is a STORAGE & RETRIEVAL system. Actual token acquisition happens elsewhere.
|
|
|
|
WHO ACQUIRES TOKENS?
|
|
- PocketBase tokens: PocketBase SDK (pb.authStore.token after user logs in)
|
|
- Graph tokens: Microsoft authentication library (via OAuth flow or app auth)
|
|
- These are obtained OUTSIDE this auth module
|
|
- This module then STORES and RETRIEVES them
|
|
|
|
THE FLOW:
|
|
|
|
1. EXTERNAL CODE ACQUIRES TOKEN
|
|
└─ Where: In user's application code or backend
|
|
└─ How: Via PocketBase SDK login or Microsoft authentication libraries
|
|
└─ When: After successful user authentication or service account setup
|
|
|
|
2. TOKEN IS STORED VIA Auth.setToken()
|
|
└─ Code: Auth.setToken('pb-user', <token-from-pocketbase>)
|
|
└─ Storage: localStorage under key 'auth:pb-user'
|
|
└─ When: Immediately after acquisition (outside this module)
|
|
|
|
3. TOKEN IS RETRIEVED VIA Auth.getToken()
|
|
└─ Code: const token = Auth.getToken('pb-user')
|
|
└─ Returns: String token or null if not found
|
|
└─ When: Whenever application needs to use the token (API calls, etc.)
|
|
|
|
================================================================================
|
|
STORAGE DETAILS (EXACT LOCATIONS & KEYS)
|
|
================================================================================
|
|
|
|
localStorage MAP:
|
|
|
|
Token Type │ Storage Key │ Where It Comes From
|
|
────────────────────┼────────────────────┼────────────────────────────────
|
|
'pb-user' │ 'auth:pb-user' │ PocketBase SDK after login
|
|
'pb-agent' │ 'auth:pb-agent' │ PocketBase SDK service account
|
|
'graph-user' │ 'auth:graph-user' │ MSAL or Graph auth library
|
|
'graph-agent' │ 'auth:graph-agent' │ Azure app authentication
|
|
|
|
STORAGE FORMAT:
|
|
- Raw string value (plaintext)
|
|
- Example: localStorage['auth:pb-user'] = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
- No serialization, just direct token string storage
|
|
|
|
PERSISTENCE:
|
|
- localStorage persists until:
|
|
* User manually clears browser data
|
|
* JavaScript calls localStorage.removeItem(key)
|
|
* Session expires (no automatic expiry in this module)
|
|
- Survives page refreshes and browser restarts (within same origin)
|
|
|
|
================================================================================
|
|
RETRIEVAL METHODS (HOW TO GET TOKENS BACK)
|
|
================================================================================
|
|
|
|
METHOD 1: Direct Retrieval
|
|
─────────────────────────
|
|
Auth.getToken('pb-user')
|
|
|
|
Returns: string | null
|
|
- Returns the token string if found
|
|
- Returns null if token was never set or was cleared
|
|
|
|
Usage Example:
|
|
const pbToken = Auth.getToken('pb-user');
|
|
if (pbToken) {
|
|
// Use token in API call
|
|
fetch('/api/users', {
|
|
headers: { 'Authorization': `Bearer ${pbToken}` }
|
|
});
|
|
}
|
|
|
|
Method Signature (TypeScript):
|
|
getToken(type: TokenType): string | null
|
|
|
|
Internal Implementation:
|
|
1. Accepts token type: 'pb-user', 'pb-agent', 'graph-user', or 'graph-agent'
|
|
2. Looks up storage key from TOKEN_STORAGE_KEYS map
|
|
3. Calls localStorage.getItem(key)
|
|
4. Returns result (string or null)
|
|
|
|
────────────────────────────────────────────────────────────────────────────
|
|
|
|
METHOD 2: Set Token (Store for Later Retrieval)
|
|
───────────────────────────────────────────────
|
|
Auth.setToken('pb-user', 'token-string-here')
|
|
|
|
Usage: When you receive a token from external auth system
|
|
// After PocketBase login:
|
|
const pbAuth = await pb.collection('users').authWithPassword(email, pass);
|
|
Auth.setToken('pb-user', pbAuth.token); // Now stored for later use
|
|
|
|
Method Signature (TypeScript):
|
|
setToken(type: TokenType, token: string | null): void
|
|
|
|
Internal Implementation:
|
|
1. Accepts token type and token string
|
|
2. Looks up storage key
|
|
3. If token is provided: localStorage.setItem(key, token)
|
|
4. If token is null: localStorage.removeItem(key)
|
|
|
|
────────────────────────────────────────────────────────────────────────────
|
|
|
|
METHOD 3: Clear Individual Token
|
|
────────────────────────────────
|
|
Auth.clearToken('pb-user')
|
|
|
|
Removes one token from storage.
|
|
|
|
Method Signature (TypeScript):
|
|
clearToken(type: TokenType): void
|
|
|
|
Internal Implementation:
|
|
Calls setToken(type, null) which removes the item
|
|
|
|
Usage: On logout or when token expires
|
|
Auth.clearToken('pb-user'); // PocketBase token removed
|
|
|
|
────────────────────────────────────────────────────────────────────────────
|
|
|
|
METHOD 4: Clear All Tokens
|
|
──────────────────────────
|
|
Auth.clearAllTokens()
|
|
|
|
Removes all stored tokens (all 4 types) in one call.
|
|
|
|
Method Signature (TypeScript):
|
|
clearAllTokens(): void
|
|
|
|
Internal Implementation:
|
|
Iterates through all TOKEN_STORAGE_KEYS
|
|
Calls localStorage.removeItem() for each key
|
|
|
|
Usage: On complete logout
|
|
Auth.clearAllTokens(); // All tokens removed
|
|
|
|
────────────────────────────────────────────────────────────────────────────
|
|
|
|
METHOD 5: Configuration & Setup
|
|
────────────────────────────────
|
|
await Auth.configure('pb+graph', { pbUrl: 'http://localhost:8090' })
|
|
|
|
Initializes the auth module with:
|
|
- Which patterns to enable ('pb', 'graph', 'pb+graph')
|
|
- Optional config (PocketBase URL, Graph API URL)
|
|
|
|
Method Signature (TypeScript):
|
|
async configure(patternString: string, config?: AuthConfig): Promise<void>
|
|
|
|
Internal Implementation:
|
|
1. Parses pattern string into array of token types
|
|
2. Stores pattern for validation
|
|
3. If pattern includes 'pb' tokens: initializes PocketBase SDK
|
|
4. If PocketBase library not loaded: throws error
|
|
|
|
CRITICAL: PocketBase must be loaded via <script> BEFORE calling configure()
|
|
|
|
Config Object Properties:
|
|
interface AuthConfig {
|
|
pbUrl?: string; // Default: http://127.0.0.1:8090
|
|
graphApiUrl?: string; // URL for Microsoft Graph API
|
|
}
|
|
|
|
────────────────────────────────────────────────────────────────────────────
|
|
|
|
METHOD 6: Query Module State
|
|
────────────────────────────
|
|
Auth.isConfigured(): boolean
|
|
Auth.getEnabledTypes(): TokenType[]
|
|
|
|
Check if module is ready and what token types are enabled.
|
|
|
|
Usage:
|
|
if (Auth.isConfigured()) {
|
|
const types = Auth.getEnabledTypes(); // Returns ['pb-user', 'pb-agent']
|
|
const token = Auth.getToken('pb-user');
|
|
}
|
|
|
|
================================================================================
|
|
FILE-BY-FILE BREAKDOWN
|
|
================================================================================
|
|
|
|
FILE 1: auth.ts (TypeScript Source)
|
|
═════════════════════════════════════
|
|
|
|
PURPOSE:
|
|
- Main implementation of AuthManager class
|
|
- Fully typed with TypeScript (strict mode)
|
|
- Source file (not browser-compatible directly)
|
|
|
|
TOKEN ACQUISITION POINT:
|
|
- NONE. This file does NOT acquire tokens.
|
|
- It only stores and retrieves tokens from localStorage
|
|
- External code must provide tokens via Auth.setToken()
|
|
|
|
TOKEN STORAGE MECHANISM:
|
|
- localStorage is the sole storage mechanism
|
|
- Keys defined in TOKEN_STORAGE_KEYS constant:
|
|
const TOKEN_STORAGE_KEYS: TokenConfig = {
|
|
'pb-user': 'auth:pb-user',
|
|
'pb-agent': 'auth:pb-agent',
|
|
'graph-user': 'auth:graph-user',
|
|
'graph-agent': 'auth:graph-agent'
|
|
};
|
|
|
|
CLASS STRUCTURE:
|
|
- AuthManager class (private instance state)
|
|
- Singleton exported as: export default Auth
|
|
- Also attached to window for browser use: window.Auth = Auth
|
|
|
|
KEY STATE VARIABLES:
|
|
- private pattern: TokenType[] = [] (which token types are enabled)
|
|
- private pbInstance: any = null (PocketBase SDK instance)
|
|
- private config: AuthConfig = {} (configuration passed by user)
|
|
|
|
METHOD IMPLEMENTATIONS:
|
|
|
|
1. configure(patternString, config?)
|
|
├─ Parses pattern string: 'pb+graph' → ['pb-user', 'pb-agent', 'graph-user', 'graph-agent']
|
|
├─ Actually only returns ['pb', 'graph'] because parsePattern treats 'pb' as a prefix filter
|
|
├─ Stores config
|
|
└─ If pattern includes 'pb': calls initPocketBase()
|
|
|
|
2. parsePattern(pattern: string): TokenType[]
|
|
├─ Splits by '+'
|
|
├─ Trims whitespace
|
|
├─ Filters empty strings
|
|
├─ Casts to TokenType[]
|
|
└─ QUIRK: This is overly simple and may not work correctly for all cases
|
|
|
|
3. initPocketBase()
|
|
├─ Gets PocketBase from window.PocketBase
|
|
├─ Creates instance with URL from config
|
|
├─ Throws if window.PocketBase not loaded
|
|
└─ Stores in this.pbInstance (but never used anywhere)
|
|
|
|
4. getToken(type: TokenType): string | null
|
|
├─ Looks up TOKEN_STORAGE_KEYS[type]
|
|
├─ Calls localStorage.getItem(key)
|
|
└─ Returns result (string | null)
|
|
|
|
5. setToken(type: TokenType, token: string | null): void
|
|
├─ Looks up TOKEN_STORAGE_KEYS[type]
|
|
├─ If token is truthy: localStorage.setItem(key, token)
|
|
└─ If token is falsy: localStorage.removeItem(key)
|
|
|
|
6. clearToken(type: TokenType): void
|
|
└─ Calls setToken(type, null)
|
|
|
|
7. clearAllTokens(): void
|
|
└─ Iterates all TOKEN_STORAGE_KEYS and removes each
|
|
|
|
DEPENDENCIES:
|
|
- localStorage (browser API) - REQUIRED
|
|
- PocketBase (window.PocketBase) - Optional, only if using 'pb' pattern
|
|
- No npm dependencies
|
|
|
|
SECURITY NOTES:
|
|
- Tokens stored in plaintext localStorage
|
|
- Accessible to any JavaScript on the page
|
|
- Vulnerable to XSS attacks
|
|
- Not suitable for highly sensitive credentials
|
|
- Production: consider HTTP-only cookies on backend
|
|
|
|
────────────────────────────────────────────────────────────────────────────
|
|
|
|
FILE 2: auth-universal.js (JavaScript Version)
|
|
════════════════════════════════════════════════
|
|
|
|
PURPOSE:
|
|
- Browser-compatible JavaScript version of auth.ts
|
|
- Simpler implementation, less feature-rich
|
|
- Can be used without TypeScript compilation
|
|
|
|
STRUCTURE:
|
|
- IIFE (Immediately Invoked Function Expression)
|
|
- Exposes Auth object to window.Auth
|
|
- Returns object with public methods
|
|
|
|
TOKEN ACQUISITION POINT:
|
|
- NONE. Same as auth.ts.
|
|
- Use Auth.setToken() to store tokens from external sources
|
|
|
|
TOKEN STORAGE:
|
|
- localStorage with keys defined in TOKEN_KEYS:
|
|
const TOKEN_KEYS = {
|
|
'pb-user': 'pbUserToken',
|
|
'pb-agent': 'pbAgentToken',
|
|
'graph-user': 'graphUserToken',
|
|
'graph-agent': 'graphAgentToken'
|
|
};
|
|
|
|
IMPORTANT DIFFERENCE FROM auth.ts:
|
|
- DIFFERENT STORAGE KEY NAMES!
|
|
- auth.ts uses: 'auth:pb-user'
|
|
- auth-universal.js uses: 'pbUserToken'
|
|
- ⚠️ INCOMPATIBLE: Tokens stored by one won't be readable by the other!
|
|
|
|
STATE VARIABLES:
|
|
let pattern = 'pb-user' (default pattern)
|
|
let enabledTypes = ['pb-user'] (which types are active)
|
|
let pb = null (PocketBase instance)
|
|
let popup = null (for OAuth popups, not implemented)
|
|
let agentCreds = { email: '', password: '' } (credentials storage, not used)
|
|
let superuserCreds = { email: '', password: '' } (credentials storage, not used)
|
|
|
|
PUBLIC METHODS:
|
|
window.Auth.use(type) │ Set active pattern
|
|
window.Auth.setPB(pbInstance) │ Inject PocketBase instance
|
|
window.Auth.getToken(type) │ Retrieve token from localStorage
|
|
window.Auth.setToken(type, token) │ Store token to localStorage
|
|
|
|
METHOD IMPLEMENTATIONS:
|
|
|
|
1. use(type)
|
|
├─ Sets pattern variable
|
|
├─ Parses type string into enabledTypes array
|
|
├─ If pattern includes 'pb': calls initPocketBase()
|
|
└─ Returns 'this' for chaining
|
|
|
|
2. setPB(pbInstance)
|
|
├─ Allows external PocketBase instance injection
|
|
└─ Stores in pb variable
|
|
|
|
3. initPocketBase()
|
|
├─ Returns early if pb already set
|
|
├─ Creates new PocketBase('http://127.0.0.1:8090')
|
|
└─ Stores in pb variable
|
|
|
|
4. getToken(type)
|
|
├─ Looks up TOKEN_KEYS[type]
|
|
├─ Returns localStorage.getItem(key) or null
|
|
└─ Same behavior as auth.ts version
|
|
|
|
5. setToken(type, token)
|
|
├─ Looks up TOKEN_KEYS[type]
|
|
├─ If token: localStorage.setItem(key, token)
|
|
└─ If !token: localStorage.removeItem(key)
|
|
|
|
UNUSED/INCOMPLETE:
|
|
- popup variable (defined but never used)
|
|
- agentCreds, superuserCreds (defined but never used)
|
|
- Suggests incomplete refactoring or planned features
|
|
|
|
DEPENDENCIES:
|
|
- localStorage (browser API)
|
|
- PocketBase (optional, can be injected via setPB())
|
|
|
|
────────────────────────────────────────────────────────────────────────────
|
|
|
|
FILE 3: auth-test.html (Testing & Validation)
|
|
═══════════════════════════════════════════════
|
|
|
|
PURPOSE:
|
|
- Interactive HTML test page
|
|
- Manual verification of auth module functionality
|
|
- No automated testing, all tests are button-triggered
|
|
|
|
TOKEN ACQUISITION:
|
|
- NONE. This file does NOT acquire tokens.
|
|
- Tests localStorage directly to verify storage mechanics
|
|
|
|
HOW IT WORKS:
|
|
- Loads auth-universal.js (or auth.ts compiled)
|
|
- Provides buttons that trigger JavaScript functions
|
|
- Functions test module availability and storage
|
|
|
|
TEST SECTIONS:
|
|
|
|
1. Module Availability Test
|
|
├─ Button: "Test Module Load"
|
|
├─ Tests: typeof window.Auth !== 'undefined'
|
|
└─ Verifies: Auth module is accessible globally
|
|
|
|
2. Token Storage Test
|
|
├─ Button: "Test Token Storage"
|
|
├─ Tests:
|
|
│ ├─ localStorage.setItem('test:token', 'test-value')
|
|
│ ├─ localStorage.getItem('test:token')
|
|
│ └─ localStorage.removeItem('test:token')
|
|
└─ Verifies: localStorage works correctly
|
|
|
|
3. Configuration Test
|
|
├─ Button: "Test Configuration"
|
|
├─ Tests: typeof window.Auth.configure === 'function'
|
|
└─ Verifies: Auth.configure method exists
|
|
|
|
4. Clear Tokens Test
|
|
├─ Button: "Clear All Tokens"
|
|
├─ Steps:
|
|
│ ├─ Creates test tokens: 'auth:pb-user', 'auth:graph-user'
|
|
│ ├─ Removes them via localStorage.removeItem()
|
|
│ └─ Verifies tokens are gone
|
|
└─ Tests: Auth module clearing capability
|
|
|
|
LIMITATIONS:
|
|
- Tests use direct localStorage, not Auth.clearAllTokens()
|
|
- Tests auth-test.html keys, not actual auth module keys
|
|
- Not comprehensive
|
|
- No error handling for edge cases
|
|
- No async test support
|
|
|
|
────────────────────────────────────────────────────────────────────────────
|
|
|
|
FILE 4: README.md (Documentation)
|
|
══════════════════════════════════
|
|
|
|
PURPOSE:
|
|
- Public-facing documentation
|
|
- Quick-start guide for developers
|
|
|
|
KEY SECTIONS:
|
|
1. Overview: Describes pattern-based approach and features
|
|
2. Quick Start: Code examples showing basic usage
|
|
3. Token Types: Lists all 4 token types
|
|
4. Configuration: Documents AuthConfig interface
|
|
5. Security Considerations: Plaintext localStorage warning
|
|
6. File Structure: Simple directory listing
|
|
7. Testing: Refers to auth-test.html
|
|
8. Future Enhancements: Planned features (refresh logic, expiration tracking, etc.)
|
|
|
|
CRITICAL SECURITY WARNING FROM DOCS:
|
|
- "Tokens are stored in plaintext in localStorage"
|
|
- "Never store highly sensitive credentials in browser localStorage"
|
|
- "For production: consider using secure HTTP-only cookies via backend"
|
|
|
|
================================================================================
|
|
COMPLETE TOKEN FLOW DIAGRAM
|
|
================================================================================
|
|
|
|
┌─────────────────────────────────────────────────────────────────────────┐
|
|
│ EXTERNAL AUTH SOURCE │
|
|
│ (PocketBase SDK, MSAL, Azure App Auth, etc.) │
|
|
└────────────────────────┬────────────────────────────────────────────────┘
|
|
│
|
|
│ TOKEN ACQUIRED
|
|
│ (user login, service auth, OAuth)
|
|
▼
|
|
┌──────────────────────────────────┐
|
|
│ Auth.setToken('type', token) │ ← CODE STORES TOKEN
|
|
└────────────┬─────────────────────┘
|
|
│
|
|
│ Calls: localStorage.setItem(key, token)
|
|
│ Key Example: 'auth:pb-user'
|
|
▼
|
|
┌──────────────────────────────────┐
|
|
│ Browser localStorage │ ← PERSISTENT STORAGE
|
|
│ 'auth:pb-user' → 'eyJhbG...' │
|
|
│ 'auth:graph-user' → 'ya29.a...' │
|
|
└──────────────────────────────────┘
|
|
│
|
|
│ On page load or API call needed
|
|
│
|
|
┌────────────▼──────────────────────┐
|
|
│ Auth.getToken('pb-user') │ ← CODE RETRIEVES TOKEN
|
|
└────────────┬─────────────────────┘
|
|
│
|
|
│ Calls: localStorage.getItem('auth:pb-user')
|
|
│ Returns: 'eyJhbG...' or null
|
|
│
|
|
┌────────────▼──────────────────────┐
|
|
│ Application Uses Token │
|
|
│ (API calls, authenticated │
|
|
│ requests, etc.) │
|
|
└──────────────────────────────────┘
|
|
|
|
================================================================================
|
|
IMPLEMENTATION GOTCHAS & KNOWN ISSUES
|
|
================================================================================
|
|
|
|
GOTCHA 1: STORAGE KEY MISMATCH
|
|
Issue: auth.ts and auth-universal.js use DIFFERENT storage keys
|
|
- auth.ts: 'auth:pb-user'
|
|
- auth-universal.js: 'pbUserToken'
|
|
Impact: If you use both files, tokens won't be visible across implementations
|
|
Fix: Standardize on one set of keys
|
|
|
|
────────────────────────────────────────────────────────────────────────────
|
|
|
|
GOTCHA 2: POCKETBASE NEVER USED
|
|
Issue: initPocketBase() creates instance but it's never actually used
|
|
- Stored in this.pbInstance but no methods call it
|
|
- No token refresh logic
|
|
- No authentication flows
|
|
Impact: PocketBase initialization is pointless
|
|
Fix: Either remove it or implement actual PocketBase auth flows
|
|
|
|
────────────────────────────────────────────────────────────────────────────
|
|
|
|
GOTCHA 3: PLAINTEXT TOKEN STORAGE
|
|
Issue: Tokens stored in plain text in localStorage
|
|
- Accessible to any JavaScript on the page
|
|
- Vulnerable to XSS attacks
|
|
- Session-persistent (no expiry tracking)
|
|
Impact: Not suitable for highly sensitive credentials
|
|
Fix: For production, implement HTTP-only cookies via backend
|
|
|
|
────────────────────────────────────────────────────────────────────────────
|
|
|
|
GOTCHA 4: UNUSED STATE VARIABLES (auth-universal.js)
|
|
Issue: Variables defined but never used:
|
|
- popup (for OAuth, not implemented)
|
|
- agentCreds, superuserCreds (storage, not implemented)
|
|
Impact: Code is confusing, suggests incomplete refactoring
|
|
Fix: Remove unused variables or implement their intended functionality
|
|
|
|
────────────────────────────────────────────────────────────────────────────
|
|
|
|
GOTCHA 5: NO PATTERN VALIDATION
|
|
Issue: parsePattern() doesn't validate that parsed strings are actual TokenTypes
|
|
- 'pb' gets parsed as 'pb' but valid types are ['pb-user', 'pb-agent']
|
|
- Calling Auth.getToken('pb') will fail (not a valid TokenType)
|
|
Impact: Configuration can silently set invalid patterns
|
|
Fix: Validate pattern strings against valid TokenType list
|
|
|
|
────────────────────────────────────────────────────────────────────────────
|
|
|
|
GOTCHA 6: NO TOKEN EXPIRY TRACKING
|
|
Issue: Module stores tokens but doesn't track expiration
|
|
- No way to know if token is expired
|
|
- No automatic refresh logic
|
|
Impact: Stale/expired tokens can be used in API calls
|
|
Fix: Implement expiration tracking and refresh logic (noted as future enhancement)
|
|
|
|
────────────────────────────────────────────────────────────────────────────
|
|
|
|
GOTCHA 7: NO ERROR BOUNDARIES
|
|
Issue: If localStorage is disabled/unavailable, getToken/setToken fail silently
|
|
- Try/catch not implemented
|
|
- No error logging
|
|
Impact: Hard to debug issues with storage failures
|
|
Fix: Add error handling and logging
|
|
|
|
================================================================================
|
|
USAGE PATTERNS: WHEN TOKENS ARE ACQUIRED & USED
|
|
================================================================================
|
|
|
|
PATTERN 1: USER CREDENTIALS LOGIN (PocketBase)
|
|
───────────────────────────────────────────────
|
|
|
|
Timeline:
|
|
1. User enters email/password
|
|
2. Frontend code calls: pb.collection('users').authWithPassword(email, pwd)
|
|
3. PocketBase returns: { token: 'eyJhbG...', user: {...} }
|
|
4. Frontend calls: Auth.setToken('pb-user', response.token)
|
|
5. Token stored in: localStorage['auth:pb-user'] = 'eyJhbG...'
|
|
6. Later, to use token: const token = Auth.getToken('pb-user')
|
|
7. In API headers: { 'Authorization': `Bearer ${token}` }
|
|
|
|
WHEN IS TOKEN ACQUIRED: During user login
|
|
WHERE IS TOKEN ACQUIRED: From PocketBase SDK response
|
|
WHERE IS IT STORED: localStorage under key 'auth:pb-user'
|
|
WHERE IS IT RETRIEVED: Via Auth.getToken('pb-user') when needed
|
|
|
|
────────────────────────────────────────────────────────────────────────────
|
|
|
|
PATTERN 2: SERVICE ACCOUNT AUTHENTICATION (PocketBase)
|
|
────────────────────────────────────────────────────────
|
|
|
|
Timeline:
|
|
1. Backend has service account credentials (email/password)
|
|
2. Backend authenticates: pb.collection('_superusers').authWithPassword(...)
|
|
3. Backend receives token and stores in Auth.setToken('pb-agent', token)
|
|
4. Frontend retrieves: Auth.getToken('pb-agent')
|
|
5. Used for server-to-server operations
|
|
|
|
WHEN IS TOKEN ACQUIRED: During backend service startup
|
|
WHERE IS TOKEN ACQUIRED: From PocketBase SDK (backend context)
|
|
WHERE IS IT STORED: localStorage['auth:pb-agent']
|
|
WHERE IS IT RETRIEVED: Via Auth.getToken('pb-agent')
|
|
|
|
────────────────────────────────────────────────────────────────────────────
|
|
|
|
PATTERN 3: MICROSOFT GRAPH DELEGATED TOKEN
|
|
─────────────────────────────────────────────
|
|
|
|
Timeline:
|
|
1. User initiates OAuth sign-in via Microsoft
|
|
2. MSAL library handles OAuth flow
|
|
3. MSAL returns: { accessToken: 'eyJ0eXAi...', expiresIn: 3600, ... }
|
|
4. Code stores: Auth.setToken('graph-user', response.accessToken)
|
|
5. Token stored in: localStorage['auth:graph-user']
|
|
6. Used in Graph API calls: fetch('https://graph.microsoft.com/v1.0/me', ...)
|
|
|
|
WHEN IS TOKEN ACQUIRED: During OAuth flow completion
|
|
WHERE IS TOKEN ACQUIRED: From MSAL authentication library
|
|
WHERE IS IT STORED: localStorage['auth:graph-user']
|
|
WHERE IS IT RETRIEVED: Via Auth.getToken('graph-user')
|
|
|
|
────────────────────────────────────────────────────────────────────────────
|
|
|
|
PATTERN 4: MICROSOFT GRAPH APP-ONLY TOKEN (Service Principal)
|
|
──────────────────────────────────────────────────────────────
|
|
|
|
Timeline:
|
|
1. Backend authenticates as service principal (not user)
|
|
2. Uses client credentials flow (clientId + clientSecret)
|
|
3. Azure AD returns: { access_token: 'eyJ0eXAi...', expires_in: 3600 }
|
|
4. Code stores: Auth.setToken('graph-agent', response.access_token)
|
|
5. Token stored in: localStorage['auth:graph-agent']
|
|
6. Used for app-to-app operations
|
|
|
|
WHEN IS TOKEN ACQUIRED: During service principal auth
|
|
WHERE IS TOKEN ACQUIRED: From Azure AD token endpoint
|
|
WHERE IS IT STORED: localStorage['auth:graph-agent']
|
|
WHERE IS IT RETRIEVED: Via Auth.getToken('graph-agent')
|
|
|
|
================================================================================
|
|
SUMMARY: QUICK REFERENCE
|
|
================================================================================
|
|
|
|
TOKENS ACQUIRED BY: External authentication systems (not this module)
|
|
TOKENS STORED BY: Auth.setToken() → localStorage
|
|
TOKENS RETRIEVED BY: Auth.getToken() → returns string or null
|
|
|
|
STORAGE LOCATION: Browser localStorage
|
|
STORAGE KEYS:
|
|
- 'auth:pb-user' (auth.ts version)
|
|
- 'auth:pb-agent' (auth.ts version)
|
|
- 'auth:graph-user' (auth.ts version)
|
|
- 'auth:graph-agent' (auth.ts version)
|
|
- 'pbUserToken' (auth-universal.js version)
|
|
- 'pbAgentToken' (auth-universal.js version)
|
|
- 'graphUserToken' (auth-universal.js version)
|
|
- 'graphAgentToken' (auth-universal.js version)
|
|
|
|
PUBLIC API:
|
|
await Auth.configure(pattern, config?) Setup module
|
|
Auth.getToken(type: TokenType) Retrieve token (returns string|null)
|
|
Auth.setToken(type: TokenType, token) Store token
|
|
Auth.clearToken(type: TokenType) Remove one token
|
|
Auth.clearAllTokens() Remove all tokens
|
|
Auth.isConfigured() Check if ready
|
|
Auth.getEnabledTypes() Get active token types
|
|
|
|
SECURITY CONCERN: Plaintext localStorage
|
|
- Not suitable for highly sensitive credentials
|
|
- Vulnerable to XSS
|
|
- Production: use HTTP-only cookies on backend
|
|
|
|
MAIN IMPLEMENTATION FILE: auth.ts (TypeScript)
|
|
BROWSER VERSION: auth-universal.js (JavaScript)
|
|
TEST PAGE: auth-test.html (manual testing)
|
|
|
|
================================================================================
|
|
END OF AUTH FOLDER ANALYSIS
|
|
================================================================================
|