Authentication
OAuth login, token management, and storage configuration.
The SDK uses OAuth 2.0 with a popup-based login flow. Authentication is handled automatically when calling upload(), download(), or downloadContent() — if no valid token exists, the SDK starts the login popup using your configured clientId and scopes.
Auth methods
const upl = new Upl({ clientId: 'your-client-id' });
// Start OAuth popup login
const token = await upl.login();
// Force re-login (clears cached token first)
const freshToken = await upl.forceLogin();
// Clear token and log out
await upl.logout();
// Check auth state
const state = await upl.getUserState(); // { status, token, user }
const user = await upl.getUser(); // UplUser | null
const authed = await upl.isAuthenticated(); // boolean
// Refresh auth state (re-check token validity, reload user)
await upl.refreshUserState();Auth options
Advanced authentication behaviour can be configured via the auth option:
const upl = new Upl({
clientId: 'your-client-id',
auth: {
redirectUri: 'https://myapp.com/callback', // OAuth redirect URI
popupTimeout: 120000, // Popup timeout in ms (default: 120s)
orgId: 'org_abc123', // Organisation ID header
tokenStore: customStore, // Custom token storage
},
});| Option | Type | Default | Description |
|---|---|---|---|
redirectUri | string | — | OAuth redirect URI |
popupTimeout | number | 120000 | Popup timeout in milliseconds |
orgId | string | — | Sets x-xeonr-auth-org-id header on API requests |
tokenStore | TokenStore | BrowserTokenStore | Custom token storage implementation |
Token lifecycle
- Login — OAuth popup opens, user authenticates, token returned via
postMessageor URL fragment - Storage — Token saved to the configured store (localStorage by default)
- Auto-refresh — When a token is within 60 seconds of expiry, the SDK refreshes it via
AuthService.refreshToken - Retry — If an API call returns
Unauthenticated, the SDK attempts a token refresh and retries once before failing
Token storage
By default, tokens are stored in localStorage under the key upl:sdk:{clientId}. You can provide a custom store:
interface TokenStore {
get(): Promise<UplToken | null>;
set(token: UplToken): Promise<void>;
clear(): Promise<void>;
}Built-in stores
BrowserTokenStore (default) — persists to localStorage. Falls back to MemoryTokenStore if localStorage is unavailable.
MemoryTokenStore — in-memory only, cleared on page reload. Useful for ephemeral sessions or environments without localStorage.
import { MemoryTokenStore } from '@xeonr/uploads-sdk/client/token-store';
const upl = new Upl({
clientId: 'your-client-id',
auth: {
tokenStore: new MemoryTokenStore(),
},
});Token type
interface UplToken {
accessToken: string;
refreshToken?: string;
expiresAt?: number; // Unix timestamp in milliseconds
tokenType?: 'Bearer';
}OAuth scopes
The default scopes requested during login are:
['upl:bucket:read', 'upl:uploads:create', 'profile']Override these via the scopes option to request additional permissions:
| Scope | Description |
|---|---|
upl:bucket:read | Read bucket contents |
upl:bucket:manage | Create/modify buckets |
upl:uploads:create | Upload files |
upl:uploads:manage | Modify/delete uploads |
upl:user:read | Read user profile |
upl:admin | Full admin access |
profile | Basic profile info |
offline_access | Offline token (longer-lived refresh token) |
User state
interface UplUserState {
status: 'unauthenticated' | 'authenticated' | 'authenticating';
token: UplToken | null;
user: UplUser | null;
}
interface UplUser {
userId: string;
username: string;
email?: string;
}In React, use the auth object from useUpl() for reactive auth state:
const { auth } = useUpl();
if (auth.loading) return <Spinner />;
if (!auth.isAuthenticated) return <button onClick={() => auth.login()}>Login</button>;
return <span>Hello, {auth.state.user?.username}</span>;