3

I need to add google sign-in method to my react native app. I used "react-native-google-signin" package. And I make a project in google console also. But I am getting an error when I try to sign in. It gives an error "Some Other Error Happened", and it is in my "_signIn()" function. Please help me to solve my problem.

Here what I tried

import React from 'react';
import {
  StyleSheet,
  Text,
  View,
  Alert,
  Image,
  ActivityIndicator,
  TouchableOpacity,
} from 'react-native';
import {
  GoogleSignin,
  GoogleSigninButton,
  statusCodes,
} from 'react-native-google-signin';

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      userInfo: null,
      gettingLoginStatus: true,
    };
  }

  componentDidMount() {
    //initial configuration
    GoogleSignin.configure({
      //It is mandatory to call this method before attempting to call signIn()
      scopes: ['https://www.googleapis.com/auth/drive.readonly'],
      // Repleace with your webClientId generated from Firebase console
      webClientId: 'my webclient id',
    });
    //Check if user is already signed in
    this._isSignedIn();
  }

  _isSignedIn = async () => {
    const isSignedIn = await GoogleSignin.isSignedIn();
    if (isSignedIn) {
      alert('User is already signed in');
      //Get the User details as user is already signed in
      this._getCurrentUserInfo();
    } else {
      //alert("Please Login");
      // console.log('Please Login');
      alert('Please Login');
    }
    this.setState({ gettingLoginStatus: false });
  };

  _getCurrentUserInfo = async () => {
    try {
      const userInfo = await GoogleSignin.signInSilently();
      console.log('User Info --> ', userInfo);
      this.setState({ userInfo: userInfo });
    } catch (error) {
      if (error.code === statusCodes.SIGN_IN_REQUIRED) {
        alert('User has not signed in yet');
        console.log('User has not signed in yet');
      } else {
        alert("Something went wrong. Unable to get user's info");
        console.log("Something went wrong. Unable to get user's info");
      }
    }
  };

  _signIn = async () => {
    //Prompts a modal to let the user sign in into your application.
    try {
      await GoogleSignin.hasPlayServices({
        //Check if device has Google Play Services installed.
        //Always resolves to true on iOS.
        showPlayServicesUpdateDialog: true,
      });
      const userInfo = await GoogleSignin.signIn();
      console.log('User Info --> ', userInfo);
      this.setState({ userInfo: userInfo });
    } catch (error) {
      console.log('Message', error.message);
      if (error.code === statusCodes.SIGN_IN_CANCELLED) {
        console.log('User Cancelled the Login Flow');
      } else if (error.code === statusCodes.IN_PROGRESS) {
        console.log('Signing In');
      } else if (error.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
        console.log('Play Services Not Available or Outdated');
      } else {
        console.log('Some Other Error Happened');
      }
    }
  };

  _signOut = async () => {
    //Remove user session from the device.
    try {
      await GoogleSignin.revokeAccess();
      await GoogleSignin.signOut();
      this.setState({ userInfo: null }); // Remove the user from your app's state as well
    } catch (error) {
      console.error(error);
    }
  };

  render() {
    //returning Loader untill we check for the already signed in user
    if (this.state.gettingLoginStatus) {
      return (
        <View style={styles.container}>
          <ActivityIndicator size="large" color="#0000ff" />
        </View>
      );
    } else {
      if (this.state.userInfo != null) {
        //Showing the User detail
        return (
          <View style={styles.container}>
            <Image
              source={{ uri: this.state.userInfo.user.photo }}
              style={styles.imageStyle}
            />
            <Text style={styles.text}>
              Name: {this.state.userInfo.user.name}{' '}
            </Text>
            <Text style={styles.text}>
              Email: {this.state.userInfo.user.email}
            </Text>
            <TouchableOpacity style={styles.button} onPress={this._signOut}>
              <Text>Logout</Text>
            </TouchableOpacity>
          </View>
        );
      } else {
        //For login showing the Signin button
        return (
          <View style={styles.container}>
            <GoogleSigninButton
              style={{ width: 312, height: 48 }}
              size={GoogleSigninButton.Size.Wide}
              color={GoogleSigninButton.Color.Light}
              onPress={this._signIn}
            />
          </View>
        );
      }
    }
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  imageStyle: {
    width: 200,
    height: 300,
    resizeMode: 'contain',
  },
  button: {
    alignItems: 'center',
    backgroundColor: '#DDDDDD',
    padding: 10,
    width: 300,
    marginTop: 30,
  },
});
Sidath
  • 379
  • 1
  • 9
  • 25
  • I am facing same issue, any solution for same – Swift Oct 21 '20 at 13:00
  • 2
    The error you're probably facing is the DEVELOPER_ERROR. Other people have raised the same issue here on StackOverflow I still haven't figured out how to solve, but these are the 2 most useful and well explained resources I've found so far: - https://chaim-zalmy-muskal.medium.com/hi-6d328bbd550f - https://github.com/react-native-google-signin/google-signin/blob/master/docs/android-guide.md - https://topherpedersen.blog/2020/07/02/solved-how-to-fix-a-developer_error-when-implementing-sign-in-with-google-using-react-native-community-google-signin-or-expo-google-sign-in/ – Daniel González Fernández Dec 01 '20 at 02:49
  • I've been trying to solve it without using a Firebase app, but no luck for me so far. If you ever manage to solve it, please let us know. – Daniel González Fernández Dec 01 '20 at 02:49
  • Any updates on this issue? – user14587589 May 21 '21 at 08:21

