Problem with Expo Google signin on Device - react-native

I followed every single step on the tutorial page of Expo.dev to create a login page using Google Oauth.
I get the browser to open and I select a google account but the response I get back is *
Object {
"type": "dismiss",
}
Here is my code, literally copied and pasted from the tutorial page of the official expo dev site
import * as React from 'react';
import * as WebBrowser from 'expo-web-browser';
import * as Google from 'expo-auth-session/providers/google';
import { Button } from 'react-native';
WebBrowser.maybeCompleteAuthSession();
export default function App() {
const [request, response, promptAsync] = Google.useAuthRequest({
expoClientId: 'GOOGLE_GUID.apps.googleusercontent.com',
iosClientId: 'GOOGLE_GUID.apps.googleusercontent.com',
androidClientId: 'GOOGLE_GUID.apps.googleusercontent.com',
webClientId: 'GOOGLE_GUID.apps.googleusercontent.com',
});
React.useEffect(() => {
if (response?.type === 'success') {
const { authentication } = response;
}
}, [response]);
return (
<Button
disabled={!request}
title="Login"
onPress={() => {
promptAsync();
}}
/>
);
}

Related

How to handle Auth with WebBrowser.openAuthSessionAsync in Expo?

I created a auth flow using WebBrowser.openAuthSessionAsync, the opening and the closing are working as expected but my problem comes with the return, I only receive back from the browser: {"type": "success", "url": "exp://192.168.0.11:19000/--/App"}, the type and my return URL.
I'm trying to figure out how to have access to any kind of info from the return, from cookies to query string on the URL as I have control over how my API handles the return, but I'm not being able to access any kind of info from the AuthSession.
Here is the implementation:
import { useEffect, useState } from "react"
import { Button, View, Text } from "react-native"
import * as WebBrowser from "expo-web-browser"
import * as Linking from "expo-linking"
export default () => {
const [result, setResult] =
useState<WebBrowser.WebBrowserAuthSessionResult | null>(null)
useEffect(() => {
console.log(result)
}, [result])
const _handlePressButtonAsync = async () => {
const baseUrl = "https://...com"
const callbackUrl = Linking.createURL("App", { scheme: "myapp" })
setResult(
await WebBrowser.openAuthSessionAsync(
`${baseUrl}/login?returnUrl=${encodeURIComponent(
`${baseUrl}/_v/login?token=...&iv=...&returnUrl=${callbackUrl}`
)}`,
callbackUrl
)
)
}
return (
<View className="items-center justify-center flex-1">
<Button title="Open Auth Session" onPress={_handlePressButtonAsync} />
{result && <Text>{JSON.stringify(result)}</Text>}
</View>
)
}
It's a SASS platform, that does not follow only the OAuth flow, which made me choose this method over https://docs.expo.dev/versions/latest/sdk/auth-session/

Use RN Expo Web Browser dismissBrowser when on specific URL

Trying to achieve the following scenario
Client clicks a button and it opens the Expo web browser with a URL e.g wwww.example.com/test
User does something and is redirected to a URL like wwww.example.com/success
The app recognizes the URL and auto-closes the web browser
It correctly opens the web browser but nothing happens afterward when I go to wwww.example.com/success.
I'm not getting any errors and with the iOS Expo preview, I get no console.log triggers, but with the Web Expo preview, I get generic logging.
Code below
import React, { useState } from 'react';
import { Button, StyleSheet, Text, View } from 'react-native';
import * as Linking from 'expo-linking';
import * as WebBrowser from 'expo-web-browser';
export const WebVerification = () => {
const [redirectData, setRedirectData] = useState(null);
const _handleRedirect = (event) => {
console.log('handle Request is called')
let data = Linking.parse(event.url);
console.log(data)
if( data.url === "wwww.example.com/success") {
WebBrowser.dismissBrowser();
}
setRedirectData(data);
};
const _openBrowserAsync = async () => {
try {
_addLinkingListener();
let result = await WebBrowser.openBrowserAsync(
`wwww.example.com/test`
);
} catch (error) {
alert(error);
console.log(error);
}
};
const _addLinkingListener = () => {
Linking.addEventListener("url", _handleRedirect);
};
const _removeLinkingListener = () => {
Linking.removeEventListener("url", _handleRedirect);
};
const _maybeRenderRedirectData = () => {
console.log("check RenderRedirect" + redirectData)
if (!redirectData) {
return;
}
return (
<Text style={{ marginTop: 30 }}>
{JSON.stringify(redirectData)}
</Text>
);
};
return (
<View>
<Text>Redirect Example</Text>
<Button onPress={_openBrowserAsync} title="Open Browser" />
{_maybeRenderRedirectData()}
</View>
);
};

