Skip to content

Commit cd04065

Browse files
committed
add expo-cng demo app
- having some issues with the expo-cng demo app and the workspace, so we remove it from the workspace entirely right now so it manages its own deps.
1 parent fdb1110 commit cd04065

File tree

16 files changed

+5081
-22
lines changed

16 files changed

+5081
-22
lines changed

app.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"ios": {
3+
"bundleIdentifier": "com.anonymous.rnaa"
4+
}
5+
}

examples/expo-cng/.gitignore

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
2+
3+
# dependencies
4+
node_modules/
5+
6+
/android
7+
/ios
8+
# Expo
9+
.expo/
10+
dist/
11+
web-build/
12+
expo-env.d.ts
13+
14+
# Native
15+
.kotlin/
16+
*.orig.*
17+
*.jks
18+
*.p8
19+
*.p12
20+
*.key
21+
*.mobileprovision
22+
23+
# Metro
24+
.metro-health-check*
25+
26+
# debug
27+
npm-debug.*
28+
yarn-debug.*
29+
yarn-error.*
30+
31+
# macOS
32+
.DS_Store
33+
*.pem
34+
35+
# local env files
36+
.env*.local
37+
38+
# typescript
39+
*.tsbuildinfo

examples/expo-cng/App.tsx

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import React, { useState } from 'react';
2+
import { StatusBar } from 'expo-status-bar';
3+
import { StyleSheet, Text, View, Button, Alert, ScrollView } from 'react-native';
4+
import { authorize, AuthConfiguration, AuthorizeResult } from 'react-native-app-auth';
5+
6+
// Demo configuration using Duende IdentityServer demo
7+
// For production, replace with your OAuth provider details
8+
const config: AuthConfiguration = {
9+
issuer: 'https://demo.duendesoftware.com',
10+
clientId: 'interactive.public',
11+
redirectUrl: 'com.example.expo-cng://oauth',
12+
scopes: ['openid', 'profile', 'email', 'api'],
13+
additionalParameters: {},
14+
useNonce: true,
15+
usePKCE: true,
16+
};
17+
18+
export default function App() {
19+
const [authState, setAuthState] = useState<AuthorizeResult | null>(null);
20+
const [loading, setLoading] = useState<boolean>(false);
21+
22+
const handleAuthorize = async (): Promise<void> => {
23+
try {
24+
setLoading(true);
25+
const result = await authorize(config);
26+
setAuthState(result);
27+
Alert.alert('Success', 'Authentication successful!');
28+
} catch (error) {
29+
console.error('Auth error:', error);
30+
Alert.alert('Error', `Authentication failed: ${(error as Error).message}`);
31+
} finally {
32+
setLoading(false);
33+
}
34+
};
35+
36+
const handleLogout = (): void => {
37+
setAuthState(null);
38+
Alert.alert('Logged out', 'You have been logged out successfully');
39+
};
40+
41+
return (
42+
<ScrollView contentContainerStyle={styles.container}>
43+
<Text style={styles.title}>React Native App Auth - Expo CNG Demo</Text>
44+
45+
<View style={styles.section}>
46+
<Text style={styles.sectionTitle}>Authentication Status</Text>
47+
<Text style={styles.status}>
48+
{authState ? 'Authenticated' : 'Not authenticated'}
49+
</Text>
50+
</View>
51+
52+
{!authState ? (
53+
<Button
54+
title={loading ? 'Authenticating...' : 'Authorize'}
55+
onPress={handleAuthorize}
56+
disabled={loading}
57+
/>
58+
) : (
59+
<View style={styles.section}>
60+
<Text style={styles.sectionTitle}>User Info</Text>
61+
<Text style={styles.info}>Access Token: {authState.accessToken.substring(0, 20)}...</Text>
62+
<Text style={styles.info}>Token Type: {authState.tokenType}</Text>
63+
<Text style={styles.info}>Scopes: {authState.scopes.join(', ')}</Text>
64+
<Button title="Logout" onPress={handleLogout} />
65+
</View>
66+
)}
67+
68+
<View style={styles.section}>
69+
<Text style={styles.sectionTitle}>Plugin Configuration</Text>
70+
<Text style={styles.info}>Redirect URL: {config.redirectUrl}</Text>
71+
<Text style={styles.info}>Issuer: {config.issuer}</Text>
72+
<Text style={styles.info}>Scopes: {config.scopes.join(', ')}</Text>
73+
</View>
74+
75+
<StatusBar style="auto" />
76+
</ScrollView>
77+
);
78+
}
79+
80+
const styles = StyleSheet.create({
81+
container: {
82+
flexGrow: 1,
83+
backgroundColor: '#fff',
84+
alignItems: 'center',
85+
justifyContent: 'center',
86+
padding: 20,
87+
},
88+
title: {
89+
fontSize: 24,
90+
fontWeight: 'bold',
91+
marginBottom: 30,
92+
textAlign: 'center',
93+
},
94+
section: {
95+
marginVertical: 20,
96+
padding: 15,
97+
backgroundColor: '#f5f5f5',
98+
borderRadius: 8,
99+
width: '100%',
100+
},
101+
sectionTitle: {
102+
fontSize: 18,
103+
fontWeight: 'bold',
104+
marginBottom: 10,
105+
},
106+
status: {
107+
fontSize: 16,
108+
color: '#666',
109+
},
110+
info: {
111+
fontSize: 14,
112+
marginBottom: 5,
113+
color: '#666',
114+
},
115+
});

