Skip to content

Instantly share code, notes, and snippets.

@NelsonBrandao
Created September 10, 2016 16:29
Show Gist options
  • Save NelsonBrandao/5923166f3635776b8d640bf921e34942 to your computer and use it in GitHub Desktop.
Save NelsonBrandao/5923166f3635776b8d640bf921e34942 to your computer and use it in GitHub Desktop.
React Native Example (Login Screen + Session Service + OAuth)
import React, { Component, PropTypes } from 'react';
import {
View,
Text,
Platform,
StyleSheet,
TouchableHighlight,
TouchableNativeFeedback
} from 'react-native';
export default class Button extends Component {
static propTypes = {
onClick: PropTypes.func,
style: Text.propTypes.style,
};
render () {
let TouchableElement = TouchableHighlight;
if (Platform.OS === 'android') {
TouchableElement = TouchableNativeFeedback;
}
return (
<TouchableElement
onPress={this.props.onClick}
>
<View style={styles.button}>
<Text style={styles.text}>
{this.props.text}
</Text>
</View>
</TouchableElement>
);
}
}
const styles = StyleSheet.create({
button: {
padding: 10,
width: 250,
marginBottom: 10,
backgroundColor: 'powderblue',
},
text: {
fontWeight: 'bold',
textAlign: 'center',
}
});
import React, { Component } from 'react';
import {
AppRegistry,
Navigator
} from 'react-native';
import Login from './src/containers/Login';
import Session from './src/services/Session';
class authWhite extends Component {
constructor () {
super();
this.session = new Session();
this.session.init();
}
renderScene (route, navigator) {
return React.createElement(
route.component,
{
...this.props,
...route.passProps,
route,
navigator
}
);
}
render() {
return (
<Navigator
style={{ flex:1 }}
initialRoute={{ component: Login }}
renderScene={ this.renderScene } />
);
}
}
AppRegistry.registerComponent('authWhite', () => authWhite);
import React, { Component } from 'react';
import {
StyleSheet,
View,
Text,
TextInput,
} from 'react-native';
import Home from '../containers/Home';
import Button from '../components/Button';
import OAuth from '../services/OAuth';
import Session from '../services/Session';
export default class Login extends Component {
constructor () {
super();
this.oauth = new OAuth();
this.session = new Session();
this.state = { showLoginForm: false };
}
onAuthFacebookClicked () {
this.oauth.authWithFacebook();
}
onAuthGoogleClicked () {
this.oauth.authWithGoogle();
}
onAuthEmailClicked () {
this.setState({ showLoginForm: true });
}
onLoginClicked () {
this.session.login()
.then(() => {
return this.props.navigator.push({
component: Home
});
});
}
renderBottomSection () {
if (this.state.showLoginForm) {
return this.renderLoginForm();
}
return this.renderLoginButtons();
}
renderLoginButtons () {
return (
<View>
<Button
style={styles.button}
text="Auth with Facebook"
onClick={() => this.onAuthFacebookClicked()}
>
</Button>
<Button
text="Auth with Google"
onClick={() => this.onAuthGoogleClicked()}
>
</Button>
<Button
text="Auth with Email"
onClick={() => this.onAuthEmailClicked()}
>
</Button>
</View>
);
}
renderLoginForm () {
return (
<View>
<Text>
Email
</Text>
<TextInput
style={{height: 40}}
placeholder="Enter Your Email"
onChangeText={(loginEmail) => this.setState({loginEmail})}
/>
<Text>
Password
</Text>
<TextInput
style={{height: 40}}
placeholder="Enter Your Password"
onChangeText={(loginPassword) => this.setState({loginPassword})}
/>
<Button
text="Login"
onClick={() => this.onLoginClicked()}
/>
</View>
);
}
render () {
return (
<View style={styles.container}>
<Text style={styles.title}>
Login Screen
</Text>
{this.renderBottomSection()}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
title: {
fontSize: 35,
textAlign: 'center',
margin: 10,
marginBottom: 50,
}
});
import React, { Component, PropTypes } from 'react';
import {
View,
Text,
Platform,
StyleSheet,
TouchableHighlight,
TouchableNativeFeedback
} from 'react-native';
export default class Button extends Component {
static propTypes = {
onClick: PropTypes.func,
style: Text.propTypes.style,
};
render () {
let TouchableElement = TouchableHighlight;
if (Platform.OS === 'android') {
TouchableElement = TouchableNativeFeedback;
}
return (
<TouchableElement
onPress={this.props.onClick}
>
<View style={styles.button}>
<Text style={styles.text}>
{this.props.text}
</Text>
</View>
</TouchableElement>
);
}
}
const styles = StyleSheet.create({
button: {
padding: 10,
width: 250,
marginBottom: 10,
backgroundColor: 'powderblue',
},
text: {
fontWeight: 'bold',
textAlign: 'center',
}
});
import OAuthManager from 'react-native-oauth';
import config from '../config';
import routes from '../oauthProvidersRoutes';
/**
* @name OAuth
* @description Class to manage all OAuth requests and authentications
*/
export default class OAuth {
constructor () {
this.authManager = new OAuthManager();
this.authManager.configureProviders({
google: {
consumer_key: config.GOOGLE_CONSUMER_KEY,
consumer_secret: config.GOOGLE_CONSUMER_SECRET
},
facebook: {
consumer_key: config.FACEBOOK_CONSUMER_KEY,
consumer_secret: config.FACEBOOK_CONSUMER_SECRET
},
})
}
/**
* @name OAuth#authWithFacebook
* @description Authenticate with facebook. This will ask the user to login
* on facebook and will redirect back to the app.
* @returns {Promise} The promise will be resolved after the user performances
* the authentication.
*/
authWithFacebook () {
return this.authManager.authorizeWithCallbackURL('facebook', config.FACEBOOK_APP_URI);
}
/**
* @name OAuth#authWithGoogle
* @description Authenticate with google. This will ask the user to login
* on google and will redirect back to the app.
* @returns {Promise} The promise will be resolved after the user performances
* the authentication.
*/
authWithGoogle () {
return this.authManager.authorizeWithCallbackURL('google', config.GOOGLE_APP_URI);
}
/**
* @name OAuth#getFacebookUserInfo
* @description Performs an authenticated request to get the facebook profile.
* @returns {Promise} The promise will be resolved with the user profile.
*/
getFacebookUserInfo () {
return this.authManager.makeRequest('facebook', 'get', routes.facebook.PROFILE);
}
/**
* @name OAuth#getGoogleUserInfo
* @description Performs an authenticated request to get the google profile.
* @returns {Promise} The promise will be resolved with the user profile.
*/
getGoogleUserInfo () {
return this.authManager.makeRequest('google', 'get', routes.google.PROFILE);
}
/**
* @name OAuth#makeAuthRequest
* @description Performs an authenticated custom request to the provider API.
* @param {String} provider The provider name to authenticate the request.
* @param {String} method The HTTP method to use.
* @param {String} routeName The route name of the request you want to make.
* The name must exists on the 'oauthProvidersRoutes' file.
* @returns {Promise} The promise will be resolved whe the request returns.
*/
makeAuthRequest (provider, method, routeName) {
return this.authManager.makeRequest(provider, method, routes[provider][routeName]);
}
/**
* @name OAuth#logoutFacebook
* @description Deauthorizes the application from facebook.
* @returns {Promise} The promise will be resolved whe the request returns.
*/
logoutFacebook () {
return this.authManager.deauthorize('facebook');
}
/**
* @name OAuth#logoutGoogle
* @description Deauthorizes the application from facebook.
* @returns {Promise} The promise will be resolved whe the request returns.
*/
logoutGoogle () {
return this.authManager.deauthorize('google');
}
}
import AsyncStorage from 'react-native';
import config from '../config';
import UserRequests from './UserRequests';
const SESSION_KEY = `${config.APP_NAME}/session`.toLowerCase();
/**
* Variable to save the instance so it always
* returns the same class instance, aka singleton.
* @type {Session}
*/
let instance = null;
/**
* @name Session
* @description This will manage all information related
* with the user session and authentication.
*/
export default class Session {
constructor () {
if (!instance) {
instance = this;
}
return instance;
}
/**
* @name Session#init
* @description Initializes the session service. This will attempt
* load the current auth token saved to storage.
*/
init () {
this.userId = null;
return new Promise((resolve, reject) => {
AsyncStorage.getItem(SESSION_KEY, (err, result) => {
if (err) {
return reject();
}
this.authToken = result;
return resolve(this.authToken);
});
});
}
/**
* @name Session#login
* @description Performs a login call to the API to attempt
* to login the user. If the call is successfull it will also
* cache those values reuse the next time the app is open
*/
login (...args) {
return UserRequests.login(...args)
.then((authToken) => {
this.authToken = authToken;
return new Promise((resolve, reject) => {
AsyncStorage.setItem(SESSION_KEY, this.authToken, (err) => {
if (err) {
return reject();
}
return resolve();
});
});
})
}
/**
* @name Session#logout
* @description Performs a logout call to the API and
* removes the cached auth token from the cache
*/
logout () {
return UserRequests.logout()
.finally(() => {
this.authToken = null;
AsyncStorage.removeItem(SESSION_KEY);
});
}
/**
* @name Session#isLoggedIn
* @description Verifies if the user is logged in or not, by
* verifying if there is a auth token present
*/
isLoggedIn () {
if (this.authToken === null) {
return false;
}
return true;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment