dappros/ethora

View on GitHub
client-reactnative/src/helpers/login/socialLoginHandle.ts

Summary

Maintainability
C
1 day
Test Coverage
/*
Copyright 2019-2022 (c) Dappros Ltd, registered in England & Wales, registration number 11455432. All rights reserved.
You may not use this file except in compliance with the License.
You may obtain a copy of the License at https://github.com/dappros/ethorablob/main/LICENSE.
Note: linked open-source libraries and components may be subject to their own licenses.
*/

import {LoginManager, AccessToken} from 'react-native-fbsdk-next';
import auth from '@react-native-firebase/auth';
import {sha256} from 'react-native-sha256';
import {checkEmailExist} from '../../config/routesConstants';
import {httpGet} from '../../config/apiService';
import {showToast} from '../../components/Toast/toast';
import {GoogleSignin} from '@react-native-google-signin/google-signin';
import {Alert, Platform} from 'react-native';
import appleAuth, {
  appleAuthAndroid,
} from '@invertase/react-native-apple-authentication';
import {v4 as uuid} from 'uuid';

export const loginOrRegisterSocialUser = async (
  user: any,

  defaultToken: string,
  loginUser: any,
  registerSocialUser: any,
  loginType: string,
) => {
  const url = checkEmailExist + user.email;
  try {
    const response = await httpGet(url, defaultToken);
    if (!response.data.success) {
      loginUser(loginType, user.authToken, user.uid, user);
    } else {
      const dataObject =
        loginType === 'apple'
          ? {
              loginType: loginType,
              authToken: user.authToken,
              displayName: user.displayName,
              password: user.uid,
              username: user.email,
              email: user.email,
              firstName: user.firstName || 'Anonymous',
              lastName: user.lastName || 'Raccoon',
            }
          : {
              firstName: user.firstName,
              lastName: user.lastName,
              username: user.email,
              email: user.email,
              password: user.uid,
              loginType,
              authToken: user.authToken,
            };
      registerSocialUser(dataObject, user);
    }
  } catch (error) {
    showToast(
      'error',
      'Error',
      'Something went wrong, please try again later',
      'top',
    );
  }
};

export const handleFaceBookLogin = async (
  defaultToken: string,
  loginUser: any,
  registerSocialUser: any,
  type: string,
) => {
  LoginManager.logOut();

  // Attempt login with permissions
  const result = await LoginManager.logInWithPermissions([
    'public_profile',
    'email',
  ]);

  if (result.isCancelled) {
    throw 'User cancelled the login process';
  }

  // Once signed in, get the users AccesToken
  const data = await AccessToken.getCurrentAccessToken();

  if (!data) {
    throw 'Something went wrong obtaining access token';
  }

  // Create a Firebase credential with the AccessToken
  const facebookCredential = auth.FacebookAuthProvider.credential(
    data.accessToken,
  );

  let facebookUser = await auth().signInWithCredential(facebookCredential);

  let hashUID = '';

  await sha256(facebookUser.user.uid).then(hash => {
    hashUID = hash;
  });

  let user = {
    firstName: facebookUser.additionalUserInfo.profile.first_name,
    lastName: facebookUser.additionalUserInfo.profile.last_name,
    email: facebookUser.additionalUserInfo.profile.email,
    photo: facebookUser.additionalUserInfo.profile.picture.data.url,
    authToken: facebookCredential.token,
    uid: hashUID,
  };

  loginOrRegisterSocialUser(
    user,
    defaultToken,
    loginUser,
    registerSocialUser,
    type,
  );
};

const signInGoogle = (googleCredential: any, callback: any) => {
  auth()
    .signInWithCredential(googleCredential)
    .then(data => callback(data))
    .catch(error => {
      if (
        error.message ===
        '[auth/network-request-failed] A network error (such as timeout, interrupted connection or unreachable host) has occurred.'
      ) {
        Alert.alert(
          'No Internet Connection',
          'Connect your phone to the Internet by using an available Wi-Fi or cellular network.',
          [
            {
              text: 'Cancel',
              onPress: () => console.log('Cancel'),
            },
            {
              text: 'Retry',
              onPress: () => handleGoogleLogin(),
            },
          ],
        );
      }
    });
};

export const handleGoogleLogin = async (
  defaultToken: string,
  loginUser: any,
  registerSocialUser: any,
  type: string,
) => {
  LoginManager.logOut();

  // Get the users ID token
  const {idToken} = await GoogleSignin.signIn();

  // Create a Google credential with the token
  const googleCredential = auth.GoogleAuthProvider.credential(idToken);

  // Sign-in the user with the credential
  // AsyncStorage.setItem('GToken', googleCredential.token);

  const googleUser = await auth().signInWithCredential(googleCredential);

  let hashUID = '';

  await sha256(googleUser.user.uid).then(hash => {
    hashUID = hash;
  });

  let user = {
    firstName: googleUser.additionalUserInfo.profile.given_name,
    lastName: googleUser.additionalUserInfo.profile.family_name,
    email: googleUser.additionalUserInfo.profile.email,
    photo: googleUser.additionalUserInfo.profile.picture,
    authToken: idToken,
    uid: hashUID,
  };

  await loginOrRegisterSocialUser(
    user,
    defaultToken,
    loginUser,
    registerSocialUser,
    type,
  );
};

export const handleAppleLogin = async (
  defaultToken: string,
  loginUser: any,
  registerSocialUser: any,
  type: string,
) => {
  let appleUser = {
    loginType: 'apple',
    authToken: '',
    displayName: '',
    uid: '',
    email: '',
  };
  LoginManager.logOut();
  // performs login request
  if (Platform.OS === 'android') {
    // Generate secure, random values for state and nonce
    const rawNonce = uuid();
    const state = uuid();

    // Configure the request
    appleAuthAndroid.configure({
      // The Service ID you registered with Apple
      clientId: 'com.ethora.service',

      // Return URL added to your Apple dev console. We intercept this redirect, but it must still match
      // the URL you provided to Apple. It can be an empty route on your backend as it's never called.
      redirectUri: 'https://ethora-668e9.firebaseapp.com/__/auth/handler',

      // The type of response requested - code, id_token, or both.
      responseType: appleAuthAndroid.ResponseType.ALL,

      // The amount of user information requested from Apple.
      scope: appleAuthAndroid.Scope.ALL,

      // Random nonce value that will be SHA256 hashed before sending to Apple.
      nonce: rawNonce,

      // Unique state value used to prevent CSRF attacks. A UUID will be generated if nothing is provided.
      state,
    });
    // console.log(appleAuthAndroid.isSupported)

    // Open the browser window for user sign in
    const responseFromApple = await appleAuthAndroid.signIn();

    const {id_token, nonce} = responseFromApple;

    const appleCredentialAndroid = auth.AppleAuthProvider.credential(
      id_token,
      nonce,
    );
    const data = await auth().signInWithCredential(appleCredentialAndroid);
    let hashUID = await sha256(data.user.uid);
    let user = {
      loginType: 'apple',
      authToken: id_token,
      displayName: '',
      uid: hashUID,
      email: data.additionalUserInfo.profile.email,
      firstName: data.user.displayName,
      lastName: data.user.displayName,
    };
    return user;

    // Send the authorization code to your backend for verification
  } else {
    const appleAuthRequestResponse = await appleAuth.performRequest({
      requestedOperation: appleAuth.Operation.LOGIN,
      requestedScopes: [appleAuth.Scope.EMAIL, appleAuth.Scope.FULL_NAME],
    });

    // Ensure Apple returned a user identityToken
    if (!appleAuthRequestResponse.identityToken) {
      throw 'Apple Sign-In failed - no identify token returned';
    }

    // Create a Firebase credential from the response
    const {identityToken, nonce} = appleAuthRequestResponse;
    const appleCredential = auth.AppleAuthProvider.credential(
      identityToken,
      nonce,
    );

    const data = await auth().signInWithCredential(appleCredential);
    let hashUID = await sha256(data.user.uid);
    let user = {
      loginType: 'apple',
      authToken: identityToken,
      displayName: '',
      uid: hashUID,
      email: data.additionalUserInfo.profile.email,
      firstName: data.user.displayName,
      lastName: data.user.displayName,
    };
    return user;
  }
};