Why isn't the google accounts login page showing up even though I have implemented the expo auth session library with react native?

I have been following the tinder 2.0 react native tutorial https://youtu.be/qJaFIGjyRms At 1:04:00 he sets the sign in method to: "await Google.logInAsync()" but I have noticed the google app auth library used in the video is now deprecated, I am redirected to use expo auth session instead, with this new library I cannot tell whether the google sign in is working or not as I am simply redirected back to the homepage after clicking the login button.
Here is my code with response printed in the console:
Screenshot:
code:
import React, { createContext, useContext } from 'react'
import * as WebBrowser from "expo-web-browser";
import { Button } from "react-native";
import * as Google from "expo-auth-session/providers/google";
import { useEffect, useState } from "react";
import { useNavigation } from "#react-navigation/native";
import { GoogleAuthProvider, signInWithCredential } from 'firebase/auth';
const AuthContext = createContext({});
const user = null
WebBrowser.maybeCompleteAuthSession();
const GoogleLogin = () => {
const navigation = useNavigation();
const [request, response, promptAsync] = Google.useAuthRequest({
expoClientId:
"236293699216-bst43767un873mcddmmrpgf4v2h088jd.apps.googleusercontent.com",
iosClientId:
"236293699216-6jdpm0rd6kn5d0qlbh1vgva5afgbqgib.apps.googleusercontent.com",
webClientId:
"236293699216-9a0nknjdq7ie79h40iubg0tddokgogfv.apps.googleusercontent.com",
scopes: ["profile", "email"],
permissions: ["public_profile","email", "gender", "location"],
});
const asyncAuthRequest = async () => {
if (response?.type === "success") {
const { authentication } = response;
// await AsyncStorage.setItem("accessTocken", "hihi");
//navigation.navigate"Home");
const { idToken, accessToken} = response;
const credential = GoogleAuthProvider.credential(idToken, accessToken);
await signInWithCredential(auth, credential)
}
return Promise.reject();
};
useEffect(() => {
asyncAuthRequest();
}, [response]);
console.log('response', response)
return (
<Button
disabled={!request}
title="Login"
onPress={() => {
promptAsync();
}}
/>
);
};
export default GoogleLogin;

How to solve React Native expo authSession google login issue?

