@scalekit-sdk/expo
v1.0.0
Published
Official Scalekit SDK for Expo - Simple, secure authentication with OAuth 2.0 + PKCE
Downloads
53
Readme
@scalekit-sdk/expo
Official Scalekit SDK for Expo - Add enterprise-ready authentication to your React Native mobile app in minutes.
✨ Features
- 🔐 OAuth 2.0 with PKCE - Secure authentication flow for mobile apps
- 🚀 3 Lines of Code - Simple, intuitive API
- 🔄 Auto Session Management - Persistent auth across app restarts
- 🏢 Enterprise SSO - SAML, OIDC, and social logins
- 🎯 TypeScript - Full type safety out of the box
- 📱 React Hooks - Modern React patterns
- 🔒 Secure Storage - Tokens stored in device keychain
- ⚡ Zero Config - Automatic deep linking setup
📦 Installation
npm install @scalekit-sdk/expoor
yarn add @scalekit-sdk/expoPeer Dependencies
This SDK requires the following Expo packages (usually already installed in Expo projects):
npx expo install expo-crypto expo-secure-store expo-web-browser🚀 Quick Start
1. Get Your Scalekit Credentials
- Sign up at Scalekit Dashboard
- Create an application
- Note your Environment URL and Client ID
- Add redirect URI:
your-app-scheme://auth/callback
Note: Client Secret is optional when using PKCE-only flow (recommended for mobile apps)
2. Configure Your App
Add the Scalekit plugin to your app.json:
{
"expo": {
"name": "My App",
"scheme": "myapp",
"plugins": [
"@scalekit-sdk/expo"
]
}
}3. Wrap Your App with ScalekitProvider
import { ScalekitProvider } from '@scalekit-sdk/expo';
export default function App() {
return (
<ScalekitProvider
envUrl="https://your-env.scalekit.com"
clientId="your_client_id"
// clientSecret="your_client_secret" // Optional - not required for PKCE-only flow
>
<YourApp />
</ScalekitProvider>
);
}4. Use the useScalekit Hook
import { useScalekit } from '@scalekit-sdk/expo';
import { View, Button, Text } from 'react-native';
function LoginScreen() {
const { login, logout, user, isAuthenticated, isLoading } = useScalekit();
if (isLoading) {
return <Text>Loading...</Text>;
}
if (isAuthenticated) {
return (
<View>
<Text>Welcome, {user?.name}!</Text>
<Button title="Logout" onPress={logout} />
</View>
);
}
return <Button title="Login with Scalekit" onPress={login} />;
}That's it! 🎉 Authentication is now fully integrated.
📚 API Reference
<ScalekitProvider>
Wrap your app with this provider to enable Scalekit authentication.
Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| envUrl | string | ✅ | Your Scalekit environment URL |
| clientId | string | ✅ | Your Scalekit client ID |
| clientSecret | string | ❌ | Your Scalekit client secret (optional for PKCE-only flow) |
| redirectUri | string | ❌ | Custom redirect URI (default: uses app scheme) |
| scopes | string[] | ❌ | OAuth scopes (default: ['openid', 'profile', 'email']) |
| children | ReactNode | ✅ | Your app components |
Example
// PKCE-only flow (recommended for mobile apps)
<ScalekitProvider
envUrl={process.env.EXPO_PUBLIC_SCALEKIT_ENV_URL}
clientId={process.env.EXPO_PUBLIC_SCALEKIT_CLIENT_ID}
scopes={['openid', 'profile', 'email', 'organizations']}
>
<App />
</ScalekitProvider>
// Or with client_secret for additional security (if required by your setup)
<ScalekitProvider
envUrl={process.env.EXPO_PUBLIC_SCALEKIT_ENV_URL}
clientId={process.env.EXPO_PUBLIC_SCALEKIT_CLIENT_ID}
clientSecret={process.env.EXPO_PUBLIC_SCALEKIT_CLIENT_SECRET}
scopes={['openid', 'profile', 'email', 'organizations']}
>
<App />
</ScalekitProvider>useScalekit()
Hook to access authentication state and methods.
Returns
{
// Auth State
isLoading: boolean;
isAuthenticated: boolean;
user: ScalekitUser | null;
tokens: ScalekitTokens | null;
error: string | null;
// Methods
login: (options?: ScalekitLoginOptions) => Promise<void>;
logout: () => Promise<void>;
refreshUser: () => Promise<void>;
getAccessToken: () => Promise<string | null>;
}Example
const {
login,
logout,
user,
isAuthenticated,
isLoading,
error
} = useScalekit();login(options?)
Initiates the OAuth login flow. Opens a browser for user authentication.
Parameters
interface ScalekitLoginOptions {
organizationId?: string; // For B2B/multi-tenant apps
connectionId?: string; // Specific SSO connection
extraParams?: Record<string, string>; // Additional OAuth params
}Examples
// Basic login
await login();
// Login with organization (B2B/Multi-tenant)
await login({ organizationId: 'org_123' });
// Login with specific SSO connection
await login({ connectionId: 'conn_456' });logout()
Logs out the current user and clears all stored session data.
await logout();refreshUser()
Refreshes user information from the stored ID token.
await refreshUser();getAccessToken()
Returns the current access token (useful for API calls).
const token = await getAccessToken();
if (token) {
// Make API call with token
fetch('https://api.example.com/data', {
headers: { Authorization: `Bearer ${token}` }
});
}🎯 Advanced Usage
Environment Variables
Store credentials securely using environment variables:
EXPO_PUBLIC_SCALEKIT_ENV_URL=https://your-env.scalekit.com
EXPO_PUBLIC_SCALEKIT_CLIENT_ID=your_client_id
EXPO_PUBLIC_SCALEKIT_CLIENT_SECRET=your_client_secret<ScalekitProvider
envUrl={process.env.EXPO_PUBLIC_SCALEKIT_ENV_URL!}
clientId={process.env.EXPO_PUBLIC_SCALEKIT_CLIENT_ID!}
clientSecret={process.env.EXPO_PUBLIC_SCALEKIT_CLIENT_SECRET!}
>
<App />
</ScalekitProvider>Protected Routes
Create an auth guard component:
function ProtectedRoute({ children }: { children: React.ReactNode }) {
const { isAuthenticated, isLoading } = useScalekit();
if (isLoading) {
return <LoadingScreen />;
}
if (!isAuthenticated) {
return <LoginScreen />;
}
return <>{children}</>;
}
// Usage
<ProtectedRoute>
<HomeScreen />
</ProtectedRoute>Multi-Tenant / B2B Applications
function OrganizationPicker() {
const { login } = useScalekit();
const [selectedOrg, setSelectedOrg] = useState('');
const handleLogin = () => {
login({ organizationId: selectedOrg });
};
return (
<View>
<Picker
selectedValue={selectedOrg}
onValueChange={setSelectedOrg}
>
<Picker.Item label="Acme Corp" value="org_acme" />
<Picker.Item label="Wayne Enterprises" value="org_wayne" />
</Picker>
<Button title="Login" onPress={handleLogin} />
</View>
);
}Making Authenticated API Calls
function DataFetcher() {
const { getAccessToken } = useScalekit();
const [data, setData] = useState(null);
const fetchData = async () => {
const token = await getAccessToken();
if (!token) {
console.error('No access token available');
return;
}
const response = await fetch('https://api.example.com/user/data', {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
});
const data = await response.json();
setData(data);
};
useEffect(() => {
fetchData();
}, []);
return <View>{/* Render data */}</View>;
}Custom Redirect URI
<ScalekitProvider
envUrl="https://your-env.scalekit.com"
clientId="your_client_id"
clientSecret="your_client_secret"
redirectUri="myapp://auth/callback"
>
<App />
</ScalekitProvider>Important: Make sure the redirect URI matches what's configured in your Scalekit dashboard.
🏗️ TypeScript Support
The SDK is written in TypeScript and provides complete type definitions.
import {
ScalekitUser,
ScalekitTokens,
ScalekitAuthState,
ScalekitLoginOptions
} from '@scalekit-sdk/expo';
const handleLogin = async (options: ScalekitLoginOptions) => {
await login(options);
};
const renderUser = (user: ScalekitUser | null) => {
if (!user) return null;
return <Text>{user.name}</Text>;
};🔧 Configuration
Custom URL Scheme
By default, the SDK uses your app's scheme from app.json. To customize:
{
"expo": {
"scheme": "myapp",
"plugins": [
["@scalekit-sdk/expo", { "scheme": "customscheme" }]
]
}
}OAuth Scopes
<ScalekitProvider
// ... other props
scopes={['openid', 'profile', 'email', 'organizations', 'offline_access']}
>
<App />
</ScalekitProvider>🐛 Troubleshooting
"No redirect URI configured" Error
Make sure your redirect URI in the Scalekit dashboard matches your app's scheme:
- Development:
exp://localhost:8081/--/auth/callback(for Expo Go) - Production:
your-app-scheme://auth/callback
Deep Linking Not Working
Rebuild your app after adding the plugin:
npx expo prebuild --cleanVerify your
app.jsonhas theschemefield:{ "expo": { "scheme": "myapp" } }
Tokens Not Persisting
Expo SecureStore requires the app to be installed (doesn't work in Expo Go on Android). Build a development build:
npx expo run:ios
# or
npx expo run:android📱 Platform Support
- ✅ iOS (13.0+)
- ✅ Android (API 21+)
- ✅ Expo Go (with limitations on Android SecureStore)
- ✅ EAS Build
- ✅ Bare React Native (with Expo modules)
🤝 Contributing
Contributions are welcome! Please see CONTRIBUTING.md for details.
📄 License
MIT © Scalekit Inc.
🔗 Links
💬 Support
- 📧 Email: [email protected]
- 📖 Docs: docs.scalekit.com
Made with ❤️ by Scalekit
