3

I'm trying to write a code for user login and persist it in react-native. I found persist-redux and react navigation lib.

Are they the best libraries for authentication progress? Can i use react navigation instead of persist-redux? Can you suggest me the good tutorial for implementing that?

2
  • Which type of authentication are using in your application? Commented Apr 27, 2019 at 5:08
  • My backend is laravel and i'm using tokens for authentication. but what do you mean about type of authenticatoin? Commented Apr 27, 2019 at 5:20

3 Answers 3

7

DO NOT USE AsyncStorage TO STORE CREDENTIALS!

According to React Native's security overview, AsyncStorage should not be used to store sensitive data as it is unencrypted.

Async Storage is a community-maintained module for React Native that provides an asynchronous, unencrypted, key-value store. Async Storage is not shared between apps: every app has its own sandbox environment and has no access to data from other apps.

Async Storage dos and don'ts table

So what should I use?

You can use any of these possibilities:

Source: https://reactnative.dev/docs/security

Sign up to request clarification or add additional context in comments.

Comments

1

You can save authentication token which you get while login to AsyncStorage and check if using some api to verify token at app start. If its valid you can navigate to main dashboard of your application or whatever screen you want. Otherwise you can navigate to login screen if its not valid.

You can use react-navigation for sure as Its most recommended library. Here is your navigation setup.

import { createSwitchNavigator, createStackNavigator, createAppContainer } from 'react-navigation';

// Implementation of HomeScreen, OtherScreen, SignInScreen, AuthLoadingScreen
// goes here.

const AppStack = createStackNavigator({ Home: HomeScreen, Other: OtherScreen });
const AuthStack = createStackNavigator({ SignIn: SignInScreen });

export default createAppContainer(createSwitchNavigator(
  {
    AuthLoading: AuthLoadingScreen,
    App: AppStack,
    Auth: AuthStack,
  },
  {
    initialRouteName: 'AuthLoading',
  }
));

and you can code following in your authloading screen

import React from 'react';
import {
  ActivityIndicator,
  AsyncStorage,
  StatusBar,
  StyleSheet,
  View,
} from 'react-native';

class AuthLoadingScreen extends React.Component {
  constructor(props) {
    super(props);
    this._bootstrapAsync();
  }

  // Fetch the token from storage then navigate to our appropriate place
  _bootstrapAsync = async () => {
    const userToken = await AsyncStorage.getItem('userToken');

    // This will switch to the App screen or Auth screen and this loading
    // screen will be unmounted and thrown away.
    this.props.navigation.navigate(userToken ? 'App' : 'Auth');
  };

  // Render any loading content that you like here
  render() {
    return (
      <View>
        <ActivityIndicator />
        <StatusBar barStyle="default" />
      </View>
    );
  }
}

for more information, you can always visit this link.

https://reactnavigation.org/docs/en/auth-flow.html

5 Comments

Thanks for your reply.It's fine but you didn't use persist-redux in this code section. Is it possible to ignore it at all without serious problem?
redux-persist ideally used for persisting store and rehydrate. It is not required to store the authentication token.
I don't see any setItem here. can you please tell me where would you get userToken?
generally in response of login/signup api. just set it there @roz333
Hi, is it secure to store oauth token in AsyncStorage? Is it prone to XSS and CSRF attacks?
0

For user login with token, you can use AsyncStorage, which is a service that is part of React Native that allows us to store small snippets of data in the users phone.

So even if the user closes out of the app or shuts down their mobile device which has the effect of dumping the information from our Redux store which is sitting inside of JavaScript memory where there is no persistence, we can see if the token exists by looking into AsyncStorage.

So if the user logs in at least one time and the token is saved to AsyncStorage, this will allow you to persist a token from different uses or reboots of your application. So to import it, would look something like this for example:

import { AsyncStorage } from "react-native";
import { FACEBOOK_LOGIN_SUCCESS } from "./types";

export const facebookLogin = () => {};

AsyncStorage works a bit like localStorage inside your browser. AsyncStorage exposes two different functions, the first is called AsyncStorage.setItem();. This can hold a particular key as a first argument and the piece of data we want to save as a second argument, AsyncStorage.setItem('fb_token', token);. The second function is AsyncStorage.getItem(); and we pass in the key under which you previously saved it, AsyncStorage.getItem('fb_token');.

When you want to save the item to the device, you say here is the token and a string to specify what key we want to save it as.

The key allows us to have a separate bucket of storage to save to a unique location and retrieve it later on by looking at that same exact key, by the example of 'fb_token'.

AsyncStorage behaves a bit different from localStorage in that it's an asynchronous operation so it takes some amount of time to read it off storage.

The AsyncStorage will return a Promise after the record has been retrieved or successfully saved. So your code will have to be set up to work with Promises when retrieving or saving with AsyncStorage.

Now, I use logging in with Facebook as an example in my code to make the point that if you are using a authentication with a third party services like Facebook, you are going to be dealing with some more Promises in addition to the AsyncStorage one.

The point being that your code can get messy real quick. To deal with that you can use the ES7 Async/Await syntax which is used to gracefully handle Promises.

So with the .then() syntax it would start looking like this:

asynchronousOperation = () => {
  myRequest().then((result) => console.log(result));
}

With the Async/Await syntax it would look like this:

asynchronousOperation = async () => {
  let result = await myRequest();
  console.log(result);
}

So in practice it would start out like this inside your action creator:

import { AsyncStorage } from "react-native";
import { FACEBOOK_LOGIN_SUCCESS } from "./types";

export const facebookLogin = () => {
  let token = await AsyncStorage.getItem("fb_token");
  if (token) {
    // Dispatch an action saying FB login is successful
  } else {
    // Start up Facebook login process
  }
};

Now action creators assume you are returning an action object immediately, right, but AsyncStorage is asynchronous in nature, so we need something like Redux Thunk, which in practice it would look like this:

import { AsyncStorage } from "react-native";
import { FACEBOOK_LOGIN_SUCCESS } from "./types";

export const facebookLogin = () => async dispatch => {
  let token = await AsyncStorage.getItem("fb_token");
  if (token) {
    // Dispatch an action saying FB login is successful
  } else {
    // Start up Facebook login process
  }
};

2 Comments

I've been looking for a tutorial like this, It was very interesting, I am using redux, redux-thunk and react-navigation in my project, You wrote an action code here but you didn't declare any reducer for that, Doesn't it need a reducer?
And one more thing, You didn't use FACEBOOK_LOGIN_SUCCESS type in your code so why did you import that?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.