examples/expo-cng/README.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# Expo CNG TypeScript Example for react-native-app-auth
2+
3+
This example demonstrates how to use the `react-native-app-auth` Expo config plugin with Continuous Native Generation (CNG) in a TypeScript project.
4+
5+
## What This Example Tests
6+
7+
1. **Config Plugin Integration**: Validates that the plugin properly configures native projects
8+
2. **TypeScript Support**: Demonstrates full type safety with react-native-app-auth
9+
3. **URL Scheme Configuration**: Tests that OAuth redirect URLs are correctly configured
10+
4. **Platform-specific Setup**: Ensures both iOS and Android native configurations work
11+
5. **CNG Compatibility**: Validates the plugin works with Expo's continuous native generation
12+
13+
## Setup Instructions
14+
15+
### 1. Install Dependencies
16+
17+
From the repository root:
18+
```bash
19+
yarn install
20+
```
21+
22+
### 2. Generate Native Code
23+
24+
Since this is a CNG (Continuous Native Generation) project, you need to generate the native code:
25+
26+
```bash
27+
cd examples/expo-cng
28+
npx expo prebuild
29+
```
30+
31+
This will:
32+
- Generate the `ios/` and `android/` directories
33+
- Apply the react-native-app-auth config plugin
34+
- Configure URL schemes and native project settings
35+
36+
### 3. Run the App
37+
38+
For iOS:
39+
```bash
40+
npx expo run:ios
41+
```
42+
43+
For Android:
44+
```bash
45+
npx expo run:android
46+
```
47+
48+
## TypeScript Benefits
49+
50+
This example showcases:
51+
52+
- **Type-safe Configuration**: `AuthConfiguration` interface ensures correct config
53+
- **Typed Results**: `AuthorizeResult` provides IntelliSense for auth responses
54+
- **Error Handling**: Proper TypeScript error handling with type assertions
55+
- **IDE Support**: Full autocomplete and type checking in development
56+
57+
## What the Plugin Should Configure
58+
59+
### iOS Configuration
60+
- **URL Schemes**: Adds the redirect URL scheme to `Info.plist`
61+
- **Bridging Header**: Configures Objective-C bridging for React Native
62+
- **Build Settings**: Adds necessary Xcode build settings
63+
- **App Delegate**: Configures the app delegate to handle OAuth callbacks
64+
65+
### Android Configuration
66+
- **Manifest Placeholders**: Adds URL scheme handling to `AndroidManifest.xml`
67+
- **Build Gradle**: Configures the app-level build.gradle file
68+
69+
## Validation Steps
70+
71+
To validate the plugin is working correctly:
72+
73+
1. **Check Native Files**: After running `npx expo prebuild`, inspect the generated native files:
74+
- iOS: Check `ios/expocng/Info.plist` for URL schemes containing `com.example.expo-cng`
75+
- Android: Check `android/app/build.gradle` for `appAuthRedirectScheme: 'com.example.expo-cng'`
76+
77+
2. **TypeScript Compilation**: The app should compile without TypeScript errors
78+
79+
3. **Build Verification**: The app should build successfully without manual native configuration
80+
81+
## Troubleshooting
82+
83+
### Plugin Not Applied
84+
If the plugin doesn't seem to be working:
85+
```bash
86+
# Clean and regenerate
87+
npx expo prebuild --clean
88+
```
89+
90+
### TypeScript Errors
91+
If you see TypeScript errors related to react-native-app-auth:
92+
- Ensure the library is properly installed: `yarn install`
93+
- Check that types are imported correctly from the main library
94+
95+
### URL Scheme Issues
96+
The example uses a demo OAuth provider. For production use, configure your own OAuth provider and update the `config` object in `App.tsx`.
97+
98+
### Build Errors
99+
If you encounter build errors:
100+
1. Ensure all dependencies are installed: `yarn install`
101+
2. Clean and rebuild: `npx expo prebuild --clean`
102+
3. Check that the plugin version matches the library version
103+
104+
## Plugin Configuration Options
105+
106+
The plugin accepts these options in `app.json`:
107+
108+
```json
109+
{
110+
"expo": {
111+
"plugins": [
112+
[
113+
"react-native-app-auth",
114+
{
115+
"redirectUrls": ["your-app-scheme://oauth"]
116+
}
117+
]
118+
]
119+
}
120+
}
121+
```
122+
123+
Currently, only `redirectUrls` is configurable. The plugin will automatically set up all necessary native configurations based on this URL scheme.
124+
125+
## TypeScript Types
126+
127+
The example imports and uses these types from react-native-app-auth:
128+
129+
```typescript
130+
import {
131+
authorize,
132+
AuthConfiguration,
133+
AuthorizeResult
134+
} from 'react-native-app-auth';
135+
```
136+
137+
This ensures full type safety throughout the authentication flow.

