Bearer Storage
In bearer mode, the client needs somewhere to store the refresh token. The TokenStorage interface lets you plug in any storage mechanism.
TokenStorage Interface
Section titled “TokenStorage Interface”interface TokenStorage {
get(): Promise<string | null>;
set(token: string): Promise<void>;
clear(): Promise<void>;
} interface TokenStorage {
get(): Promise<string | null>;
set(token: string): Promise<void>;
clear(): Promise<void>;
} Examples
Section titled “Examples”localStorage (Web)
Section titled “localStorage (Web)”const auth = createAuthClient({
baseUrl: '/auth',
tokenMode: 'bearer',
tokenStorage: {
get: async () => localStorage.getItem('refresh_token'),
set: async (token) => localStorage.setItem('refresh_token', token),
clear: async () => localStorage.removeItem('refresh_token'),
},
}); const auth = createAuthClient({
baseUrl: '/auth',
tokenMode: 'bearer',
tokenStorage: {
get: async () => localStorage.getItem('refresh_token'),
set: async (token) => localStorage.setItem('refresh_token', token),
clear: async () => localStorage.removeItem('refresh_token'),
},
}); expo-secure-store (React Native)
Section titled “expo-secure-store (React Native)”import * as SecureStore from 'expo-secure-store';
const auth = createAuthClient({
baseUrl: 'https://api.example.com/auth',
tokenMode: 'bearer',
tokenStorage: {
get: () => SecureStore.getItemAsync('refresh_token'),
set: (token) => SecureStore.setItemAsync('refresh_token', token),
clear: () => SecureStore.deleteItemAsync('refresh_token'),
},
}); import * as SecureStore from 'expo-secure-store';
const auth = createAuthClient({
baseUrl: 'https://api.example.com/auth',
tokenMode: 'bearer',
tokenStorage: {
get: () => SecureStore.getItemAsync('refresh_token'),
set: (token) => SecureStore.setItemAsync('refresh_token', token),
clear: () => SecureStore.deleteItemAsync('refresh_token'),
},
}); react-native-keychain
Section titled “react-native-keychain”import * as Keychain from 'react-native-keychain';
const auth = createAuthClient({
baseUrl: 'https://api.example.com/auth',
tokenMode: 'bearer',
tokenStorage: {
get: async () => {
const creds = await Keychain.getGenericPassword();
return creds ? creds.password : null;
},
set: (token) => Keychain.setGenericPassword('authfort', token),
clear: () => Keychain.resetGenericPassword().then(() => {}),
},
}); import * as Keychain from 'react-native-keychain';
const auth = createAuthClient({
baseUrl: 'https://api.example.com/auth',
tokenMode: 'bearer',
tokenStorage: {
get: async () => {
const creds = await Keychain.getGenericPassword();
return creds ? creds.password : null;
},
set: (token) => Keychain.setGenericPassword('authfort', token),
clear: () => Keychain.resetGenericPassword().then(() => {}),
},
}); In-Memory (Testing)
Section titled “In-Memory (Testing)”let token: string | null = null;
const auth = createAuthClient({
baseUrl: '/auth',
tokenMode: 'bearer',
tokenStorage: {
get: async () => token,
set: async (t) => { token = t; },
clear: async () => { token = null; },
},
}); let token: string | null = null;
const auth = createAuthClient({
baseUrl: '/auth',
tokenMode: 'bearer',
tokenStorage: {
get: async () => token,
set: async (t) => { token = t; },
clear: async () => { token = null; },
},
}); Security Notes
Section titled “Security Notes”- Never use localStorage in production for sensitive tokens if XSS is a concern.
localStorageis accessible to any JavaScript on the page. - For web apps, cookie mode is more secure since HttpOnly cookies are not accessible via JavaScript.
- For mobile apps, use platform-specific secure storage (Keychain on iOS, Keystore on Android).
- The access token is always stored in memory only — never persisted. Only the refresh token uses
TokenStorage.