React Native - GoogleSignIn - refreshToken, idToken, accessTokenExpirationDate are all null - react-native

I am trying to use expo-google-sign-in in my project. I am able to login with GoogleSignIn.signInAsync() but in the object I get back as a result the refreshToken, idToken and accessTokenExpirationDate are all null. Does anybody have any idea what the problem can be? I use expo 4.2.1. I have ejected the project and run it with react-native run-android
Here is my code:
import React from 'react';
import { View, Button } from 'react-native';
import * as GoogleSignIn from 'expo-google-sign-in';
export default function App() {
return (
<View>
<Button title='sign in' onPress={async () => {
await GoogleSignIn.initAsync({
clientId: '<MY CLIENT ID>',
scopes: [
GoogleSignIn.SCOPES.OPEN_ID
],
});
const r = await GoogleSignIn.signInAsync();
console.log(JSON.stringify(r));
}}/>
</View>
);
}
And the result is something like this:
{
"type": "success",
"user": {
"uid": "8978924659847365874563486867",
"email": "john.bar#gmail.com",
"displayName": "John Bar",
"photoURL": "https://lh3.googleusercontent.com/a-/AjsgdyegdrR-_wluyiuBUUKDKWBUWYDKUWGHDjO-M",
"firstName": "John",
"lastName": "Bar",
"auth": {
"idToken": null,
"refreshToken": null,
"accessToken": "ya29.a0AfH6SMCh1K322dfdf34rff6_gGHW98-kIngxBUUTtfRZTugtwff4f4wf4f4wf4fPib9fc2JPXmg7ewfGx7peVtC4ffwfw4fwfw4fw4fBeFkqJydbWxcwiUb",
"accessTokenExpirationDate": null
},
"scopes": [
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/userinfo.email"
],
"serverAuthCode": null
}
}
What is also strange that the scopes field in the result doesn't contain openid.
These are my credentials in my google cloud console (the SHA1 fingerprint comes from debug.keystore).
The Consent setup
Thanks in advance

Try to use webClientId instead of clientId in initAsync It worked for me.
await GoogleSignIn.initAsync({
webClientId: '<MY CLIENT ID>',
});

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/

know route name from outside the stack navigator container in react native?

How to get the current route name I am accessing in my app.
In my App.js
import React from 'react';
import { StatusBar } from 'react-native-web';
import { NavigationContainer } from '#react-navigation/native'
import { MainStack } from './MainStack';
import HeaderProfileContainer from './components/ScreenContainers/HeaderProfileContainer';
import FooterContainer from './components/ScreenContainers/FooterContainer';
import { navigationRef,getRootState } from './RootNavigation';
export default function App() {
const location = getRootState()
console.log(location);
return (
<NavigationContainer ref={navigationRef}>
<StatusBar style="light"/>
<HeaderProfileContainer />
<MainStack /> //This Contains all Stack Navigator and Screen
<FooterContainer /> //I want to access the route name of current screen in this container
</NavigationContainer>
);
}
I tried using the ref method of creating a new js file with RootNavigation: this-
//RootNavigation.js
import React from 'react';
export const navigationRef = React.createRef();
// Export navigation functions to use throughout your app, without accessing the `navigation` prop.
export function navigate(name, params) {
navigationRef.current?.navigate(name, params);
}
// This is the function I tried , but it returns only an object with all navigation routes names and I want to get name of current screen!
export function getRootState() {
return navigationRef.current?.getRootState();
}
I used the getRootState and it returns me this object: How can i get the current screem name?
Object {
"index": 2,
"key": "stack-nG_wBAHrHSWx38PLK9jT3",
"routeNames": Array [
"Home",
"Login",
"Signup",
"Profile",
],
"routes": Array [
Object {
"key": "Home-tT-YdLtMCFnkC8JeD-WHD",
"name": "Home",
"params": undefined,
},
Object {
"key": "Profile-LtAishscTlUhvi78A8k2R",
"name": "Profile",
"params": undefined,
"path": undefined,
},
],
"stale": false,
"type": "stack",
}
Any Solution for this one?!

React native Expo error trying to sign in with Google federated in apple device