I wanted to implement login with google feature on my React native app. I'm using expo-cli and I used expo authSession for this.
LoginScreen.js
import * as React from "react";
import * as WebBrowser from "expo-web-browser";
import * as Google from "expo-auth-session/providers/google";
import { Button, View, Text, TouchableOpacity } from "react-native";
WebBrowser.maybeCompleteAuthSession();
export default function LoginScreen() {
const [googleAccessToken, setGoogleAccessToken] = React.useState(null);
const [userInfo, setUserInfo] = React.useState(false);
const [request, response, promptAsync] = Google.useAuthRequest({
expoClientId: "###",
iosClientId: "###",
androidClientId: "###",
webClientId: "###",
});
React.useEffect(() => {
if (response?.type === "success") {
const { authentication } = response;
setGoogleAccessToken(authentication.accessToken);
fetchUserInfo();
}
}, [response]);
const fetchUserInfo = () => {
if (googleAccessToken) {
fetch("https://www.googleapis.com/oauth2/v3/userinfo", {
headers: { Authorization: `Bearer ${googleAccessToken}` },
})
.then((response) => response.json())
.then((userInfoObj) => {
setUserInfo(userInfoObj);
console.log(userInfoObj);
})
.catch((err) => {
console.log(err);
});
}
};
return (
<View>
<Button
disabled={!request}
title="Login Here"
onPress={() => {
promptAsync();
}}
/>
{userInfo ? <Text>{userInfo.email}</Text> : <Text>Nope</Text>}
</View>
);
}
But once, I click LOGIN HERE button and login with google account it doesn't set userInfo state in the first time. I have to click LOGIN HERE button again to login. Even though I have authenticated with google, it doesn't set userInfo state in the first time. But once I click LOGIN HERE again and after continue the process, then it works. How can I solve this issue?
Also I'm getting this warning as well.
Warning
EventEmitter.removeListener('url', ...): Method has been deprecated. Please instead use `remove()` on the subscription returned by `EventEmitter.addListener`.
at node_modules/react-native/Libraries/vendor/emitter/_EventEmitter.js:164:4 in EventEmitter#removeListener
at node_modules/react-native/Libraries/EventEmitter/NativeEventEmitter.js:108:4 in removeListener
at node_modules/react-native/Libraries/Linking/Linking.js:57:4 in removeEventListener
at node_modules/expo-web-browser/build/WebBrowser.js:354:4 in _stopWaitingForRedirect
at node_modules/expo-web-browser/build/WebBrowser.js:347:31 in _openAuthSessionPolyfillAsync
I found the answer for this question by myself. You need to put fetchUserInfo() inside useEffect.
import * as React from "react";
import * as WebBrowser from "expo-web-browser";
import * as Google from "expo-auth-session/providers/google";
import { Button, View, Text, TouchableOpacity } from "react-native";
WebBrowser.maybeCompleteAuthSession();
export default function LoginScreen() {
const [googleAccessToken, setGoogleAccessToken] = React.useState(null);
const [userInfo, setUserInfo] = React.useState(false);
const [request, response, promptAsync] = Google.useAuthRequest({
expoClientId: "###",
iosClientId: "###",
androidClientId: "###",
webClientId: "###",
});
React.useEffect(() => {
const fetchUserInfo = () => {
if (googleAccessToken) {
fetch("https://www.googleapis.com/oauth2/v3/userinfo", {
headers: { Authorization: `Bearer ${googleAccessToken}` },
})
.then(response => response.json())
.then(userInfoObj => {
setUserInfo(userInfoObj);
console.log(userInfoObj);
})
.catch(err => {
console.log(err);
});
}
};
if (response?.type === "success") {
const { authentication } = response;
setGoogleAccessToken(authentication.accessToken);
fetchUserInfo();
}
}, [response]);
return (
<View>
<Button
disabled={!request}
title="Login Here"
onPress={() => {
promptAsync();
}}
/>
{userInfo ? <Text>{userInfo.email}</Text> : <Text>Nope</Text>}
</View>
);
}

possible unhandled promise rejection request while google aunthentication

I am getting the following error while trying to integrate the google login into a react native app and got the following error. It was working fine before. Could someone help. Unable to figure the error
import type {Node} from 'react';
import { GoogleSignin } from '#react-native-google-signin/google-signin';
import auth from '#react-native-firebase/auth';
import {
SafeAreaView,
ScrollView,
StatusBar,
StyleSheet,
Text,
useColorScheme,
View,
Button
} from 'react-native';
const App: () => Node = () => {
GoogleSignin.configure({
webClientId: 'xxx',
});
const signInWithGoogleAsync = async() => {
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
const user_sign_in = auth().signInWithCredential(googleCredential);
user_sign_in.then((user) =>{
console.log(user);
})
.catch((error)=>{
console.log(error);
})
}
return (
<View style={{flex:1, justifyContent:'center', alignItems:'center'}}>
<Button
title='Sign in with Google'
onPress={signInWithGoogleAsync}
/>
</View>
);
};
export default App;