Recently Apple has employed a stance on social login that WKWebView is not secure enough. Instead we must use SafariViewController which is available to us through react-native-InAppBrowser-reborn.
First, the imports and some basic formatting:
import React from ‘react’;
Import { View, SafeAreaView, Text, TouchableOpacity, Linking } from ‘react-native’;
import InAppBrowser from 'react-native-inappbrowser-reborn’;
Import { Auth } from ‘aws-amplify’;
import { CognitoAuth } from "amazon-cognito-auth-js";
const settings = {
container: {
style: {
flex: 1,
backgroundColor: '#631D76',
justifyContent: 'center',
alignItems: 'center'
}
},
button: {
style: {
borderWidth: 2,
borderColor: '#832161',
borderRadius: 10,
width: '80%',
height: 50,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#832161',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5
}
},
buttonText: {
style: {
color: 'white'
}
},
title: {
style: {
color: 'white',
fontSize: 28,
fontWeight: '600',
textAlign: 'center',
marginBottom: 150
}
}
};
class SignInScreen extends React.Component {
render() {
return (
<SafeAreaView {...settings.container}>
<View>
<Text {...settings.title}>Cognito Authentication Example</Text>
</View>
<TouchableOpacity {...settings.button}>
<Text {...settings.buttonText}>I'm a button</Text>
</TouchableOpacity>
</SafeAreaView>
);
}
}
export default SignInScreen;
Add the same to SignInScreen.android.js.
With the design of our SignInScreens done, lets add them to our App.js file and configure the screens and AWS to handle our authentication. First, clear out the App.js file and add the SignInScreen so it looks like this:
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
*/
import React from "react";
import SignInScreen from "./src/Screens/SignInScreen";
import awsConfiguration from './src/Utils/awsConfiguration';
import Amplify from 'aws-amplify';
const App = () => {
return <SignInScreen />;
};
export default App;
Note that I added two new imports to the file. We must configure amplify to use our AWS configuration object. Above the return block add:
Amplify.configure(awsConfiguration);
Now I’m going to implement a simple switch for unauthenticated and authenticated users. Replace the App function to look like:
class App extends React.Component {
state = {
authenticated: false
};
render() {
if (this.state.authenticated) {
return <Authenticated />;
}
return <SignInScreen toAuthenticated={() => this.setState({ authenticated: true })} />;
}
}
Here we’ve created a state field named authenticated and based on this property we are displaying one of two files. Because we currently only have a SignInScreen this is set to false. The other thing to note here is that we have passed a prop to SignInScreen which sets authenticated to true.
Let’s actually handle the authentication. As mentioned previously, Apple now requires us to use SafariViewController and in turn react-native-InAppBrowser-reborn. We will focus on iOS as Android can be achieved in a number of different manners.
In SignInScreen.ios.js add the code to handle redirection to the app. We will need an App URL Scheme. To set this up:
- Edit the Info.plist
- Add ‘URL types’ as a row
- Add a row to ‘URL types’ called ‘URL Identifier’. This is usually the same as your bundle id
- Add another row to ‘URL types’ called ‘URL Schemes’.
- Add an item as the name of your scheme. E.g. myapp will be used as myapp://
First we need to handle the redirection. This is done in componentDidMount() by adding listeners for AppState changes.
componentDidMount() {
// this handles the case where the app is closed and is launched via Universal Linking.
Linking.getInitialURL()
.then(url => {
console.log("I am in the get initial url");
if (url) {
Alert.alert("GET INIT URL", `initial url ${url}`);
console.log("GET INIT URL", `initial url ${url}`);
// this.resetStackToProperRoute(url);
}
})
.catch(e => {});
// This listener handles the case where the app is woken up from the Universal or Deep Linking
Linking.addEventListener("url", this.appWokeUp);
}
componentWillUnmount() {
Linking.removeEventListener("url", this.appWokeUp);
}
We now require a number of different functions to handle sign in and redirection from cognito. First of all, we are going to open the Hosted UI directly on Facebook’s log in screen. Add this code to the onPress of the TouchableOpacity.