I develop a react-native (expo) mobile app and try to sign in with a google account to firebase, but I get an error:
"auth/operation-not-supported-in-this-enviroment. This operation is not supported in the enviroment this application is running on. "location.protocol" must be http, https or chrome-extension and web storage must be enabled"
Code:
loginGoogle() {
var provider = new firebase.auth.GoogleAuthProvider();
provider.addScope('profile');
provider.addScope('email');
firebase.auth().signInWithPopup(provider).then(function(result) {
var token = result.credential.accessToken;
var user = result.user;
return true;
}).catch(function(error) {
alert(error.code + '\n' +
error.message + '\n' +
error.email + '\n' +
error.credential);
return false;
});
}
signInWithPopup is not supported in react-native. You will need to use a third party OAuth library to get the OAuth ID token or access token and then sign in with Firebase:
const cred = firebase.auth.GoogleAuthProvider.credential(googleIdToken, googleAccessToken);
firebase.auth().signInWithCredential(cred)
.then((result) => {
// User signed in.
})
.catch((error) => {
// Error occurred.
});
Firebase does not support signInWithPopup in a React Native environment.
You can view a full list of supported environments on this page.
You can also submit a feature request for extended Firebase support for React Native here.
If you are using expo bare workflow or simple React native cli (or in simple words which contain android and ios folder) then simply use "React Native Firebase" library.
Here is the link https://rnfirebase.io/
But if you are using expo managed workflow(which donot contain android and ios folder ) then you have to follow below steps .
1.setup google developer account
use this guide to setup : https://docs.expo.dev/versions/latest/sdk/google/
Note that: use host.exp.exponent as the package name.
Another problem you may face in this step is generation of hash,which I also faced,the reason for that error is java dev kit(JDK) is not install ,so do install it before proceeding to this step.
2.Setup Firebase account
Simply setup firebase project as you set before, enable google sign in service
but this time the only change is you have to add client ID of your google developer account in (safest client id field) which will popup once you click on edit Google signin in firebase
look like this
3.Coding Part
import * as Google from 'expo-google-app-auth'; //imported from expo package
import {
GoogleAuthProvider,getAuth
} from 'firebase/auth';
import { initializeApp } from "firebase/app";
import { firebaseconfig } from '[your firebase credentials]';
const app=intitializeApp(firebaseconfig)
const auth=getAuth(app);
async function signInWithGoogleAsync() {
try {
const result = await Google.logInAsync({
androidClientId: 'cliend id from google dev console',
iosClientId: 'client id from google dev console for ios app(if you setup)',
scopes: ['profile', 'email'],
});
if (result.type === 'success') {
console.log(result)
const credential = GoogleAuthProvider.credential(result.idToken, result.accessToken);
// Sign in with credential from the Facebook user.
signInWithCredential(auth, credential)
.then(async result => {
console.log(result)
})
.catch(error => { console.log(error) });
return result.accessToken;
} else {
console.log("cancelled by user")
return { cancelled: true };
}
} catch (e) {
console.log(e);
return { error: true };
}//
}
Related
When the Google button is clicked in the application, if the process is successful, I take the user's e-mail address and send it to the backend. This situation works in debug mode, but does not work after publishing the application in the market. iOS works fine. The only error I can find in logcat is as follows. How can I solve this problem?
2023-01-12 13:20:37.361 2577-12107/? W/Auth: [GetTokenResponse] No token found in response, service=oauth2:email openid profile [CONTEXT service_id=153 ]
import React from "react"
import { Button } from "react-native"
import { GoogleSignin } from '#react-native-google-signin/google-signin';
import auth from '#react-native-firebase/auth';
export default function AuthScreen() {
async function onGoogleButtonPress() {
// 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
return auth().signInWithCredential(googleCredential).then((response: any) => {
console.log(response.user.email)
// send email to the backend..ƒ
})
}
return (
<Button
title={"google signin"}
onPress={() => onGoogleButtonPress().then(() => console.log('Signed in with Google!'))}
/>
)
}
I'm attempting to set up push notifications using Twilio Conversations and Firebase Cloud Messaging on a Next.js 12 app. The documentation is written with the assumption of using Firebase 8 syntax, but I'm using Firebase 9 in this scenario. I've been struggling to get push notifications to work while the page is open. I have the service worker set up (per Firebase docs) but it doesn't seem to be recognizing that a new message is being received from Twilio in order to actually show the notification.
Docs I've followed:
https://www.twilio.com/docs/conversations/javascript/push-notifications-web
https://firebase.google.com/docs/cloud-messaging/js/client
What I've tried
On my backend, I pass the Push Credential SID when I construct a new ChatGrant:
const chatGrant = new ChatGrant({
pushCredentialSid: process.env.TWILIO_PUSH_CREDENTIAL_SID,
serviceSid: CONVERSATIONS_SID
});
In the frontend, I followed the Twilio documentation to set up Firebase:
init.ts
import { getMessaging, getToken, onMessage } from "firebase/messaging";
import { initializeApp } from "firebase/app";
import { Client } from "#twilio/conversations";
// Omitted
const firebaseConfig = {};
export function getPermission(client: Client) {
const app = initializeApp(firebaseConfig);
const messaging = getMessaging(app);
getToken(messaging, { vapidKey:"KEY" })
.then((data) => {
console.log({ data });
client.setPushRegistrationId("fcm", data).catch((error) => {
console.error({ error });
});
onMessage(messaging, (payload) => {
console.log({ payload });
client.handlePushNotification(payload).catch((error) => {
console.error(error);
// test
});
});
})
.catch((error) => {
console.error(error);
// test
});
}
I call getPermission from this file once when the conversation app loads.
// chatClient is stored in a ref so it doesn't recalculate/refetch/reauthorize all the time
const chatClient = useRef(null);
// [Other code]
chatClient.current = new ConversationClient(data.chatAccessToken);
chatClient.current.on("connectionStateChanged", async (state) => {
switch (state) {
case "connected": {
// Only get permission once the chat client is fully set up
getPermission(chatClient.current);
// ..........
And my service worker firebase-messaging-sw.js:
importScripts('https://www.gstatic.com/firebasejs/9.14.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/9.14.0/firebase-messaging-compat.js');
if (!firebase.apps.length) {
firebase.initializeApp({
// CONFIG GOES HERE
});
}
const messaging = firebase.messaging();
//background notifications will be received here
messaging.onBackgroundMessage(function(payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
const notificationTitle = 'Background Message Title';
const notificationOptions = {
body: 'Background Message body.',
icon: '/android-chrome-192x192.png'
};
self.registration.showNotification(notificationTitle, notificationOptions);
});
What's happening
In the service worker, messaging.onBackgroundMessage never appears to be invoked. I don't know where this issue is derived from - is Twilio not passing message info to Firebase? Or is Firebase not listening to when Twilio sends it the information? Has that changed from v8 to v9?
In init.ts, onMessage is never invoked. Same deal here, is Twilio not passing the right information to Firebase, or did I misconfigure something?
I'm not getting any console errors or warnings, and the network tab is not pointing out anything super helpful.
I got this to work by using the example code (from docs) and configuring my Next.js application to compile the TypeScript into JavaScript. This helped a lot: https://github.com/vercel/next.js/issues/33863#issuecomment-1140518693
Been facing this issue
"You have created a new client application that uses libraries for user authentication or authorization that will soon be deprecated. New clients must use the new libraries instead; existing clients must also migrate before these libraries are deprecated. See the Migration Guide for more information."
How to sign in with google now if they have block client ID for new users
as google will deprecate their old sign in library
https://developers.googleblog.com/2021/08/gsi-jsweb-deprecation.html
you can now implement their new google service identity SDK https://developers.google.com/identity/gsi/web
or if you are using react, I made a small package https://www.npmjs.com/package/#react-oauth/google
it is using the new SDK
I was having this issue and solved it using this answer
import React, { useEffect } from 'react';
import { GoogleLogin, GoogleLogout } from 'react-google-login';
import env from 'react-dotenv';
import { gapi } from 'gapi- script';
function AuthPage() {
useEffect(() => {
function start() {
gapi.client.init({
clientId: env.REACT_PUBLIC_GOOGLE_CLIENT_ID,
scope: 'email',
});
}
gapi.load('client:auth2', start);
}, []);
// **you can access the token like this**
// const accessToken = gapi.auth.getToken().access_token;
// console.log(accessToken);
const onSuccess = response => {
console.log('SUCCESS', response);
};
const onFailure = response => {
console.log('FAILED', response);
};
const onLogoutSuccess = () => {
console.log('SUCESS LOG OUT');
};
return (
<div>
<GoogleLogin
clientId={env.REACT_PUBLIC_GOOGLE_CLIENT_ID}
onSuccess={onSuccess}
onFailure={onFailure}
/>
<GoogleLogout
clientId={env.REACT_PUBLIC_GOOGLE_CLIENT_ID}
onLogoutSuccess={onLogoutSuccess}
/>
</div>
);
}
export default AuthPage;
I've faced the same issue, like you.
This is how I solved it in my React Application. https://stackoverflow.com/a/72944782/15145736
it will solve the problem
For angular developers,
a repository with an example of how to use the new google sign in:
https://github.com/ShemiNechmad/GoogleSignInAngular
Check the readme.md file for instructions.
I am trying to implement google sign in on my app and every thing running well , it ask me to choose account on press of sign in button but it response it send me code 16 "CANCELLED" error.
I've installed library by npm install react-native-google-sign-in.
Then I linked it. I created a new project on firebase and download google-services.json from there and paste it in android/app. Also generated release SHA1 and add in firebase project.
componentDidMount() {
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 client id',
});
}
Google sign in button and action
<TouchableOpacity
onPress={() => _signIn()}
style={{height:50,width:50,borderRadius:50}}
>
<Image
style={{height:50,width:50}}
resizeMode='contain'
source={ImagePath.GOOGLE_ICON}
/>
</TouchableOpacity>
_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();
alert(JSON.stringify(userInfo))
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 {
alert(JSON.stringify(error))
console.log('Some Other Error Happened',error);
}
}
};
These are my signing config
release {
if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
storeFile file(MYAPP_RELEASE_STORE_FILE)
storePassword MYAPP_RELEASE_STORE_PASSWORD
keyAlias MYAPP_RELEASE_KEY_ALIAS
keyPassword MYAPP_RELEASE_KEY_PASSWORD
}
}
I expect successful google sign in and user data in response. Any kind of help will be appreciated.Thank you
The fix to this is to add SHA1 to the firebase.
If you are testing for debug build then add debug SHA1 and for release build use release SHA1.
After adding SHA1 certificate fingerprints to the firebase.
Download and add the firebase google-services.json file to /android/app/
You can create a debug key by below command
cd android
gradlew signingReport
OR
cd android && ./gradlew signingReport
Reference link
Please share your AndroidManifest.xml file. Please check whether you have added any launch mode in manifest. If so please remove.
I have an Outlook add-ins using React + TypeScript, debugging locally with Node.js. I'm using the office-js-helpers library to authenticate and the msgraph-sdk-javascript Graph client library. As a POC I'm simply trying to verify that I can successfully call Graph, by retrieving details of the current email by its id. I can successfully use the office-js-helpers Authenticator to authorize the app, and successfully retrieve a token.
However, when I use the Graph client to make a call to v1/me/messages/{ID}, I get:
"401 InvalidAuthenticationToken: Access token validation failure"
I'm not sure whether this is a problem with the way I'm using the Authenticator, or a problem with my add-in or app's manifests. My add-in is using these for AppDomains:
<AppDomains>
<AppDomain>https://localhost:3000</AppDomain>
<AppDomain>https://login.microsoftonline.com</AppDomain>
</AppDomains>
I am using https://localhost:3000 as my app's redirect URI, with implicit auth enabled.
If I use the force option with the authenticate method, I also get this error:
Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('https://login.microsoftonline.com') does not match the recipient window's origin ('https://localhost:3000').
However, I am able to retrieve a token.
What am I doing wrong? I'm not certain about the flow for the Authenticator, in terms of when to use authenticator.tokens.get and authenticator.authenticate. For the first run I assume always authenticate and no need to use tokens.get, and for second run I assume just use tokens.get, but if I try either of those or always both it doesn't seem to change the result of an invalid token.
import * as React from "react";
import { Button, ButtonType, TextField } from "office-ui-fabric-react";
import { Authenticator, Utilities, DefaultEndpoints } from "#microsoft/office-js-helpers";
import * as Graph from "#microsoft/microsoft-graph-client";
export default class GetItemOJSHelpers extends React.Component<any, any> {
constructor(props) {
super(props);
this.getEmail = this.getEmail.bind(this);
this.callGraph = this.callGraph.bind(this);
this.getItemRestId = this.getItemRestId.bind(this);
this.state = { graphResponse: "", accessToken: "" };
console.log("====GetItemOJSHelpers loaded");
}
getEmail() {
console.log("====getEmail(): Entered ");
//debugger;
// Get the access token and create a Microsoft Graph client
let authenticator = new Authenticator();
// register Microsoft (Azure AD 2.0 Converged auth) endpoint
authenticator.endpoints.registerMicrosoftAuth("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", {
redirectUrl: "https://localhost:3000/index.html",
scope: "Mail.ReadWrite User.Read User.ReadBasic.All"
});
console.log("====getEmail(): Getting token");
let authObject = authenticator.tokens.get("Microsoft");
let accessToken = authObject.access_token;
if (accessToken !== null) {
console.log(`====getEmail(): Current cached token: ${accessToken}`);
this.callGraph(accessToken);
return;
} else {
// for the default Microsoft endpoint
//If the user, rejects the grant to the application then you will receive an error in the catch function.
authenticator
.authenticate(DefaultEndpoints.Microsoft)
.then(function(token) {
/* Microsoft Token */
console.log(`====getEmail(): Authenticated; auth token: ${token.access_token}`);
accessToken = token.access_token;
})
.catch(function(error) {
//debugger;
console.log("====getEmail(): authenticate error");
Utilities.log(error);
throw new Error("Failed to login using your Office 365 Account");
});
}
console.log(`====getEmail(): Current token: ${accessToken}`);
this.callGraph(accessToken);
}
callGraph(token) {
// Get the item's REST ID
let itemId = this.getItemRestId();
console.log(`====callGraph(): itemId ${itemId}`);
const client = Graph.Client.init({
authProvider: done => {
done(null, token); //first parameter takes an error if you can't get an access token
},
debugLogging: true
});
client
.api("me/messages/" + itemId)
.version("v1.0")
.get()
.then(function(item) {
//debugger;
console.log("Email " + item.Subject + " retrieved!!!");
})
.then(function() {
console.log("====callGraph(): complete");
//debugger;
})
.catch(err => {
//debugger;
//403 Forbidden! code: "ErrorAccessDenied", message: "Access is denied. Check credentials and try again."
//Also 401 InvalidAuthenticationToken: Access token validation failure.
console.log(`====callGraph(): error! ${err.statusCode}:'${err.code}': ${err.message}`);
});
}
getItemRestId() {
if (Office.context.mailbox.diagnostics.hostName === "OutlookIOS") {
// itemId is already REST-formatted
return Office.context.mailbox.item.itemId;
} else {
// Convert to an item ID for API v2.0
return Office.context.mailbox.convertToRestId(
Office.context.mailbox.item.itemId,
Office.MailboxEnums.RestVersion.v2_0
);
}
}
render() {
return (
<div>
<Button
id="getEmailButton"
className="ms-welcome__action ms-bgColor-red"
buttonType={ButtonType.primary}
onClick={this.getEmail}
>
Call Graph
</Button>
<div>
<h3> Access Token </h3>
<TextField id="accessToken" />
</div>
<div>
<h3>Graph API Call Response</h3>
<TextField id="graphResponse" />
</div>
</div>
);
}
}