diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index d5f9412e..cec6f8d7 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - A0Auth0 (5.1.0): + - A0Auth0 (5.2.1): - Auth0 (= 2.14) - boost - DoubleConversion @@ -2778,7 +2778,7 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/yoga" SPEC CHECKSUMS: - A0Auth0: 022a85f2093860dcbf9e5337946f6cda5780de4d + A0Auth0: 9253099fae9372f663f89abbf5d02a6b36faf45c Auth0: 022dda235af8a664a4faf9e7b60b063b5bc08373 boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb diff --git a/example/src/screens/class-based/ClassLogin.tsx b/example/src/screens/class-based/ClassLogin.tsx index e49b63cc..8a9bd8e8 100644 --- a/example/src/screens/class-based/ClassLogin.tsx +++ b/example/src/screens/class-based/ClassLogin.tsx @@ -9,6 +9,7 @@ import Button from '../../components/Button'; import Header from '../../components/Header'; import Result from '../../components/Result'; import type { ClassDemoStackParamList } from '../../navigation/ClassDemoNavigator'; +import config from '../../auth0-configuration'; type NavigationProp = StackNavigationProp< ClassDemoStackParamList, @@ -24,7 +25,10 @@ const ClassLoginScreen = () => { setLoading(true); setError(null); try { - const credentials = await auth0.webAuth.authorize(); + const credentials = await auth0.webAuth.authorize({ + scope: 'openid profile email offline_access', + audience: `https://${config.domain}/api/v2/`, + }); // On success, we save the credentials and navigate to the profile screen. await auth0.credentialsManager.saveCredentials(credentials); navigation.replace('ClassProfile', { credentials }); diff --git a/example/src/screens/class-based/ClassProfile.tsx b/example/src/screens/class-based/ClassProfile.tsx index 744c6cc8..483a9de3 100644 --- a/example/src/screens/class-based/ClassProfile.tsx +++ b/example/src/screens/class-based/ClassProfile.tsx @@ -6,6 +6,7 @@ import { StyleSheet, Text, Alert, + Linking, } from 'react-native'; import { RouteProp, NavigationProp } from '@react-navigation/native'; import { jwtDecode } from 'jwt-decode'; @@ -16,7 +17,6 @@ import UserInfo from '../../components/UserInfo'; import { User, Credentials, ApiCredentials } from 'react-native-auth0'; import type { ClassDemoStackParamList } from '../../navigation/ClassDemoNavigator'; import LabeledInput from '../../components/LabeledInput'; -import config from '../../auth0-configuration'; import Result from '../../components/Result'; type ProfileRouteProp = RouteProp; @@ -31,6 +31,7 @@ interface State { result: Credentials | ApiCredentials | object | boolean | null; error: Error | null; audience: string; + webAppUrl: string; } class ClassProfileScreen extends Component { @@ -41,7 +42,8 @@ class ClassProfileScreen extends Component { user, result: null, error: null, - audience: config.audience, + audience: '', + webAppUrl: 'https://your-web-app.com/login', }; } @@ -74,7 +76,7 @@ class ClassProfileScreen extends Component { }; render() { - const { user, result, error, audience } = this.state; + const { user, result, error, audience, webAppUrl } = this.state; const { accessToken } = this.props.route.params.credentials; return ( @@ -143,6 +145,65 @@ class ClassProfileScreen extends Component { /> +
+ + Exchange your refresh token for a Session Transfer Token to enable + seamless SSO to your web application. + + this.setState({ webAppUrl: text })} + autoCapitalize="none" + placeholder="https://your-web-app.com/login" + /> +
+
+ +
+ + Exchange your refresh token for a Session Transfer Token to enable + seamless SSO to your web application. + + +
); @@ -147,8 +209,10 @@ const styles = StyleSheet.create({ }, sectionTitle: { fontSize: 18, fontWeight: 'bold', marginBottom: 12 }, buttonGroup: { gap: 10 }, + description: { fontSize: 14, color: '#757575', marginBottom: 10 }, destructiveButton: { backgroundColor: '#424242' }, secondaryButton: { backgroundColor: '#FF9800' }, + primaryButton: { backgroundColor: '#4CAF50' }, }); export default CredentialsScreen; diff --git a/example/src/screens/hooks/Home.tsx b/example/src/screens/hooks/Home.tsx index ad065c12..351c347f 100644 --- a/example/src/screens/hooks/Home.tsx +++ b/example/src/screens/hooks/Home.tsx @@ -12,6 +12,7 @@ import Button from '../../components/Button'; import Header from '../../components/Header'; import LabeledInput from '../../components/LabeledInput'; import Result from '../../components/Result'; +import config from '../../auth0-configuration'; const HomeScreen = () => { const { @@ -30,7 +31,10 @@ const HomeScreen = () => { const onLogin = async () => { try { - await authorize(); + await authorize({ + scope: 'openid profile email offline_access', + audience: `https://${config.domain}/api/v2/`, + }); } catch (e) { console.log('Login error: ', e); } diff --git a/ios/NativeBridge.swift b/ios/NativeBridge.swift index a2858c05..c95e19f5 100644 --- a/ios/NativeBridge.swift +++ b/ios/NativeBridge.swift @@ -244,19 +244,18 @@ public class NativeBridge: NSObject { } @objc public func getSSOCredentials(parameters: [String: Any], headers: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { - credentialsManager.ssoCredentials(parameters: parameters, headers: headers) { result in + let stringHeaders = headers.compactMapValues { $0 as? String } + credentialsManager.ssoCredentials(parameters: parameters, headers: stringHeaders) { result in switch result { case .success(let ssoCredentials): var response: [String: Any] = [ "sessionTransferToken": ssoCredentials.sessionTransferToken, - "tokenType": ssoCredentials.tokenType, - "expiresIn": ssoCredentials.expiresIn + "tokenType": ssoCredentials.issuedTokenType, + "expiresIn": ssoCredentials.expiresIn, + "idToken": ssoCredentials.idToken ] // Add optional fields if present - if let idToken = ssoCredentials.idToken { - response["idToken"] = idToken - } if let refreshToken = ssoCredentials.refreshToken { response["refreshToken"] = refreshToken }