3 Answers3

0
  1. Install

npm i @react-native-google-signin/google-signin

Setting up Android environment

After installing the required module, let's set up some android files to make it work properly.

Update android/build.gradle with the following configuration:

Add classpath 'com.google.gms:google-services:4.3.10' into your dependencies in buildscript.

  1. Update android/app/build.gradle with the following configuration:
  • Add apply plugin: 'com.android.application' at the top of your build gradle (android/app).
  • Add implementation 'com.google.android.gms:play-services-auth:20.0.0'

implementation "androidx.browser:browser:1.2.0" in dependencies in the same.

Importing module in our App

Now import the installed module like this

import { GoogleSignin, statusCodes } from '@react-native-google-signin/google-signin';

then after importing the module let's set up a configuration code for our sign-up.

GoogleSignin.configure({
  webClientId:
   '842785997270- 
   q7jqk66e76ctb8qrh1l7fmcoqgv483j3.apps.googleusercontent.com',
   offlineAccess: true
 });

Let's not worry about the client Id, for now, we will generate it later on in this tutorial.

Now after configuration is done, it's time to make our sign-up function using the Google Auth module we just imported.

 signIn = async () => {
   try {
    console.warn('hello');
    await GoogleSignin.hasPlayServices();
    const userInfo = await GoogleSignin.signIn();

   console.log('user name =>', userInfo.user.email);
} catch (error) {
  if (error.code === statusCodes.SIGN_IN_CANCELLED) {
    // user cancelled the login flow
    console.warn('SIGN IN CANCELLED', error.message);
  } else if (error.code === statusCodes.IN_PROGRESS) {
    // operation (e.g. sign in) is in progress already
    console.warn('IN PROGRESS', error.message);
  } else if (error.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
    // play services not available or outdated
    console.warn('play services not available or outdated', error.message);
  } else {
    ToastAndroid.showWithGravity(
      'Something went wrong. Please try again',
      ToastAndroid.LONG,
      ToastAndroid.CENTER,
    );
    alert(error.message)
    console.warn('Meassage', error.message);
  }
  }
 };

Now Connect this function to your button with onPress={GoogleSingUp} prop

Generating Web client ID and SHA1 key for Sign up

Now, this is the main part where most of the developer gets stuck or get a pretty common and irritating error -

Error: Status{statusCode=DEVELOPER_ERROR}

But what is causing this error?. It is quite simple, the SHA1 key of Debug Keystore. Yeah, according to google, you have to put your Release Keystore key in Google Console. But most blogs and articles forget to mention this point which is very important no matter which module you are using.

1) Generate Release keystore and it's SHA

Now assuming you have already installed JDK in your system, let's move to generating the Release key. In your android/app run this command in cmd -

 keytool -genkey -v -keystore my_release_key.keystore -alias my_key_alias -keyalg RSA -keysize 2048 -validity 10000 

