@onairos/react-native
v4.5.9
Published
Onairos React Native SDK for social media authentication and AI model training
Readme
Onairos React Native SDK
A React Native SDK for integrating Onairos authentication and AI model training into your mobile applications. This package provides a complete solution for social media platform connection, secure authentication, and AI model training.
Features
Approval in the installed Onairos app
Both OnairosButton and Onairos accept deviceApproval:
deviceApproval={{
applicationId: 'YOUR_REGISTERED_APPLICATION_ID',
redirectUri: 'your-app://onairos-callback',
appName: 'Your app',
confirmations: ['basic', 'personality', 'preferences'],
exchange: body => exchangeThroughYourBackend(body),
}}Register the exact return URI for that application and backend environment. On iOS,
add onairos to LSApplicationQueriesSchemes and register your callback scheme;
on Android, declare the onairos package-visibility intent query and callback
intent filter. Install/link react-native-keychain and react-native-get-random-values.
The host must continue forwarding incoming URLs to React Native Linking.
The SDK shows permission choices with Deny/Approve, opens Onairos after Approve,
then shows Approved only after a verified code exchange. If Onairos is not
available, the normal in-SDK onboarding flow continues. Omit deviceApproval
to test only the in-SDK flow.
exchange must send the PKCE exchange body to your own authenticated backend,
which calls Onairos and returns the exchanged response unchanged (including
state, token, and authorizedData). Never embed a backend client secret in
the consumer app. Returning to the app alone is not proof of approval.
The entry component's autoFetch and inferenceData also apply to the handoff.
Approved public profile and stored traits appear separately in
result.apiResponse.publicProfile and result.apiResponse.traits. Preferences
need items in inferenceData (or a backend preset); missing input does not block
trait retrieval. Check apiResponse.dataFetch for partial data. Raw-memory access
still requires backend eligibility and explicit consent. autoFetch={false}
returns the verified grant without fetching data. Cold-start callbacks require
mounting the configured SDK entry component when the host app starts.
- Universal onboarding flow with multi-platform support
- Multi-platform OAuth authentication (Pinterest, YouTube, LinkedIn, Gmail, Reddit)
- Real-time AI model training with Socket.io integration
- Secure credential management with biometric authentication
- PIN-based security with validation and encryption
- Deep linking support for OAuth callbacks
- Email verification and account management
- Existing user detection and data confirmation
- Background training optimization
- Comprehensive error handling and retry logic
- Haptic feedback integration
- Customizable UI components
- Full TypeScript support
Installation
npm install @onairos/react-native
# or
yarn add @onairos/react-native🎯 Example App
A complete example app is available in the example/ directory demonstrating real-world SDK integration:
cd example
npm install
npm run ios # or npm run androidThe example app showcases:
- ✅ SDK initialization and configuration
- ✅ OnairosButton component integration
- ✅ WelcomeScreen component usage
- ✅ Custom styling options
- ✅ JWT token handling and user data extraction
- ✅ Error handling and debugging
See example/README.md for detailed setup instructions.
TypeScript Support
The package includes full TypeScript declarations. Import types directly:
import { OnairosButton, OnairosCredentials, PlatformConfig } from '@onairos/react-native';
// Type your component props
const MyComponent: React.FC<{ credentials: OnairosCredentials }> = ({ credentials }) => {
// Your component code
};
// Type your handlers
const handleResolved = (apiUrl: string, accessToken: string, loginDetails: any) => {
console.log('Authentication successful:', { apiUrl, accessToken, loginDetails });
};Required Dependencies
The package requires the following dependencies:
# Core dependencies
yarn add @gorhom/bottom-sheet react-native-reanimated react-native-gesture-handler react-native-safe-area-context
# Authentication dependencies
yarn add react-native-webview react-native-keychain
# UI dependencies
yarn add react-native-vector-icons
# Network and encryption
yarn add @react-native-community/netinfo react-native-rsa-native react-native-crypto-jsiOS Setup
- Install pods:
cd ios && pod install- Add the following to your
Info.plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<!-- <string>onairosreact</string> -->
<string>onairosanime</string>
</array>
</dict>
</array>
<!-- Add for biometric authentication -->
<key>NSFaceIDUsageDescription</key>
<string>We use Face ID to securely access your Onairos account</string>- Configure your OAuth providers in the project settings and register the callback URLs.
Android Setup
- Add the following to your
android/app/src/main/AndroidManifest.xml:
<activity>
<!-- ... -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- <data android:scheme="onairosreact" /> -->
<data android:scheme="onairosanime" />
</intent-filter>
</activity>- Add biometric permissions:
<uses-permission android:name="android.permission.USE_BIOMETRIC" />Usage
📖 Quick Integration Guide - Start here for immediate copy-paste setup!
📖 For comprehensive usage examples in both JavaScript and TypeScript, see USAGE_EXAMPLES.md
Important: Setup Portal Host
For modals and overlays to appear properly, you must wrap your app with the PortalHost component:
import { PortalHost } from '@onairos/react-native';
export default function App() {
return (
<PortalHost>
{/* Your app content goes here */}
<MainNavigator />
</PortalHost>
);
}Basic Button Integration
- Import and initialize the SDK:
import { OnairosButton, initializeApiKey } from '@onairos/react-native';
// Initialize once at app startup
await initializeApiKey({ apiKey: 'YOUR_API_KEY' });- Use the component in your app:
export default function App() {
const handleComplete = (result) => {
console.log('API URL:', result.apiUrl);
console.log('Token:', result.token);
console.log('User data:', result.apiResponse);
console.log('Authorized data:', result.authorizedData);
// authorizedData = { basic: true, personality: true, preferences: true, ... }
};
return (
<View style={styles.container}>
<OnairosButton
AppName="YourApp"
autoFetch={true}
onComplete={handleComplete}
requestData={{
personality: {
name: 'Personality Traits',
description: 'Your personality profile',
},
preferences: {
name: 'Content Analysis',
description: 'Inference and sentiment',
},
}}
/>
</View>
);
}External Auth Token Support
If your app already handles authentication, pass the user JWT to SDK APIs:
import { setUserToken, clearUserToken } from '@onairos/react-native';
// After your app login succeeds
await setUserToken(userJwtToken);
// Later, when user logs out
await clearUserToken();Security-migrated backend routes (/sendModel, /updateAccountInfo, /inferenceUsername) now require this user JWT and ignore username fields sent in request bodies.
requestData Configuration
The requestData prop controls which consent options appear on the DataRequest screen.
Valid keys:
| Key | Description | When Shown |
|-----|-------------|------------|
| basic | Basic profile info | Always shown |
| personality | Personality traits (LLM profile) | If included |
| preferences | Inference/sentiment (ML model) | If included |
| rawMemories | Raw LLM conversation data | If included AND LLM connected |
Supported formats:
// Object format (full control)
requestData={{
personality: { name: 'Personality', description: '...' },
preferences: { name: 'Content Analysis', description: '...' },
}}
// Array format (uses SDK default descriptions)
requestData={['personality', 'preferences']}Note: If requestData is not provided, only "Basic Profile" is shown and a warning is logged.
Initialize OAuth Service
Add this to your app's entry point to handle deep linking for OAuth:
import { initializeOAuthService } from '@onairos/react-native';
// In your app's entry point
useEffect(() => {
// Set up OAuth deep linking
initializeOAuthService();
// Clean up when component unmounts
return () => {
cleanupOAuthService();
};
}, []);Working with Secure Storage
import { storeCredentials, getCredentials, hasCredentials } from '@onairos/react-native';
// Check if user has stored credentials
const checkAuth = async () => {
const hasExisting = await hasCredentials();
if (hasExisting) {
// Get credentials with biometric authentication
const credentials = await getCredentials({
useBiometrics: true,
biometricPrompt: {
title: 'Authenticate to continue',
subtitle: 'Please verify your identity'
}
});
if (credentials) {
// User is authenticated
console.log('User authenticated:', credentials.username);
}
} else {
// Redirect to onboarding flow
setShowOnboarding(true);
}
};API Reference
Main Components
OnairosButton
The main entry point for Onairos authentication with full training flow support.
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| AppName | string | Yes | Your application name |
| requestData | object/array | Yes | Consent options to show (see below) |
| onComplete | function | Yes | Callback with OnairosResult object |
| autoFetch | boolean | No | Auto-fetch approved data after consent (default: true) |
| backgroundLoadData | boolean | No | Skip SDK training UI and return training metadata for host-side handling (default: false) |
| trainingScreenMode | 'mock' | 'fast' | 'real' | 'none' | No | Training UI behavior. Defaults to fast, or none when backgroundLoadData=true |
| appIcon | ImageSource | No | Your app icon for onboarding UI |
| buttonType | 'circle' | 'pill' | No | Button style (default: 'circle') |
| color | string | No | Button color (default: #00BFA5) |
| debug | boolean | No | Enable debug mode (default: false) |
requestData keys: basic (always shown), personality, preferences, rawMemories
onComplete(result) is the primary completion callback. onResolved(apiUrl, token, userData) is still supported for older integrations, but new code should use onComplete.
When autoFetch=false, the SDK returns apiUrl, token, consent/authorization metadata, and training metadata so the host app can fetch final data itself.
OnairosResult:
{
apiUrl: string;
token: string;
userData: object;
apiResponse?: object; // If autoFetch=true
authorizedData?: object; // What user consented to
training?: { ready: boolean; statusUrl?: string; pollIntervalMs?: number };
}UniversalOnboarding
The universal onboarding flow component.
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| visible | boolean | Yes | Whether the onboarding is visible |
| onClose | function | Yes | Callback when onboarding is closed |
| AppName | string | Yes | Your application name |
| requestData | object/array | Yes | Consent options: basic, personality, preferences, rawMemories |
| onComplete | function | Yes | Callback with (apiUrl, token, userData) |
| autoFetch | boolean | No | Auto-fetch approved data after consent (default: true) |
| backgroundLoadData | boolean | No | Skip SDK training UI and return training metadata for host-side handling (default: false) |
| trainingScreenMode | 'mock' | 'fast' | 'real' | 'none' | No | Training UI behavior. Defaults to fast, or none when backgroundLoadData=true |
| debug | boolean | No | Enable debug mode (default: false) |
TrainingModal
Email authentication and training progress modal.
| Prop | Type | Required | Description | |------|------|----------|-------------| | visible | boolean | Yes | Whether the modal is visible | | onCancel | function | Yes | Callback when modal is cancelled | | onComplete | function | Yes | Callback when training is complete | | modelKey | string | No | Model key for training | | username | string | No | Username for training | | isPrimaryAuth | boolean | No | Whether this is primary authentication | | autoFocusEmailInput | boolean | No | Auto-focus email input on show |
WelcomeScreen
New welcome flow component with modern UI.
| Prop | Type | Required | Description | |------|------|----------|-------------| | visible | boolean | Yes | Whether the screen is visible | | onClose | function | Yes | Callback when screen is closed | | onComplete | function | Yes | Callback when flow is complete |
Overlay
Data request overlay component.
| Prop | Type | Required | Description | |------|------|----------|-------------| | visible | boolean | Yes | Whether the overlay is visible | | onClose | function | Yes | Callback when overlay is closed | | onAccept | function | Yes | Callback when request is accepted | | AppName | string | Yes | Your application name | | requestData | object | Yes | Data being requested | | biometricType | 'FaceID' | 'TouchID' | 'BiometricID' | No | Type of biometric auth to use |
Utility Functions
Secure Storage
storeCredentials(credentials, options): Store credentials securelygetCredentials(options): Retrieve credentials with optional biometric authhasCredentials(): Check if user has stored credentialsdeleteCredentials(): Delete stored credentialsupdateCredentials(updates, options): Update specific fields in credentialsgenerateDeviceUsername(): Generate a device-specific unique usernameverifyCredentials(credentials): Verify if credentials are valid
OAuth Service
connectPlatform(platform): Initiate OAuth flow for a specific platformdisconnectPlatform(platform, credentials): Disconnect a platforminitializeOAuthService(): Initialize OAuth service handlerscleanupOAuthService(): Clean up OAuth service handlersstorePlatformConnection(platform, connectionData, credentials): Store platform connection
API Communication
validateCredentials(username, options): Validate user credentials with the APIcreateAccount(credentials, options): Create a new user accountauthenticate(credentials, options): Authenticate with the API using credentialsrefreshToken(refreshToken, options): Refresh authentication tokengetPlatformData(accessToken, platform, options): Get user's connected platform datagetUserProfile(accessToken, options): Get user profile informationupdatePlatformConnections(accessToken, platforms, options): Update user platform connections
Development and Testing
Native import regressions
Run npm run test:imports before changing native ChatGPT/Claude import, raw-memory delivery, or authentication handling. The suite uses synthetic data and local HTTP servers; it needs no simulator, provider account, API key, or AWS access. It includes real 35-second downloads to catch accidental reuse of the short polling timeout.
The same command runs in GitHub Actions on pull requests and pushes to master/dev, and before SDK publishing. The backend repository has its own npm run test:imports contract/privacy suite. These checks complement live provider smoke tests; they do not test provider UI changes or deployed infrastructure.
Setup Development Environment
- Clone the repository:
git clone https://github.com/onairos/onairos-react-native.git
cd onairos-react-native- Install dependencies:
yarn install- Run the typecheck:
yarn typecheckBuilding the Package
npm run build:allTesting with a Local App
- Link the package locally:
# In your package directory
yarn link
# In your app directory
yarn link @onairos/react-native- Run your app and test the integration.
Troubleshooting
OAuth Callback Issues
- Ensure your deep link schemes are properly configured in both iOS and Android
- Check that the callback URLs match what's registered with your OAuth providers
- Ensure all required permissions are enabled in your app configurations
Biometric Authentication Issues
- Ensure proper permissions are set in Info.plist and AndroidManifest.xml
- Test on physical devices as simulators may not support all biometric features
- For iOS, ensure that Face ID/Touch ID is enabled and set up on the device
Platform Specific Issues
iOS
- For keychain issues, check that the Keychain Sharing capability is enabled
- Ensure the bundle identifier is consistent with your OAuth configuration
Android
- For deep linking issues, check the androidManifest.xml configuration
- Ensure that biometric hardware is available on test devices
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
MIT
Bundled SDK typography
The mobile SDK ships DM Sans and Instrument Serif, matching the web SDK. Native autolinking registers the fonts without modifying the host app's global text styles. After updating this package, run your normal iOS pod installation and rebuild the native app (Android also requires a rebuild). Existing installations without the native module keep their system-font fallback until rebuilt. Existing globalThis.onairosFontFamilies overrides still take precedence when configured before importing the SDK.
The fonts and their SIL Open Font License notices are included under typography/fonts/.
Design parity preview
The repository example has a Design parity preview button in debug builds. It uses the compiled package's real screens with sample data, including sign-in, code entry, connections, secret code, permissions, and training. Preview callbacks do not authenticate, upload data, or store a PIN. Use the screen controls to inspect loading and error states where supported. The actual authentication and biometric flows must be tested separately.
Run npm run build:dev, then the example's existing local SDK workflow on port 8082. Run npm run test:design for consent interaction regression checks (requires the example's development dependencies).
Ephemeral ChatGPT and Claude imports (React Native)
<OnairosButton
AppName="My App"
apiKey={developerApiKey}
rawMemoriesOnly
allowedPlatforms={['chatgpt', 'claude']}
requestData={['basic', 'rawMemories']}
onComplete={result => setSources(result.ephemeralPayloads ?? [])}
/>This native Smart Filter, Files, and ephemeral multi-connector flow is enabled only by rawMemoriesOnly={true}. Omitting it or setting it to false retains the existing profile connector, storage, and training flow; rawMemoriesOffered or requesting raw-memory consent alone does not activate the native importer. The developer key must have backend raw-memory access. Users sign in inside a private WebView, select topics, then approve Raw Memories. Raw-only mode skips training, uploads, and persistent SDK storage. The callback has no fetch URL; keep its ephemeralPayloads in host memory and clear it when finished. Native import supports up to 100 conversations per connector, local topic grouping, explicit title-phrase exclusions, and optional file contents. Connect ChatGPT and Claude sequentially in one session; ephemeralPayloads and platformData retain both. The singular ephemeralPayload remains available for a single source. Files are off by default, capped at 1 MB each and 4 MB per connector, and returned in conversation.files with imported/unavailable/too_large/limit_reached statuses. Imported file data is text or base64; signed download URLs and provider credentials never leave the WebView. Saved memories and custom instructions are not imported. See the native import contract.
Host-verified email
Pass preVerifiedEmail?: string | null to OnairosButton, Onairos, or UniversalOnboarding when your app has already verified the user's email:
<OnairosButton AppName="My App" preVerifiedEmail={verifiedUser.email} onComplete={handleComplete} />After SDK initialization, Get Started submits that email to the pre-verified auth endpoint. The backend decides whether it can issue a session or requires an email code. Connector permissions, PIN requirements, and sharing consent still apply. A different email entered by the user takes the normal verification path. Null/invalid values use normal sign-in. With this prop, the button uses UniversalOnboarding even if useNewWelcomeFlow is enabled. The programmatic options type also accepts the prop, but that existing helper does not mount a modal; use the component/ref API for a rendered flow.
This is an email string, not a JWT or a boolean. Supply only an email verified by your host app; do not use it as a generic email-prefill field. The local backend's policy can differ from another deployed version. No no-OTP guarantee is made for existing accounts.
