66 StyleSheet ,
77 Text ,
88 Alert ,
9+ Linking ,
910} from 'react-native' ;
1011import { RouteProp , NavigationProp } from '@react-navigation/native' ;
1112import { jwtDecode } from 'jwt-decode' ;
@@ -16,7 +17,6 @@ import UserInfo from '../../components/UserInfo';
1617import { User , Credentials , ApiCredentials } from 'react-native-auth0' ;
1718import type { ClassDemoStackParamList } from '../../navigation/ClassDemoNavigator' ;
1819import LabeledInput from '../../components/LabeledInput' ;
19- import config from '../../auth0-configuration' ;
2020import Result from '../../components/Result' ;
2121
2222type ProfileRouteProp = RouteProp < ClassDemoStackParamList , 'ClassProfile' > ;
@@ -31,6 +31,7 @@ interface State {
3131 result : Credentials | ApiCredentials | object | boolean | null ;
3232 error : Error | null ;
3333 audience : string ;
34+ webAppUrl : string ;
3435}
3536
3637class ClassProfileScreen extends Component < Props , State > {
@@ -41,7 +42,8 @@ class ClassProfileScreen extends Component<Props, State> {
4142 user,
4243 result : null ,
4344 error : null ,
44- audience : config . audience ,
45+ audience : '' ,
46+ webAppUrl : 'https://your-web-app.com/login' ,
4547 } ;
4648 }
4749
@@ -74,7 +76,7 @@ class ClassProfileScreen extends Component<Props, State> {
7476 } ;
7577
7678 render ( ) {
77- const { user, result, error, audience } = this . state ;
79+ const { user, result, error, audience, webAppUrl } = this . state ;
7880 const { accessToken } = this . props . route . params . credentials ;
7981
8082 return (
@@ -143,6 +145,65 @@ class ClassProfileScreen extends Component<Props, State> {
143145 />
144146 </ Section >
145147
148+ < Section title = "Native to Web SSO (Early Access)" >
149+ < Text style = { styles . description } >
150+ Exchange your refresh token for a Session Transfer Token to enable
151+ seamless SSO to your web application.
152+ </ Text >
153+ < LabeledInput
154+ label = "Web App URL"
155+ value = { webAppUrl }
156+ onChangeText = { ( text ) => this . setState ( { webAppUrl : text } ) }
157+ autoCapitalize = "none"
158+ placeholder = "https://your-web-app.com/login"
159+ />
160+ < Button
161+ onPress = { ( ) =>
162+ this . runTest (
163+ ( ) => auth0 . credentialsManager . getSSOCredentials ( ) ,
164+ 'Get SSO Credentials'
165+ )
166+ }
167+ title = "credentialsManager.getSSOCredentials()"
168+ />
169+ < Button
170+ onPress = { async ( ) => {
171+ try {
172+ this . setState ( { error : null } ) ;
173+ const ssoCredentials =
174+ await auth0 . credentialsManager . getSSOCredentials ( ) ;
175+ this . setState ( { result : ssoCredentials } ) ;
176+
177+ // Open web app with session transfer token
178+ const url = `${ webAppUrl } ?session_transfer_token=${ ssoCredentials . sessionTransferToken } ` ;
179+
180+ Alert . alert (
181+ 'Open Web App' ,
182+ `Open ${ webAppUrl } with session transfer token?` ,
183+ [
184+ { text : 'Cancel' , style : 'cancel' } ,
185+ {
186+ text : 'Open' ,
187+ onPress : async ( ) => {
188+ const supported = await Linking . canOpenURL ( url ) ;
189+ if ( supported ) {
190+ await Linking . openURL ( url ) ;
191+ } else {
192+ Alert . alert ( 'Error' , `Cannot open URL: ${ url } ` ) ;
193+ }
194+ } ,
195+ } ,
196+ ]
197+ ) ;
198+ } catch ( e ) {
199+ this . setState ( { error : e as Error } ) ;
200+ }
201+ } }
202+ title = "Get SSO Credentials & Open Web App"
203+ style = { styles . primaryButton }
204+ />
205+ </ Section >
206+
146207 < Section title = "Navigation & Logout" >
147208 < Button
148209 onPress = { ( ) =>
@@ -188,8 +249,10 @@ const styles = StyleSheet.create({
188249 } ,
189250 sectionTitle : { fontSize : 18 , fontWeight : 'bold' , marginBottom : 12 } ,
190251 buttonGroup : { gap : 10 } ,
252+ description : { fontSize : 14 , color : '#757575' , marginBottom : 10 } ,
191253 destructiveButton : { backgroundColor : '#424242' } ,
192254 secondaryButton : { backgroundColor : '#FF9800' } ,
255+ primaryButton : { backgroundColor : '#4CAF50' } ,
193256} ) ;
194257
195258export default ClassProfileScreen ;
0 commit comments