I am trying to implement google federated sign in, with AWS Amplify, in react native manged flow by expo, and a get a weird error only in my apple physical device.
I followed the documentation in <https://docs.amplify.aws/lib/auth/social/q/platform/js/#full-samples> and got this code:
import React, { useEffect, useState } from 'react';
import { Button, Linking, Platform, Text, View } from 'react-native';
import * as WebBrowser from 'expo-web-browser';
import Amplify, { Auth, Hub } from 'aws-amplify';
async function urlOpener(url, redirectUrl) {
const { type, url: newUrl } = await WebBrowser.openAuthSessionAsync(
url,
redirectUrl,
);
if (type === 'success' && Platform.OS === 'ios') {
WebBrowser.dismissBrowser();
return Linking.openURL(newUrl);
}
}
const [
localRedirectSignIn,
productionRedirectSignIn,
] = awsconfig.oauth.redirectSignIn.split(",");
const [
localRedirectSignOut,
productionRedirectSignOut,
] = awsconfig.oauth.redirectSignOut.split(",");
Amplify.configure({
. "aws_project_region": "us-east-1",
"aws_cognito_identity_pool_id": "us-east-1:27777e6d-857e-4187-84b6-85a17891d320",
"aws_cognito_region": "us-east-1",
"aws_user_pools_id": "us-east-1_MLaD0VGx7",
"aws_user_pools_web_client_id": "6kanfftqjuu7pgv7415or1hkl9",
"oauth": {
"domain": "velpaf3732cb1-f3732cb1-dev.auth.us-east-1.amazoncognito.com",
"scope": [
"aws.cognito.signin.user.admin",
"email",
"openid",
"phone",
"profile"
],
"redirectSignIn": "exp://127.0.0.1:19000/--/,
"redirectSignOut": "exp://127.0.0.1:19000/--/,
"responseType": "token"
},
"federationTarget": "COGNITO_USER_AND_IDENTITY_POOLS",
"aws_appsync_graphqlEndpoint": "https://tlpmf7idfvextlpbc4qrrmwgfy.appsync-api.us-east-1.amazonaws.com/graphql",
"aws_appsync_region": "us-east-1",
"aws_appsync_authenticationType": "API_KEY",
"aws_appsync_apiKey": "da2-3tpwvu3nobf35bk4mmx3m3gfnq",
"aws_user_files_s3_bucket": "velpanewversion3d014069f75d4be1bc2875498e9be3dc193449-staging",
"aws_user_files_s3_bucket_region": "us-east-1"
});
function App() {
const [user, setUser] = useState(null);
useEffect(() => {
Hub.listen('auth', ({ payload: { event, data } }) => {
switch (event) {
case 'signIn':
getUser().then((userData) => setUser(userData));
break;
case 'signOut':
setUser(null);
break;
case 'signIn_failure':
case 'cognitoHostedUI_failure':
console.log('Sign in failure', data);
break;
}
});
getUser().then((userData) => setUser(userData));
}, []);
function getUser() {
return Auth.currentAuthenticatedUser()
.then((userData) => userData)
.catch(() => console.log('Not signed in'));
}
return (
<View>
<Text>User: {user ? JSON.stringify(user.attributes) : 'None'}</Text>
{user ? (
<Button title="Sign Out" onPress={() => Auth.signOut()} />
) : (
<Button title="Federated Sign In" onPress={() => Auth.federatedSignIn()} />
)}
</View>
);
}
export default App;
This is my awsExport:
const awsmobile = {
"aws_project_region": "us-east-1",
"aws_cognito_identity_pool_id": "us-east-1:27777e6d-857e-4187-84b6-85a17891d320",
"aws_cognito_region": "us-east-1",
"aws_user_pools_id": "us-east-1_MLaD0VGx7",
"aws_user_pools_web_client_id": "6kanfftqjuu7pgv7415or1hkl9",
"oauth": {
"domain": "velpaf3732cb1-f3732cb1-dev.auth.us-east-1.amazoncognito.com",
"scope": [
"aws.cognito.signin.user.admin",
"email",
"openid",
"phone",
"profile"
],
"redirectSignIn": "exp://127.0.0.1:19000/--/,exp://exp.host/#mateodelat/velpa/",
"redirectSignOut": "exp://127.0.0.1:19000/--/,exp://exp.host/#mateodelat/velpa/",
"responseType": "token"
},
"federationTarget": "COGNITO_USER_AND_IDENTITY_POOLS",
"aws_appsync_graphqlEndpoint": "https://tlpmf7idfvextlpbc4qrrmwgfy.appsync-api.us-east-1.amazonaws.com/graphql",
"aws_appsync_region": "us-east-1",
"aws_appsync_authenticationType": "API_KEY",
"aws_appsync_apiKey": "da2-3tpwvu3nobf35bk4mmx3m3gfnq",
"aws_user_files_s3_bucket": "velpanewversion3d014069f75d4be1bc2875498e9be3dc193449-staging",
"aws_user_files_s3_bucket_region": "us-east-1"
};
export default awsmobile;
When I do the sign in with google from my virtual emulator device I can do a successful login.
Logging from my physical apple device, I can open the web browser but once authorized from google, get the following screen:
Image error

