A production-ready React Native authentication SDK powered by Firebase. Built with TypeScript, offering both pre-built UI components and headless hooks for complete flexibility.
- Email/Password Authentication - Built-in validation and error handling
- Pre-built UI Components - Beautiful, customizable auth screens out of the box
- Headless Hooks - Full control with
useAuth()for custom implementations - Social Login Support - Google and Apple Sign-In (iOS only for Apple)
- Persistent Sessions - Configurable session management (local/memory)
- TypeScript First - Full type safety and IntelliSense support
- Zero Configuration - Works with minimal setup
- Expo & Bare React Native - Compatible with both workflows
- Node.js v18 or higher
- React Native v0.70+
- Expo SDK 49+ (Recommended)
npm install rn-swiftauth-sdkFor Expo projects:
npx expo install rn-swiftauth-sdknpm install firebase @react-native-async-storage/async-storage react-native-safe-area-contextFor Expo:
npx expo install firebase @react-native-async-storage/async-storage react-native-safe-area-contextGoogle Sign-In:
npm install @react-native-google-signin/google-signinApple Sign-In (iOS only):
npm install @invertase/react-native-apple-authenticationInstall iOS CocoaPods:
cd ios && pod install && cd ..- Go to Firebase Console
- Create a new project or select existing one
- Register a Web App (click the
</>icon) - Copy the
firebaseConfigobject
- Navigate to Authentication > Sign-in method
- Enable Email/Password
- (Optional) Enable Google and/or Apple for social login
Android:
- Register an Android app in Firebase Console
- Download
google-services.jsonand place inandroid/app/ - Add to
android/build.gradle:classpath 'com.google.gms:google-services:4.3.15' - Add to
android/app/build.gradle:apply plugin: 'com.google.gms.google-services'
iOS:
- Register an iOS app in Firebase Console
- Download
GoogleService-Info.plistand place in project root (Expo) orios/YourAppName/(Bare) - Update
app.json:{ "expo": { "ios": { "googleServicesFile": "./GoogleService-Info.plist", "bundleIdentifier": "com.yourcompany.yourapp" } } }
For detailed Firebase setup instructions, see the Firebase documentation.
import React from 'react';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { AuthProvider, AuthScreen, useAuth } from 'rn-swiftauth-sdk';
const firebaseConfig = {
apiKey: "AIzaSyD-Your-Actual-Key",
authDomain: "your-project.firebaseapp.com",
projectId: "your-project-id",
storageBucket: "your-project.appspot.com",
messagingSenderId: "123456789",
appId: "1:123456789:web:abcdef"
};
const MainNavigation = () => {
const { user } = useAuth();
return user ? <HomeScreen user={user} /> : <AuthScreen />;
};
export default function App() {
return (
<SafeAreaProvider>
<AuthProvider config={firebaseConfig}>
<MainNavigation />
</AuthProvider>
</SafeAreaProvider>
);
}const firebaseConfig = {
apiKey: "AIzaSyD-Your-Actual-Key",
authDomain: "your-project.firebaseapp.com",
projectId: "your-project-id",
storageBucket: "your-project.appspot.com",
messagingSenderId: "123456789",
appId: "1:123456789:web:abcdef",
// Enable social login
enableGoogle: true,
enableApple: true, // iOS only
// Required for Google Sign-In
googleWebClientId: "YOUR-CLIENT-ID.apps.googleusercontent.com",
};Wraps your app and provides authentication context.
| Prop | Type | Required | Description |
|---|---|---|---|
| config | AuthConfig | Yes | Firebase configuration object |
| children | ReactNode | Yes | Your app components |
Access authentication state and methods.
const {
user, // Current user object or null
status, // AuthStatus enum
error, // Last error object or null
isLoading, // Boolean loading state
signInWithEmail, // Sign in method
signUpWithEmail, // Sign up method
signOut, // Sign out method
clearError // Clear error state
} = useAuth();| Method | Signature | Description |
|---|---|---|
signInWithEmail |
(options: {email, password}) => Promise<void> |
Sign in existing user |
signUpWithEmail |
(options: {email, password}) => Promise<void> |
Create new account |
signOut |
() => Promise<void> |
Log out current user |
clearError |
() => void |
Clear error state |
<AuthScreen
styles={{
container: { backgroundColor: '#1a1a1a' },
title: { color: '#ffffff', fontSize: 30, fontWeight: '800' },
subtitle: { color: '#cccccc' },
input: {
backgroundColor: '#333333',
color: '#ffffff',
borderColor: '#555555'
},
button: { backgroundColor: '#FFD700' },
buttonText: { color: '#000000', fontWeight: 'bold' }
}}
/>
---
## 🔐 Password Management
The **SwiftAuth SDK** includes built-in support for **password recovery flows** using **Firebase’s email-based password reset mechanism**.
---
### ✉️ Sending a Reset Email
The `sendPasswordReset(email)` function sends a password reset link to the user’s email address.
#### Method Signature
```ts
sendPasswordReset: (email: string) => Promise<void>import React, { useState } from 'react';
import { View, TextInput, Button, Alert, Text } from 'react-native';
import { useAuth } from 'rn-swiftauth-sdk';
export const ForgotPasswordScreen = () => {
const [email, setEmail] = useState('');
const { sendPasswordReset, isLoading, error } = useAuth();
const handleReset = async () => {
if (!email) {
Alert.alert("Error", "Please enter your email address.");
return;
}
try {
await sendPasswordReset(email);
Alert.alert("Success", "Password reset link sent! Check your email.");
} catch (err) {
// Errors are automatically handled by the global `error` state,
// but can also be caught locally for custom logic.
console.error("Reset failed:", err);
}
};
return (
<View>
<TextInput
placeholder="Enter your email"
value={email}
onChangeText={setEmail}
autoCapitalize="none"
keyboardType="email-address"
/>
<Button
title={isLoading ? "Sending..." : "Reset Password"}
onPress={handleReset}
disabled={isLoading}
/>
{error && <Text style={{ color: 'red' }}>{error.message}</Text>}
</View>
);
};The error handling system includes specific exceptions for password reset flows.
| Exception Class | Error Code | User Message |
|---|---|---|
UserNotFoundException |
auth/user-not-found |
"No account found with this email. Please check the email address." |
InvalidEmailException |
auth/invalid-email |
"The email address is badly formatted." |
Errors are exposed through the global error state returned by useAuth() and can also be handled locally using try/catch.
You can integrate password recovery into custom login forms by toggling a “Forgot Password” mode using the headless hook.
const { sendPasswordReset } = useAuth();
const onForgotPasswordPress = async (email: string) => {
await sendPasswordReset(email);
// Show success feedback to the user
};This allows you to fully control your UI while leveraging SwiftAuth’s secure password reset flow.
If you want, I can also:
- Add UX flow diagrams
- Add Firebase setup prerequisites
- Document rate limits & edge cases
- Align tone with the rest of your SDK README
Just tell me 👍
---
## Error Handling
SwiftAuth provides a comprehensive error handling system with custom exceptions that map Firebase errors to user-friendly messages.
### Custom Exception Classes
All errors extend the base `AuthException` class and include:
- `code`: Machine-readable error code
- `message`: User-friendly error message
- `timestamp`: When the error occurred
- `originalError`: The underlying Firebase error (optional)
- `toJSON()`: Serialize for logging/debugging
### Supported Exceptions
| Exception Class | Error Code | User Message |
|-----------------|------------|--------------|
| `InvalidCredentialsException` | `auth/invalid-credentials` | "Invalid email or password. Please check your credentials and try again." |
| `UserNotFoundException` | `auth/user-not-found` | "No account found with this email. Please sign up first." |
| `EmailAlreadyInUseException` | `auth/email-already-in-use` | "This email is already registered. Please sign in or use a different email." |
| `WeakPasswordException` | `auth/weak-password` | "Password is too weak. Please use at least 6 characters with a mix of letters and numbers." |
| `TokenExpiredException` | `auth/token-expired` | "Your session has expired. Please sign in again." |
| `NetworkException` | `auth/network-error` | "Network error. Please check your internet connection and try again." |
| `GoogleSignInCancelledException` | `auth/google-sign-in-cancelled` | "Google Sign-In was cancelled." |
| `AppleSignInCancelledException` | `auth/apple-sign-in-cancelled` | "Apple Sign-In was cancelled." |
| `AppleSignInNotSupportedException` | `auth/apple-sign-in-not-supported` | "Apple Sign-In is only available on iOS 13+ devices." |
| `GooglePlayServicesUnavailableException` | `auth/google-play-services-unavailable` | "Google Play Services are not available. Please update Google Play Services." |
| `ConfigurationException` | `auth/configuration-error` | Custom message based on configuration issue |
| `UnknownAuthException` | `auth/unknown` | "An unexpected error occurred." |
### Basic Error Display
```typescript
import { useAuth } from 'rn-swiftauth-sdk';
const LoginScreen = () => {
const { error, clearError } = useAuth();
return (
<View>
{error && (
<View style={styles.errorContainer}>
<Text style={styles.errorText}>{error.message}</Text>
<Button title="Dismiss" onPress={clearError} />
</View>
)}
</View>
);
};
import {
useAuth,
InvalidCredentialsException,
EmailAlreadyInUseException,
NetworkException
} from 'rn-swiftauth-sdk';
const SignUpScreen = () => {
const { signUpWithEmail } = useAuth();
const handleSignUp = async () => {
try {
await signUpWithEmail({ email, password });
} catch (error) {
if (error instanceof EmailAlreadyInUseException) {
Alert.alert(
"Account Exists",
"Would you like to sign in instead?",
[
{ text: "Cancel", style: "cancel" },
{ text: "Sign In", onPress: () => navigation.navigate('SignIn') }
]
);
} else if (error instanceof NetworkException) {
Alert.alert("Connection Issue", "Please check your internet and try again.");
} else if (error instanceof InvalidCredentialsException) {
Alert.alert("Invalid Input", "Please check your email and password.");
} else {
Alert.alert("Error", error.message);
}
}
};
return <Button title="Sign Up" onPress={handleSignUp} />;
};For advanced use cases, access the raw Firebase error:
const { error } = useAuth();
useEffect(() => {
if (error?.originalError) {
console.log('Firebase Error Code:', error.originalError.code);
console.log('Firebase Error Message:', error.originalError.message);
// Custom handling for specific Firebase codes
if (error.originalError.code === 'auth/requires-recent-login') {
showReauthenticationPrompt();
}
}
}, [error]);const { error } = useAuth();
useEffect(() => {
if (error) {
// Log full error details (includes timestamp, code, original error)
console.log('Auth Error:', JSON.stringify(error.toJSON(), null, 2));
// Send to error tracking service (e.g., Sentry)
logErrorToService(error.toJSON());
}
}, [error]);import { useAuth } from 'rn-swiftauth-sdk';
const ErrorBoundary = ({ children }) => {
const { error, clearError } = useAuth();
if (error) {
return (
<View style={styles.errorScreen}>
<Text style={styles.errorTitle}>Oops!</Text>
<Text style={styles.errorMessage}>{error.message}</Text>
<Text style={styles.errorCode}>Error Code: {error.code}</Text>
<Button title="Try Again" onPress={clearError} />
</View>
);
}
return <>{children}</>;
};const config = {
...firebaseConfig,
persistence: 'local' // User stays logged in
};const config = {
...firebaseConfig,
persistence: 'memory' // User logged out when app closes
};The SDK exposes a secure Firebase ID Token (user.token) for backend authentication.
import { useAuth } from 'rn-swiftauth-sdk';
const UserProfile = () => {
const { user } = useAuth();
const fetchPrivateData = async () => {
if (!user?.token) return;
try {
const response = await fetch('https://your-api.com/profile', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${user.token}`
}
});
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Request failed:', error);
}
};
return <Button title="Get Profile" onPress={fetchPrivateData} />;
};const admin = require('firebase-admin');
// Middleware to verify Firebase ID token
const verifyToken = async (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(401).send('Unauthorized');
}
const idToken = authHeader.split('Bearer ')[1];
try {
const decodedToken = await admin.auth().verifyIdToken(idToken);
req.user = decodedToken;
next();
} catch (error) {
res.status(403).send('Invalid Token');
}
};
// Protected route example
app.get('/profile', verifyToken, (req, res) => {
res.json({ userId: req.user.uid, email: req.user.email });
});Check out our example implementation:
# Clone the repository
git clone https://github.com/allcodez/Auth-SDK_Stage8
# Navigate to example app
cd Auth-SDK_Stage8/swiftauth-example
# Install dependencies
npm install
# Start the app
npx expo startWe welcome contributions! See CONTRIBUTING.md for guidelines.
MIT License - see LICENSE file for detailss.
- Issues: GitHub Issues
- NPM Package: rn-swiftauth-sdk
- Documentation: Full Docs