Created
September 10, 2016 16:29
-
-
Save NelsonBrandao/5923166f3635776b8d640bf921e34942 to your computer and use it in GitHub Desktop.
React Native Example (Login Screen + Session Service + OAuth)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | |
</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, | |
} | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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', | |
} | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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