@edge-markets/connect-react-native
v1.3.0
Published
React Native SDK for EDGE Connect authentication flow for mobile apps
Readme
@edge-markets/connect-react-native
React Native SDK for EDGE Connect authentication flow for mobile apps.
Features
- 🔐 Secure OAuth 2.0 with PKCE - No client secrets in mobile app
- 📱 Native In-App Browser - Uses SFSafariViewController (iOS) / Chrome Custom Tabs (Android)
- 🔗 Deep Link Support - Seamless callback handling
- ⚛️ React Hooks - Simple, declarative API
- 📊 Event Tracking - Analytics and debugging support
- 🎨 Customizable - Works with your app's flow
Installation
# npm
npm install @edge-markets/connect-react-native react-native-inappbrowser-reborn
# yarn
yarn add @edge-markets/connect-react-native react-native-inappbrowser-reborn
# pnpm
pnpm add @edge-markets/connect-react-native react-native-inappbrowser-reborniOS Setup
cd ios && pod installFor Expo Projects
npx expo install expo-web-browserThe SDK will automatically use expo-web-browser if available.
Quick Start
1. Configure Deep Linking
iOS (Info.plist):
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>Android (AndroidManifest.xml):
<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="myapp" android:host="oauth" android:pathPrefix="/callback" />
</intent-filter>2. Use the Hook
import { useEdgeLink } from '@edge-markets/connect-react-native'
import { Button, Alert } from 'react-native'
function ConnectEdgeButton() {
const { open, isOpen, isSuccess, result, error, reset } = useEdgeLink({
clientId: 'your-client-id',
environment: 'staging',
redirectUri: 'myapp://oauth/callback',
})
// Handle success
React.useEffect(() => {
if (isSuccess && result) {
// Send code to your backend for token exchange
fetch('https://your-api.com/edge/exchange', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
code: result.code,
codeVerifier: result.codeVerifier,
}),
})
.then(res => res.json())
.then(data => {
Alert.alert('Success', 'EdgeBoost connected!')
reset() // Reset for next use
})
.catch(err => {
Alert.alert('Error', 'Failed to connect EdgeBoost')
reset()
})
}
}, [isSuccess, result])
// Handle errors
React.useEffect(() => {
if (error) {
Alert.alert('Error', error.message)
reset()
}
}, [error])
return (
<Button
title={isOpen ? 'Connecting...' : 'Connect EdgeBoost'}
onPress={open}
disabled={isOpen}
/>
)
}API Reference
useEdgeLink(config)
React hook for EdgeLink integration.
Config:
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| clientId | string | ✅ | Your OAuth client ID |
| environment | 'production' \| 'staging' \| 'sandbox' | ✅ | Environment |
| redirectUri | string | ✅ | Deep link URI for callback |
| scopes | EdgeScope[] | ❌ | Requested permissions |
| linkUrl | string | ❌ | Custom Link URL (dev only) |
| useExternalBrowser | boolean | ❌ | Use external browser |
Returns:
| Property | Type | Description |
|----------|------|-------------|
| open | () => Promise<void> | Opens the Link flow |
| close | () => Promise<void> | Closes the Link flow |
| isOpen | boolean | Whether flow is open |
| isSuccess | boolean | Whether flow succeeded |
| isError | boolean | Whether there was an error |
| result | EdgeLinkSuccess \| null | Success result with code |
| error | { code, message } \| null | Error info |
| reset | () => void | Reset state for retry |
EdgeLink Class
For more control, use the class directly:
import { EdgeLink } from '@edge-markets/connect-react-native'
const link = new EdgeLink({
clientId: 'your-client-id',
environment: 'staging',
redirectUri: 'myapp://oauth/callback',
onSuccess: (result) => {
console.log('Auth code:', result.code)
console.log('Code verifier:', result.codeVerifier)
},
onExit: (metadata) => {
if (metadata.error) {
console.error('Error:', metadata.error.message)
} else {
console.log('User closed')
}
},
onEvent: (event) => {
analytics.track('edge_link_event', event)
},
})
// Open the flow
await link.open()
// Later, cleanup
link.destroy()Deep Link Handling
The SDK automatically sets up deep link listeners. If you have custom routing, you can handle links manually:
import { useEdgeLinkHandler } from '@edge-markets/connect-react-native'
import { Linking } from 'react-native'
function App() {
const { handleUrl } = useEdgeLinkHandler({
redirectUri: 'myapp://oauth/callback',
onSuccess: (result) => {
// Handle success
},
onError: (error) => {
// Handle error
},
})
useEffect(() => {
const subscription = Linking.addEventListener('url', ({ url }) => {
if (!handleUrl(url)) {
// Handle other deep links
handleOtherDeepLinks(url)
}
})
return () => subscription.remove()
}, [handleUrl])
return <YourApp />
}Security Considerations
PKCE
The SDK uses PKCE (Proof Key for Code Exchange) to secure the OAuth flow. This prevents authorization code interception attacks without requiring a client secret in the mobile app.
In-App Browser
The SDK uses secure system browsers (SFSafariViewController / Chrome Custom Tabs) instead of WebViews. This is more secure because:
- Cookies are isolated from your app
- Users can verify they're on the real EdgeBoost domain
- Prevents credential theft by malicious apps
Secure Random
For production, install a cryptographic random number generator:
npm install react-native-get-random-valuesThen import it at the top of your entry file:
import 'react-native-get-random-values'Without this, the SDK falls back to less secure random generation and will log a warning.
Backend Integration
The result.code and result.codeVerifier must be sent to your backend for token exchange:
// Your backend (using @edge-markets/connect-node)
import { EdgeConnectServer } from '@edge-markets/connect-node'
const server = new EdgeConnectServer({
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
environment: 'staging',
})
// In your API endpoint
app.post('/edge/exchange', async (req, res) => {
const { code, codeVerifier } = req.body
const tokens = await server.exchangeCode(code, codeVerifier)
// Store tokens securely
await saveTokensForUser(req.user.id, tokens)
res.json({ success: true })
})Troubleshooting
Deep link not working
- Verify your URL scheme is registered in both iOS and Android configs
- Test with
npx uri-scheme open myapp://oauth/callback --iosor--android - Make sure the redirectUri matches exactly (including trailing slashes)
In-app browser not opening
- Install
react-native-inappbrowser-rebornand runpod install - Or for Expo, install
expo-web-browser - The SDK will fall back to external browser if neither is available
"Insecure random" warning
Install and import react-native-get-random-values before any crypto operations.
Comparison with Browser SDK
| Feature | Browser SDK | React Native SDK |
|---------|-------------|------------------|
| Auth UI | Popup window | In-app browser |
| Callback | postMessage | Deep links |
| Crypto | Web Crypto API | Polyfills/native |
| API | EdgeLink class | EdgeLink + hooks |
License
MIT