examples/expo-cng/app.json

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"expo": {
3+
"name": "expo-cng",
4+
"slug": "expo-cng",
5+
"version": "1.0.0",
6+
"orientation": "portrait",
7+
"icon": "./assets/icon.png",
8+
"userInterfaceStyle": "light",
9+
"newArchEnabled": true,
10+
"splash": {
11+
"image": "./assets/splash-icon.png",
12+
"resizeMode": "contain",
13+
"backgroundColor": "#ffffff"
14+
},
15+
"ios": {
16+
"supportsTablet": true,
17+
"bundleIdentifier": "com.anonymous.expocng"
18+
},
19+
"android": {
20+
"adaptiveIcon": {
21+
"foregroundImage": "./assets/adaptive-icon.png",
22+
"backgroundColor": "#ffffff"
23+
},
24+
"edgeToEdgeEnabled": true,
25+
"package": "com.anonymous.expocng"
26+
},
27+
"web": {
28+
"favicon": "./assets/favicon.png"
29+
},
30+
"plugins": [
31+
[
32+
"react-native-app-auth",
33+
{
34+
"redirectUrls": [
35+
"com.example.expo-cng://oauth"
36+
]
37+
}
38+
]
39+
]
40+
}
41+
}
17.1 KB
Loading
1.43 KB
Loading

examples/expo-cng/assets/icon.png

21.9 KB
Loading
17.1 KB
Loading

examples/expo-cng/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { registerRootComponent } from 'expo';
2+
3+
import App from './App';
4+
5+
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
6+
// It also ensures that whether you load the app in Expo Go or in a native build,
7+
// the environment is set up appropriately
8+
registerRootComponent(App);

0 commit comments

Comments
 (0)