It will ask for some detail so fill them in carefully and remember the password you entered in it.

This command will generate a release key in your android/app directory.

  • Now in your android/gradle.properties add

    MYAPP_UPLOAD_STORE_FILE=my_release_key.keystore
    MYAPP_UPLOAD_KEY_ALIAS= my_key_alias
    MYAPP_UPLOAD_STORE_PASSWORD=yourPassword
    MYAPP_UPLOAD_KEY_PASSWORD=yourPassword
    
  • And this in your android/app/build.gradle

    signingConfigs {
     debug {
        // storeFile file('debug.keystore')
       // storePassword 'android'
       // keyAlias 'androiddebugkey'
       // keyPassword 'android'
    
      storeFile file(MYAPP_UPLOAD_STORE_FILE)
      storePassword MYAPP_UPLOAD_STORE_PASSWORD
      keyAlias MYAPP_UPLOAD_KEY_ALIAS
      keyPassword MYAPP_UPLOAD_KEY_PASSWORD
     }
    
    release {
     if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) {
         storeFile file(MYAPP_UPLOAD_STORE_FILE)
         storePassword MYAPP_UPLOAD_STORE_PASSWORD
         keyAlias MYAPP_UPLOAD_KEY_ALIAS
         keyPassword MYAPP_UPLOAD_KEY_PASSWORD
     }
    }
    }
    

Now this will generate release SHA as your debug keystore SHA, so you don't have to worry about that error

Now generate release SHA1 using this command in android

keytool -list -v -keystore app/my_release_key.keystore -alias my_key_alias

Copy that SHA1 key and paste it somewhere for the next step.

2) Inserting SHA1 key in Google Developer Console.

Now, after doing that much hard work, let's do this final part. We have to paste this key into the Google Developer console to tell google about our app and its authentication.

  • After signing up in the Google Developer console or Google cloud platform, head over to the Credential tab. There you will find a button saying "Create Credential", choose OAth Client ID.

enter image description here

  • Then choose Application type- Android and enter the package name and then the SHA1 key you copied in the previous step. Hit create and your Android API is ready.

enter image description here

Now Similarly create an OathID for Web client instead of Android and leave all other fields as it is. enter image description here

  • Now copy the Web client ID from the Oath you just created.

enter image description here

That's it we got the Web client ID we needed for Step 3 above.

Finalizing

Now paste this Web Client ID into your Google config object in Step 3 above and run the app.

After pressing the Sign-in Button, A pop-up should appear. Select the account you want to login with and after selecting the account it will return an object containing IdToken and some other stuff.

If you did everything exactly the same and didn't mess up anywhere, we should see some results like this

{
 "idToken": "Your-google-auth-token",
  "scopes": [
    "https://www.googleapis.com/auth/userinfo.email",
    "https://www.googleapis.com/auth/userinfo.profile"
],
 "serverAuthCode": "your-server-auth-code",
  "user": {
    "email": "youremail@gmail.com",
    "familyName": "your-last-name",
    "givenName": "your-first-name",
    "id": "some-id",
    "name": "your-full-name",
    "photo": "a-url-for-profile-photo"
 }
}

And with that, we successfully integrated the Google auth into our React Native app.

Deepak Singh
  • 749
  • 4
  • 16
0

I was also struggling with the same issue and what worked was adding the androidClientId key to the config object like so

GoogleSignin.configure({
  scopes: ["MY SCOPE"],
  offlineAccess: true,
  webClientId: WEB_CLIENT_ID,
  androidClientId: ANDROID_CLIENT_ID,  // <-- Added here
});

Referring to the below picture as shared by @Deepak Singh in his answer, the WEB_CLIENT_ID would be the circled one and ANDROID_CLIENT_ID will be the top one.

enter image description here

Samkit Jain
  • 1,560
  • 2
  • 16
  • 33
-1

still blocked ? You can try to see the error in you'r log , like this :

     else {
    console.log('Some Other Error Happened', error);

And with this make a new research or response :)

Esoriak
  • 37
  • 3