Offline-first authentication library for React Native with Guest Mode and JWT support
A production-ready authentication library for React Native that prioritizes offline-first functionality. Built with TypeScript, Zustand, and AsyncStorage.
- Offline-First - Works without internet, syncs when available
- Guest Mode - Let users try your app without registration
- Easy Upgrade - Seamless guest β authenticated account flow
- JWT Support - Standard JWT token management
- Type-Safe - Full TypeScript support with comprehensive types
- Zero Native Code - Pure JavaScript/TypeScript, works with Expo
- Flexible API - Bring your own API implementation
- Tree-Shakeable - Optimized bundle size
npm install @loonylabs/react-native-offline-auth zustand @react-native-async-storage/async-storageor
yarn add @loonylabs/react-native-offline-auth zustand @react-native-async-storage/async-storageThis library requires:
react>= 18.0.0react-native>= 0.70.0zustand>= 4.0.0@react-native-async-storage/async-storage>= 1.17.0
import { AuthProvider } from '@loonylabs/react-native-offline-auth';
import App from './App';
export default function Root() {
return (
<AuthProvider
apiCallbacks={{
login: async (credentials) => {
const response = await fetch('https://api.example.com/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(credentials),
});
return response.json(); // { user, token }
},
register: async (credentials) => {
const response = await fetch('https://api.example.com/auth/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(credentials),
});
return response.json(); // { user, token }
},
validateToken: async (token) => {
const response = await fetch('https://api.example.com/auth/me', {
headers: { Authorization: `Bearer ${token}` },
});
const data = await response.json();
return data.user;
},
}}
>
<App />
</AuthProvider>
);
}import { useAuth } from '@loonylabs/react-native-offline-auth';
function HomeScreen() {
const {
user,
isAuthenticated,
isGuestMode,
login,
logout,
continueAsGuest,
} = useAuth();
if (isGuestMode) {
return <Text>Welcome Guest! π€</Text>;
}
if (isAuthenticated) {
return (
<View>
<Text>Welcome {user.username}! π</Text>
<Button title="Logout" onPress={logout} />
</View>
);
}
return (
<View>
<Button title="Login" onPress={() => login({ email, password })} />
<Button title="Continue as Guest" onPress={continueAsGuest} />
</View>
);
}- Authenticated - User logged in with JWT token
- Guest Mode - User using app without account (local data only)
- Unauthenticated - User needs to login or continue as guest
- App starts immediately with cached credentials
- Token validation happens in background (non-blocking)
- Users stay logged in even when offline
- No forced logout on network errors
function RootNavigator() {
const { isLoading, isAuthenticated, isGuestMode } = useAuth();
if (isLoading) {
return <SplashScreen />;
}
if (isAuthenticated || isGuestMode) {
return <MainApp />;
}
return <AuthScreens />;
}- Getting Started - Step-by-step setup guide
- API Reference - Complete API documentation
- Error Handling - Error handling guide
- Examples - Common use cases and patterns
- Example App - Full working example
Allow users to try your app without registration:
await continueAsGuest();
// User can now use the app with local-only dataConvert guest users to authenticated users:
await upgradeToAccount({
email: '[email protected]',
username: 'newuser',
password: 'securepass123'
});
// Local data is preserved, now synced to cloudUsers stay logged in when offline:
// On app start:
// 1. Load token + user from AsyncStorage (instant)
// 2. Show app immediately
// 3. Validate token in background (when online)
// 4. Update user data if validation succeeds
// 5. Stay logged in even if validation fails (offline)<AuthProvider
apiCallbacks={...}
config={{
// Custom storage keys (optional)
storageKeys: {
token: '@custom_token',
user: '@custom_user',
guestMode: '@custom_guest',
},
// Enable debug logging
debug: true,
// Custom token validator
validateToken: async (token) => {
// Your custom validation logic
return user;
},
// Error callback
onTokenValidationError: (error) => {
console.log('Token validation failed:', error);
},
}}
onReady={() => console.log('Auth initialized')}
>
<App />
</AuthProvider>Fully typed with comprehensive TypeScript definitions:
import type {
User,
AuthState,
LoginCredentials,
RegisterCredentials,
AuthConfig,
} from '@loonylabs/react-native-offline-auth';The library includes test infrastructure:
npm test # Run tests
npm run test:watch # Watch mode
npm run test:coverage # Coverage reportNote: We're actively working on expanding test coverage. Contributions welcome!
βββββββββββββββββββββββββββββββββββββββββββββββ
β React Components β
β (useAuth hook) β
βββββββββββββββββββ¬ββββββββββββββββββββββββββββ
β
βββββββββββββββββββΌββββββββββββββββββββββββββββ
β AuthProvider β
β (Zustand Store + Context) β
βββββββββββββββββββ¬ββββββββββββββββββββββββββββ
β
βββββββββββββββββββΌββββββββββββββββββββββββββββ
β AuthService β
β (Business Logic + Validation) β
βββββββββββββββββββ¬ββββββββββββββββββββββββββββ
β
βββββββββββββββββββΌββββββββββββββββββββββββββββ
β AuthStorage β
β (AsyncStorage Wrapper) β
βββββββββββββββββββββββββββββββββββββββββββββββ
- Use guest mode for better onboarding
- Load auth state on app start
- Handle offline scenarios gracefully
- Validate tokens in background
- Cache user data locally
- Wait for API calls on app start
- Logout users on network errors
- Block UI during token validation
- Store sensitive data beyond JWT token
- Force registration before trying the app
- React Native: 0.70+
- Expo: β Compatible (SDK 47+)
- React Native Web: β Compatible
- iOS: β Tested
- Android: β Tested
Contributions are welcome! Please read our Contributing Guide first.
MIT Β© LoonyLabs
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Built with:
- Zustand - State management
- AsyncStorage - Persistent storage
- TypeScript - Type safety
Made with β€οΈ by Loonylabs