Initial commit
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
---
|
||||
title: Manage Auth Tokens Properly
|
||||
impact: CRITICAL
|
||||
impactDescription: Prevents unauthorized access, handles token expiration gracefully
|
||||
tags: authentication, tokens, refresh, security, session
|
||||
---
|
||||
|
||||
## Manage Auth Tokens Properly
|
||||
|
||||
Auth tokens should be refreshed before expiration, validated on critical operations, and properly cleared on logout. The SDK's authStore handles most of this automatically.
|
||||
|
||||
**Incorrect (ignoring token expiration):**
|
||||
|
||||
```javascript
|
||||
// Bad: never checking token validity
|
||||
async function fetchUserData() {
|
||||
// Token might be expired!
|
||||
const records = await pb.collection('posts').getList();
|
||||
return records;
|
||||
}
|
||||
|
||||
// Bad: manually managing tokens
|
||||
let authToken = localStorage.getItem('token');
|
||||
fetch('/api/posts', {
|
||||
headers: { 'Authorization': authToken } // Token might be invalid
|
||||
});
|
||||
```
|
||||
|
||||
**Correct (proper token management):**
|
||||
|
||||
```javascript
|
||||
import PocketBase from 'pocketbase';
|
||||
|
||||
const pb = new PocketBase('http://127.0.0.1:8090');
|
||||
|
||||
// Check token validity before operations
|
||||
async function fetchSecureData() {
|
||||
// authStore.isValid is a client-side check only (JWT expiry parsing).
|
||||
// Always verify server-side with authRefresh() for critical operations.
|
||||
if (!pb.authStore.isValid) {
|
||||
throw new Error('Please log in');
|
||||
}
|
||||
|
||||
return pb.collection('posts').getList();
|
||||
}
|
||||
|
||||
// Refresh token periodically or before expiration
|
||||
async function refreshAuthIfNeeded() {
|
||||
if (!pb.authStore.isValid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// Verifies current token and returns fresh one
|
||||
await pb.collection('users').authRefresh();
|
||||
console.log('Token refreshed');
|
||||
return true;
|
||||
} catch (error) {
|
||||
// Token invalid - user needs to re-authenticate
|
||||
pb.authStore.clear();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-refresh on app initialization
|
||||
async function initializeAuth() {
|
||||
if (pb.authStore.token) {
|
||||
try {
|
||||
await pb.collection('users').authRefresh();
|
||||
} catch {
|
||||
pb.authStore.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Listen for auth changes and handle expiration
|
||||
pb.authStore.onChange((token, record) => {
|
||||
if (!token) {
|
||||
// User logged out or token cleared
|
||||
redirectToLogin();
|
||||
}
|
||||
});
|
||||
|
||||
// Setup periodic refresh (e.g., every 10 minutes)
|
||||
setInterval(async () => {
|
||||
if (pb.authStore.isValid) {
|
||||
try {
|
||||
await pb.collection('users').authRefresh();
|
||||
} catch {
|
||||
pb.authStore.clear();
|
||||
}
|
||||
}
|
||||
}, 10 * 60 * 1000);
|
||||
```
|
||||
|
||||
**SSR / Server-side token handling:**
|
||||
|
||||
```javascript
|
||||
// Server-side: create fresh client per request
|
||||
export async function handleRequest(request) {
|
||||
const pb = new PocketBase('http://127.0.0.1:8090');
|
||||
|
||||
// Load auth from cookie
|
||||
pb.authStore.loadFromCookie(request.headers.get('cookie') || '');
|
||||
|
||||
// Validate and refresh
|
||||
if (pb.authStore.isValid) {
|
||||
try {
|
||||
await pb.collection('users').authRefresh();
|
||||
} catch {
|
||||
pb.authStore.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// ... handle request ...
|
||||
|
||||
// Send updated cookie with secure options
|
||||
const response = new Response();
|
||||
response.headers.set('set-cookie', pb.authStore.exportToCookie({
|
||||
httpOnly: true, // Prevent XSS access to auth token
|
||||
secure: true, // HTTPS only
|
||||
sameSite: 'Lax', // CSRF protection
|
||||
}));
|
||||
return response;
|
||||
}
|
||||
```
|
||||
|
||||
**Token configuration (Admin UI or migration):**
|
||||
|
||||
```javascript
|
||||
// Configure token durations (superuser only)
|
||||
await pb.collections.update('users', {
|
||||
authToken: {
|
||||
duration: 1209600 // 14 days in seconds
|
||||
},
|
||||
verificationToken: {
|
||||
duration: 604800 // 7 days
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Reference: [PocketBase Auth Store](https://pocketbase.io/docs/authentication/)
|
||||
Reference in New Issue
Block a user