Newby Coder header banner

React Native Basic Authentication

Implementing Basic Authentication in React Native

Basic Authentication is when raw(or with basic encoding) username and password is sent to the server, typically in its body

Sending credential pair in 'Authorization' header of a request can be also considered as basic authentication request:

fetch('http://192.168.43.34:4500/users/getInfo', {
    headers: {
      'Authorization': 'Basic ' + base64.encode(username + ":" + password);
    }
});

It consists of a prefix Basic (or some other word) and base64 encoding of username and password separated by colon (:)

Provided application requires a backend server which performs the authentication

Check Nodejs Basic Authentication server to implement such a server in Nodejs

Creating new React Native App

Check React Native Installation for installation related info

Use react-native init command to create a new React Native project (here named NcBasicAuthApp)

react-native init NcBasicAuthApp

This creates a directory named NcBasicAuthApp and initializes it as a react native application directory

This can be skipped in case an existing react native project is being integrated into


Dependency

Since this example uses NavigationDrawer component, related packages have to be added

Go to project directory (here NcBasicAuthApp)

cd NcBasicAuthApp

Add react-navigation react-navigation-drawer && react-navigation-stack and associated dependencies to current project using yarn

yarn add react-navigation react-navigation-drawer react-navigation-stack \
react-native-gesture-handler react-native-reanimated react-native-safe-area-context react-native-screens

or using npm

npm install react-navigation react-navigation-drawer react-navigation-stack \
react-native-gesture-handler react-native-reanimated react-native-safe-area-context react-native-screens --save

iOS

After yarn add command, cd into ios folder inside project directory

cd ios

Use pod command to install any required CocoaPods dependencies:

pod install

Implementation

Example provided here implements two similar kinds of basic authentication

Login Page

ViewUser page

To ger user info, authorization string is created with username and password

App Code

Following code of App.js defines

App.js
import React from 'react';
import {
  StyleSheet,
  View,
  Text,
  StatusBar,
  KeyboardAvoidingView,
  TextInput,
  Button, ScrollView
} from 'react-native';

import { createAppContainer } from 'react-navigation';
import { createStackNavigator} from 'react-navigation-stack';
import base64 from 'react-native-base64'

import ViewUser from './ViewUser';


class LoginPage extends React.Component {

  constructor() {
    super();
    this.state = {
      username:'',
      password:''
    }
  }

  navigateToPage(data) {
    const { navigate } = this.props.navigation;
    data.password = this.state.password;
    navigate('User', {
      userData: data
    })
  };

  login() {
    const {username, password} = this.state;
    const encoded =  base64.encode(password);
    if(username.length < 1) {
      alert('Enter username');
    }
    else if (password.length < 1) {
      alert('enter password');
    }
    else {
      fetch('http://192.168.43.34:4500/users/authenticate', {
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({username: username, password: encoded})
      })
      .then(response => {
        if (!response.ok) throw response;
        return response.json();
      })
      .then(responseJson => {
        this.navigateToPage(responseJson);
      })
      .catch(error => {
        if(error instanceof Error) {
          console.error(error);
        }
        else {
          error.json().then((body) => {
                if(body.message) {
                  alert(body.message);
                }
                console.log(body);
          });
        }
      });
    }
  };

  render() {
    return (
      <View style={{ backgroundColor: 'white', flex: 1 }}>
        <ScrollView keyboardShouldPersistTaps="handled">
          <KeyboardAvoidingView
            behavior="padding"
            style={{ flex: 1, justifyContent: 'space-between' }}>
            <TextInput
              placeholder="Enter username"
              onChangeText={username => this.setState({ username })}
              style={{ padding:10 }}
            />
            <TextInput
              placeholder="Enter password"
              onChangeText={password => this.setState({ password })}
              style={{ padding:10 }}
              secureTextEntry
            />
            <Button
              title="Submit"
              onPress={this.login.bind(this)}
            />
          </KeyboardAvoidingView>
        </ScrollView>
      </View>
    );
  };
};

const App = createStackNavigator({
  HomeScreen: {
    screen: LoginPage,
    navigationOptions: {
      title: 'Basic Auth - Login Page',
    },
  },
  User: {
    screen: ViewUser,
    navigationOptions: {
      title: 'User Page',
    },
  }
});

export default createAppContainer(App);

ViewUser class displays some info about a user

ViewUser.js
import React from 'react';
import { Text, View, Button, TextInput, Image } from 'react-native';
import base64 from 'react-native-base64'


export default class ViewUser extends React.Component {
  constructor(props) {
    super(props);
    const {username, password} = props.navigation.state.params.userData;
    this.auth = 'Basic ' + base64.encode(username + ":" + password);
    this.state = {
      user_id: props.navigation.state.params.userData.id,
      user_contact: '',
      user_city: '',
      user_country: '',
      user_image: '',
      user_fn: '',
    };
  };

  componentDidMount() {
    this.getUserData();
  };

  async getUserData() {
    var responseJson = null;
    try {
        responseJson = await( await fetch('http://192.168.43.34:4500/users/getInfo', {
        method: 'GET',
        headers: {
          'Authorization': this.auth
        }
      })).json();
    }
    catch(err) {
      console.log("error", err);
    }
    if(responseJson) {
      console.log("viewuser response " + JSON.stringify(responseJson));
      this.setState({
        user_contact: responseJson.userdata.cell,
        user_fn: responseJson.userdata.name.first + ' ' + responseJson.userdata.name.last,
        user_city: responseJson.userdata.location.city,
        user_country: responseJson.userdata.location.country,
        user_image: responseJson.userdata.picture.medium
      });
    }
  };

  render() {
    const { user_id, user_contact, user_city, user_country, user_image, user_fn } = this.state;
    return (
      <View style={{ flexDirection:'row', backgroundColor:'#628367'}}>
        <View style={{ marginLeft: 35, marginRight: 35, margin: 10, flex: 2 }}>
          <Text>Id: {user_id}</Text>
          <Text>Name: {user_fn}</Text>
          <Text>Phone: {user_contact}</Text>
          <Text>City: {user_city}</Text>
          <Text>Country: {user_country}</Text>
        </View>
        <View>
        { user_image.length == 0? null:
          <Image source={{uri:user_image}} style={{ width:100, height:150, marginLeft: 35, marginRight: 35, margin: 10, flex:1, resizeMode:'contain' }}/> }
        </View>
      </View>
    );
  };
}

Run instructions

Running in Android

cd into project directory (here NcBasicAuthApp)

cd NcBasicAuthApp

Run metro server to serve js

react-native start

Go to project directory in another terminal tab

Enter following run command for Android:

react-native run-android
cl-react-native-basic-auth

Running in ios

cd into project directory (here NcBasicAuthApp)

cd NcBasicAuthApp

Enter following command :

react-native run-ios

This might take some time


If the app shows error about metro server not configured (check Running an App in iOS), then run metro server in another tab:

react-native start

Reload the app

Re-run react-native run-ios command if reloading doesn't work

cm-react-native-basic-authentication-as1cm-react-native-basic-authentication-as2