I'm using firebase.auth().signOut() to log a user out of his Google account. However, when I the user logs in again using firebase.auth().signInWithPopup(provider) (const provider = new firebase.auth.GoogleAuthProvider()), he immediately gets logged in to the Google account he was last logged in with. No password request, no UI, nothing. Just a short loading animation and the user is logged in again.
What do I have to do so the user can switch to a different Google account? At the moment it's simply not possible.
A little late response but hope it helps.
You can add a custom parameter to the auth provider to force picking an account each time.
const provider = new firebase.auth.GoogleAuthProvider();
provider.setCustomParameters({
prompt: 'select_account'
});
firebase.auth().signInWithPopup(provider)
Related
I have been reading the user documentation for browser login Persistence at Google Documentation. However its not clear enough, on what I should be doing for v9. Briefly here's what I understood. There are three types of persistence's: Per Session, Per Browser, and None. So now what I wanted to do was set Persistence for "per Browser". I saw two functions being used, one is inMemoryPersistence which I assumed to be per Browser and the other to be browserSessionPersistence which i assumed to be "per Session". However even after trying with both of them, after closing the tab and reopening its sends me to the login page.
const auth = getAuth();
setPersistence(auth, browserSessionPersistence)
.then(() => {
// Existing and future Auth states are now persisted in the current
// session only. Closing the window would clear any existing state even
// if a user forgets to sign out.
// ...
// New sign-in will be persisted with session persistence.
return signInWithEmailAndPassword(auth, email, password);
})
.catch((error) => {
// Handle Errors here.
const errorCode = error.code;
const errorMessage = error.message;
});
My code is just the same as what's provided in the docs, with browserSessionPersistance being one of two parameters I tried.
So my question is:
Is my understanding of the 3 Types Correct?
If it is, then why isn't browser persistence working?
(Also I'm using Vanilla Javascript with Modular Import)
If you want to persist auth state and required explicit logout, use browserLocalPersistence.
Version V8 firebase.auth.Auth
Version V9
Description
Persistence.LOCAL
browserLocalPersistence
Explit logout required
Persistence.SESSION
browserSessionPersistence
current session or tab, cleared when closed
Persistence.NONE
inMemoryPersistence
in memory, not persisted, cleared when page is refreshed
Also checkout Persistence interface in the documentation.
So I followed this tutorial on how to sign in a user with rnfirebase and google signup. And it works fine. Here is the code:
const googleSignUp = async () => {
// 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
const user = auth().signInWithCredential(googleCredential);
return { idToken, user };
};
(Let me note here, that the app has already a sign in with email and password way, with Firebase).
Then I realized that the user cannot change his name, email or delete his account.
Looking deeper, I found out that the onAuthStateChanged(firebase.auth, async (user) => ... returns null for the user.
I've seen in some older answers that if you use Google sign up, you need to sign up the user with signInWithCredential, which I use, so this in not the issue.
Could it be a problem that for email/password sign in, I use code from Firebase web and not from rnfirebase? Although I already had a combination of those, using the push notifications from rnfirebase.
Can someone explain why I get this behavior, and how to fix it?
Thanks!
If I understand correctly, you use both the react-native-firebase library (which wraps the native iOS and Android SDKs) and the JavaScript Web SDK for Firebase in your app.
If that is the case, both indeed have a separate sign-in state, and signing into one won't fire onAuthStateChanged listeners on the other.
You'll have to pick one SDK to authenticate with Firebase, and then use that for both providers.
In Firebase JavaScript v8, if you want to ask Google to show the account selection page every time you login, you can do:
var provider = new firebase.auth.GoogleAuthProvider();
provider.setCustomParameters({
prompt: 'select_account'
});
But with the more modular design of v9, the above syntax is not possible. How do you achieve the same result (ie., ask Google Signin to show an account selection page every time the user logs in) in this newer version of Firebase?
So, after some time I stumbled onto the same documentation that I had read before. Not sure whether they've added it recently or if my eyes were malfunctioning before, what I wrote as "not possible" in the original question is actually possible. From the documentation:
provider.setCustomParameters({
'login_hint': 'user#example.com'
});
How about writing the below code:
import { GoogleAuthProvider } from "firebase/auth";
const provider = new GoogleAuthProvider({
prompt: "select_account"
});
I am building a login page in my React app using firebase (sign in with google redirect the user method)
and it is working but it takes almost two seconds for firebase to get the current user, which is not the best for UX.
here is the code
componentDidMount(){
console.log(Date.now());
const auth = getAuth();
this.authListener = onAuthStateChanged(auth, (user) => {
if (user) {
// User is signed in
console.log(Date.now());
this.props.dispatch(addUserAction(user.email))
}
else {
// User is signed out
this.props.dispatch(addUserAction(null))
}
});
}
what i get in my console is that the difference of time is 1768 milliseconds which is almost 2 seconds,
am i doing something wrong ?
the console is showing the difference of time as 2 seconds
When you restart the app/reload the page, Firebase automatically restores the user's authentication state based on the information it stored in local storage when the user first signed in. For this it does make a call to the server though, to check whether the credentials are still valid - and for example to ensure the account hasn't been disabled. It's likely that this call is what is taking time in your use-case.
A common trick is to make your own determination on whether the server-check is likely to succeed based on only client-side information. For this, store an extra value in local storage when the user signs in successfully, say isAuthenticated. Now when you reload the page/app, you an read this value from local storage, and then the user was previously authenticated, assume that they will be authenticated again.
The assumption may be wrong of course, so you'll have to handle that scenario too in your code.
Also see this talk Architecting Mobile Web Apps, where Michael Bleigh talks about the technique.
I have created an app with Electron that allows users to sign-in and sign-out.
On logout, I delete all information stored in keytar (access tokens, etc.)
I then call oAuth2Client.revokeCredentials() when logging out.
const { google, GoogleApis } = require('googleapis')
const oAuth2Client = new google.auth.OAuth2(
credentials.client_id,
credentials.client_secret,
credentials.redirect_uris[1]
)
async function logout() {
console.log('Logging out....')
await keytar.deletePassword(keytarService, keytarAccount)
await oAuth2Client.revokeCredentials()
}
However, when the user opens the app again, and they get the login screen, their Google Account is still there where all they have to do is click on it. They don't have to login again, they don't have to enter a password, and they don't have to use 2FA again.
What I am looking for is, when a user logs out of my Desktop Application, they are completely Logged out with no Google remnants left behind, such that, when they open the Application the next time, they have to re-enter a user name and a password and use their 2FA.
The reason behind the users seeing their google account logged in, is that the users didn't logout of their google account, so all the session cookies are stored in your renderer and revoking the tokens in your main process will not revoke the tokens in your renderer process. In order to clear the users session data from your renderer, what you can do is that, you can clear the storage from that renderer as shown below.
// Before quitting the window, clear the storage so all the cookies related to google are cleared
AuthWindow.webContents.session.clearStorageData().then(function (data) {
AuthWindow.destroy();
});
Next time when the users opens their app again, they will need to login their account using their credentials as all the session data related to their account is cleared now.