@kokolabs-io/client
v1.0.0
Published
Authentication client for Koko applications with built-in token management, auto-refresh, and localStorage integration
Maintainers
Readme
@kokolabs-io/client
Authentication client for Koko applications with built-in token management, auto-refresh, and localStorage integration.
Features
- Token Management: Automatic access and refresh token storage
- Auto-Refresh: Automatic token refresh before expiration
- localStorage Integration: Persistent token storage in the browser
- Fetch Wrapper: Built-in fetch with automatic auth headers
- Unauthorized Handler: Custom callback for handling 401 responses
- SSO/OAuth Support: Easy integration with OAuth flows
- Type-Safe: Full TypeScript support
Installation
pnpm add @kokolabs-io/clientUsage
Basic Setup
import { createAuthClient } from '@kokolabs-io/client';
const auth = createAuthClient({
authUrl: 'https://your-app.com/auth/login',
refreshUrl: 'https://your-app.com/auth/refresh',
autoRefresh: true,
onUnauthorized: async ({ response, token }) => {
console.log('Unauthorized request detected');
// Handle 401 responses, e.g., redirect to login
window.location.href = '/login';
}
});
// Initialize the client (loads tokens from localStorage)
const { authenticated, token } = auth.init();
if (authenticated) {
console.log('User is authenticated:', token);
} else {
console.log('User is not authenticated');
}Login
// Redirect to login page
auth.login('/dashboard'); // Optional returnTo parameter
// Or use with OAuth/SSO
auth.login(); // Redirects to authUrlLogout
// Logout and redirect
auth.logout({ redirect: true, returnTo: '/' });
// Logout without redirect (just clear tokens)
auth.logout({ redirect: false });Token Management
// Get current access token
const token = auth.getToken();
// Set access token (e.g., after login)
auth.setToken('your-access-token');
// Clear access token
auth.clearToken();
// Get refresh token
const refreshToken = auth.getRefreshToken();
// Set refresh token
auth.setRefreshToken('your-refresh-token');
// Clear refresh token
auth.clearRefreshToken();Token Expiration
// Get token expiration timestamp (in milliseconds)
const expiresAt = auth.getExpiresAtMs();
// Set token expiration
auth.setExpiresAtMs(Date.now() + 3600000); // 1 hour from now
// Check if token is expired
const isExpired = auth.isExpired();
// Check with time skew (default 60 seconds)
const isExpired = auth.isExpired(120000); // 2 minutes skewToken Refresh
// Manually refresh the access token
try {
const result = await auth.refresh();
console.log('New access token:', result.access_token);
console.log('New refresh token:', result.refresh_token);
console.log('Expires in (seconds):', result.expires_in);
} catch (error) {
console.error('Failed to refresh token:', error);
}Authenticated Fetch
The fetch method automatically adds the Authorization header and handles token refresh:
// Make an authenticated request
const response = await auth.fetch('https://api.example.com/user/profile');
const data = await response.json();
// With custom options
const response = await auth.fetch('https://api.example.com/user/profile', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'John Doe' })
});Configuration Options
interface KokoAuthClientConfig {
// Required: URL to redirect to for login
authUrl: string;
// Optional: URL to refresh tokens (if not provided, refresh is disabled)
refreshUrl?: string;
// Optional: localStorage key for access token (default: 'koko_auth_token')
storageKey?: string;
// Optional: localStorage key for refresh token (default: 'koko_auth_refresh_token')
refreshStorageKey?: string;
// Optional: localStorage key for expiration timestamp (default: 'koko_auth_expires_at')
expiresAtKey?: string;
// Optional: Enable automatic token refresh (default: true)
autoRefresh?: boolean;
// Optional: Callback when 401 Unauthorized is received
onUnauthorized?: (ctx: UnauthorizedContext) => void | Promise<void>;
}Complete Example
import { createAuthClient } from '@kokolabs-io/client';
// Create auth client
const auth = createAuthClient({
authUrl: 'https://your-app.com/auth/login',
refreshUrl: 'https://your-app.com/auth/refresh',
storageKey: 'my_app_token',
autoRefresh: true,
onUnauthorized: async ({ response }) => {
// Clear tokens and redirect to login
auth.clearToken();
auth.clearRefreshToken();
window.location.href = '/login?returnTo=' + encodeURIComponent(window.location.pathname);
}
});
// Initialize on app load
const { authenticated } = auth.init();
// Login button handler
document.getElementById('login-btn')?.addEventListener('click', () => {
auth.login(window.location.pathname);
});
// Logout button handler
document.getElementById('logout-btn')?.addEventListener('click', () => {
auth.logout({ redirect: true, returnTo: '/' });
});
// Make authenticated API calls
async function fetchUserProfile() {
try {
const response = await auth.fetch('https://api.example.com/user/profile');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const profile = await response.json();
return profile;
} catch (error) {
console.error('Failed to fetch profile:', error);
throw error;
}
}
// Check authentication before making requests
if (authenticated) {
fetchUserProfile().then(profile => {
console.log('User profile:', profile);
});
} else {
console.log('Please login first');
auth.login();
}API Reference
Class: KokoAuthClient
Methods
init(): { authenticated: boolean; token: string | null }- Initialize and check authentication statuslogin(returnTo?: string): void- Redirect to login pagelogout(options?: { redirect?: boolean; returnTo?: string }): void- Logout usergetToken(): string- Get access tokensetToken(token: string): void- Set access tokenclearToken(): void- Clear access tokengetRefreshToken(): string- Get refresh tokensetRefreshToken(token: string): void- Set refresh tokenclearRefreshToken(): void- Clear refresh tokengetExpiresAtMs(): number- Get token expiration timestampsetExpiresAtMs(ms: number): void- Set token expiration timestampclearExpiresAtMs(): void- Clear token expiration timestampisExpired(skewMs?: number): boolean- Check if token is expiredrefresh(): Promise<{ access_token: string; refresh_token: string; expires_in: number }>- Refresh access tokenfetch(url: string, options?: RequestInit): Promise<Response>- Make authenticated request
Build
Build from root:
pnpm -C .. buildBuild this package only:
pnpm --filter @kokolabs-io/client buildLicense
MIT - Copyright (c) 2026 KokoLabs.io