React Native: Standalone, Expo built app on Android crashes when using Facebook login (works on iOS)

I have a React Native app I built using the Expo managed workflow. I am using Facebook login for my app along with Firebase authentication. My understanding is this can not be tested when running in the Expo app, and can only be used in a standalone app.
FB login is working fine in my iOS standalone app, however, in android, it crashes before the Facebook login screen even appears. My LandingPage loads, but as soon as I press the "Login With Facebook" button, it crashes.
Below is my app.json file and my login code. Per the instructions, I have also added the Facebook Key Hash to my project on the Facebook developer site. Can anyone help me understand what is wrong?
app.json:
{
"expo": {
"name": "Pick Up",
"slug": "PickUp",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/ball-and-glove-5.png",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"notification": {
"icon": "./assets/ball-and-glove-5.png",
"color": "#fff",
"androidMode": "default"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"**/*"
],
"ios": {
"supportsTablet": true,
"userInterfaceStyle": "light",
"config": {
"googleMobileAdsAppId": "ca-app-pub-xxxxxxxxxxxxxxxx~xxxxxxxxxx",
"googleMapsApiKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
"bundleIdentifier": "com.myapp.name",
"buildNumber": "1.0.0"
},
"userInterfaceStyle": "automatic",
"android": {
"useNextNotificationsApi": true,
"userInterfaceStyle": "dark",
"config": {
"googleMobileAdsAppId": "ca-app-pub-xxxxxxxxxxxxxxxx~xxxxxxxxxx",
"googleMaps": {
"apiKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
},
"package": "com.myapp.name",
"versionCode": 1
},
"web": {
"favicon": "./assets/favicon.png"
},
"facebookScheme": "fbxxxxxxxxxxxxxxxx",
"facebookAppId": "xxxxxxxxxxxxxxx",
"facebookDisplayName": "myname"
}
}
Login Code:
import React, { useState, useEffect, useContext } from 'react';
import { Alert, Animated, Image, StatusBar, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { Ionicons } from '#expo/vector-icons';
import * as WebBrowser from 'expo-web-browser';
import * as Facebook from 'expo-facebook';
import * as firebase from 'firebase';
import { loginUser } from '../../firebase.js';
import { StoreContext } from '../../contexts/storeContext';
const turquoise = "#4ECDC4";
const LandingPage = ({ navigation }) => {
const store = useContext(StoreContext);
const handleFacebook = async () => {
try {
await Facebook.initializeAsync();
const options = {
permissions: ["public_profile"]
}
const { type, token } = await Facebook.logInWithReadPermissionsAsync(options);
if (type === "success") {
const credential = firebase.auth.FacebookAuthProvider.credential(token);
if (credential) {
const bool = await loginUser(credential);
}
}
else {
Alert.alert("", "There was a problem. Please try again.");
}
}
catch (e) {
console.log("e : ", e);
Alert.alert("", e);
}
}
return (
<View>
<StatusBar barStyle="dark-content" backgroundColor={ turquoise } />
<View>
<TouchableOpacity onPress={ handleFacebook }>
<Ionicons name="logo-facebook" />
<Text>Continue with Facebookk</Text>
</TouchableOpacity>
<TouchableOpacity onPress={ () => navigation.navigate("PhoneVerification") }>
<Text>Use cell phone number</Text>
</TouchableOpacity>
</View>
<View>
<Image
resizeMode="contain"
source={require('../../assets/new-logo.png')}
/>
</View>
</View>
)
}
The issue was that for Android, Facebook.initializeAsync() needs to be passed an argument -- your FB appID.
const handleFacebook = async () => {
try {
await Facebook.initializeAsync("123456789"); // <-- your FB appID
const options = {
permissions: ["public_profile"]
}
const { type, token } = await Facebook.logInWithReadPermissionsAsync(options);
if (type === "success") {
const credential = firebase.auth.FacebookAuthProvider.credential(token);
// do the rest of your Firebase login logic
}
else {
Alert.alert("", "There was a problem. Please try again.");
}
}
catch (e) {
console.log("e : ", e);
Alert.alert("", e);
}
}

React Native Expo: Authentication with Identity Server 4

I am trying to use the sample code from expo documentation "https://docs.expo.io/guides/authentication/" for IdentityServer4. I have created a React template from ASP.NET Core Web Application. When I run the react native app to redirect to the login page of the ASP application I can login but the problem is the window does not close to return the token. It logs in and then I go to the home page of the ASP application. I believe I am missing the redirect URL or the client is not setup the right way. Can someone help me how to set this up? Or what part am I missing?
Here is my client set up from the ASP application from the appsettings.json:
"IdentityServer": {
"Clients": {
"AAA": {
"ClientId": "myclientid,
"ClientName": "Native Client (Code with PKCE)",
"RequireClientSecret": false,
"RedirectUris": [ "io.expo.auth/#username/Auth" ],
"AllowedGrantTypes": "GrantTypes.Code",
"RequirePkce": "true",
"AllowedScopes": ['openid', 'profile', 'email', 'offline_access'],
"AllowOfflineAccess": "true",
"Profile": "IdentityServerSPA",
"ClientSecrets": [
{
"Value": "secretvalue"
}
]
}
},
Below is my React Native app:
import * as React from 'react';
import { Button, Text, View } from 'react-native';
import * as AuthSession from 'expo-auth-session';
import * as WebBrowser from 'expo-web-browser';
WebBrowser.maybeCompleteAuthSession();
const useProxy = true;
const redirectUri = AuthSession.makeRedirectUri({
native: 'myApp://io.expo.auth/#username/Auth',
useProxy,
});
export default function App() {
const discovery = AuthSession.useAutoDiscovery('https://demo.identityserver.io');
// Create and load an auth request
const [request, result, promptAsync] = AuthSession.useAuthRequest(
{
clientId: 'myclientid',
redirectUri,
scopes: ['openid', 'profile', 'email', 'offline_access'],
},
discovery
);
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Button title="Login!" disabled={!request} onPress={() => promptAsync({ useProxy })} />
{result && <Text>{JSON.stringify(result, null, 2)}</Text>}
</View>
);
}
Here is what you need to fix on ur code:
On appsettings.json change RedirectUris to be a list, result would be like this:
"IdentityServer": {
"Clients": {
"AAA": {
"ClientId": "myclientid,
"ClientName": "Native Client (Code with PKCE)",
"RequireClientSecret": false,
"RedirectUris": [ "io.expo.auth/#username/Auth" ],
"AllowedGrantTypes": "GrantTypes.Code",
"RequirePkce": "true",
"AllowedScopes": [ "api" ],
"AllowOfflineAccess": "true",
"Profile": "IdentityServerSPA",
"ClientSecrets": [
{
"Value": "secretvalue"
}
]
}
},
Read more here
Make sure URL listed on RedirectUris exist, and it match the value set for redirectUri on the native client. I'm no expo expert, you may use some sort of middleware but as far as I understand from your code above these URLs dont match.
#nahidf: I have updated the url from the react native and the ASP app. The log in still is fine on the android app, but after I log in, the app stays open with the home page of that ASP app and not closing to return to react app and also return the token. Does the expo app have to be published because I am running it locally? Also, the ASP I have published it on a local server.