React Native - Firebase auth persistence not working - javascript

Firebase auth does not persist logged in user and everytime I refresh or reopen app I have to sign in again.
I have tried setting persistence to local and the callback does verify its set but the persistence is still no working
For setting persistence I am using...
//set auth persistence
firebase.auth().setPersistence(firebase.auth.Auth.Persistence.LOCAL)
.then(function() {
console.log("successfully set the persistence");
})
.catch(function(error){
console.log("failed to ser persistence: " + error.message)
});
.
.
.
For signing in I am using this code
firebase.auth().signInWithEmailAndPassword(email, password)
.then((user) =>{
this.checkAccountStatus(user.uid, user.email);
})
.catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
console.log(errorMessage)
// ...
});
And here is the code I am using to check login status...
if (firebase.auth().currentUser) {
const currentUser = firebase.auth().currentUser;
console.log("Signed in username" + currentUser.displayName);
this.props.navigation.navigate('AppTab');
}else{
console.log("no user signed in");
this.props.navigation.navigate('AuthTab');
}
if there anything I am not doing right

You don't need to set persistence. Firebase handles it for you by default. You just need to call this function to check whether user is logged or not:
firebase.auth().onAuthStateChanged((user) => {
if (user) {
console.log('user is logged');
}
});
This will not be triggered only if user has sign out or cleaned app data.
You can find more details in the official docs: https://firebase.google.com/docs/auth/web/manage-users
Hope it helps.

Make sure you do not restrict the 'Token Service API' in the console, with the API key you are using. I did not add the service to my key, and it logged me out every 3-4 hours, even with the right code suggested above.

Firebase now recommends to use firestore instead of realtime-database and it manages offline persistence by default. It is clear in its documentation here
You just need to access the user through this code:
if (auth().currentUser !== null) {
console.log('User is logged in');
console.log(auth().currentUser.email);
props.navigation.navigate('Home');
} else {
props.navigation.navigate('Login');
}
This code will prop you to home screen if user is logged-in, even when you close the app. To clear the user's credentials, you manually need to sign-out the user using this code.
try {
auth()
.signOut()
.then(props.navigation.navigate('Login'));
} catch (error) {
Alert.alert('Error', error.toString());
}
You can also check this simple app (used react hooks in it) for further assistance.

Related

Keep logged in between reloads - Firebase (Sign in with Google)

How do you keep a user logged in with Sign in with Google between reloads?
Here is my login function (Firebase):
const loginWithGoogle = async () => {
try {
const provider = new firebase.auth.GoogleAuthProvider();
const res = await firebase.auth().signInWithPopup(provider);
$user = res.user;
$isLoggedIn = true;
}
catch (error) {
console.log(error);
}
}
Although $isLoggedIn and the $user object save to LocalStorage (I'm using SvelteJS), the user does not actually stay logged in after reloading.
After reloading, admin users are no longer able to write to the database and I get the error firestore: PERMISSION_DENIED: Missing or insufficient permissions.
(Here are my firestore rules)
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read;
allow write: if (request.auth != null && (request.auth.uid == "someAdminID" || request.auth.uid == "otherAdminID"));
}
}
How would I stay logged in after reloading? Or is there some way to automatically log in again if the user had not previously logged out?
On most browser environments Firebase automatically persists the user credentials in local storage, and restores them when the app/page reloads. This requires it to make a call to the server however, a.o. to check if the account was disabled, and thus it isn't completed right away when the page loads.
To react to when the authentication state is restored (or otherwise changes), you'll want to use an auth state listener as shown in the first code snippet in the documentation on getting the currently signed in user:
firebase.auth().onAuthStateChanged((user) => {
if (user) {
// User is signed in, see docs for a list of available properties
// https://firebase.google.com/docs/reference/js/firebase.User
var uid = user.uid;
// ...
// 👈 This is where you can also query the database as the user for the first time
} else {
// User is signed out
// ...
}
});

Amplify w/Cognito: How do I get the Current User's Email?

I am using AWS Amplify, with Cognito for user Auth.
Users go into a user pool, and register and sign in just with email address and password.
When a user that has signed in through Cognito navigates to a certain page, I want to be retrieve their email address. How can I do this?
I am able to retrieve some user data with this code (I am using javascript/Angular):
import Auth from '#aws-amplify/auth';
...
ngOnInit(){
Auth.currentAuthenticatedUser().then((user)=>{
console.log('user = ' + JSON.stringify(user.pool))
})
}
The email does appear on the response, but I haven't yet been able to isolate the email from the returned JSON.
I've tried going through the docs, but I haven't yet found info on stuff like the attribute options I can add to currentAuthenticatedUser(), or if there is another method that is cleaner (which I assume there is).
EDIT: It looks like the following works:
Auth.currentAuthenticatedUser().then((user) => {
console.log('user email = ' + user.attributes.email);
});
But I am still hoping to understand the documentation better. I found this solution in a random github question, not the official docs. Where would I find this solution in the AWS Amplify / Cognito documentation?
import cognito from "../path/to/your/config/cognito.json";
import Amplify, { Auth, Hub } from 'aws-amplify';
...
...
useEffect(() => {
Amplify.configure({ Auth: cognito });
Hub.listen('auth', ({ payload: { event, data } }) => {
switch (event) {
case 'signIn':
console.log('Event name -> ', event, data)
// here is your name, email e.t.c.
console.log(data.signInUserSession.idToken.payload);
break
case 'signOut':
console.log('sign out')
// this.setState({ user: null })
break
default:
console.log('Unhandled use case - ' + event)
}
})
}, [])
You can check this one from the official documentation
and enable read access
General settings -> App clients -> Show details -> Set attribute read and write permissions link
and then to make sure you are fetching the updated attributes
Auth.currentAuthenticatedUser({ bypassCache: true })
Auth.currentSession()
.then((data) => {
// this data has user details in accessToken
}).catch(err => console.log(err));
The following works for me after the user is logged in...
import { Auth, Amplify } from 'aws-amplify'
console.log(Auth.user.attributes.email)

Firebase email/password authentication in electron

I did firebase authentication with email/password in my electron app, and it works, but only on first page. When I go to second page, I'm no longer signed in. Because I'm new to elecetron.js and firebase as well I used this tutorial:https://www.youtube.com/watch?v=bWS0ocfszmE.
login.js
loginBtn.addEventListener('click', function() {
var emailField = document.getElementById('email').value;
var passwordField = document.getElementById('password').value;
firebase.auth().signInWithEmailAndPassword(emailField, passwordField).then(function() {
document.location.href = 'mainPage.html';
console.log(firebase.auth().currentUser);
}).catch(function(error) {
if (error != null) {
console.log(error.message);
alertify.error(error.message);
return;
}
});
secondpage.js
var firebase = require("firebase/app");
require("firebase/auth");
console.log(firebase.auth().currentUser);
I expected the output in console with user that I signed in, but get null.
The problem is that on each new page Firebase Authentication will check whether the user's sign-in token is still valid. Since this may take some time (and require calling a server), this happens asynchronously. And by the time your console.log(firebase.auth().currentUser) runs, the process hasn't completed yet.
That's why you'll want to use an onAuthStateChanged listener to detect the authentication state of the user:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
} else {
// No user is signed in.
}
});

firebase - Firebase Current User not storing the correct user

I have a project using Firebase for the authentication. When I log into my project, sometimes the firebase.auth().currentUser method returns info from some other user. Sometimes I get the info from the actual current user and sometimes the previously signed in user - when this happens, the only way to correct the problem and get data for the correct user is to logout and sign back in again.
My login method:
onLoginClick = () => {
firebase.auth().signInWithEmailAndPassword(this.state.email.trim(), this.state.password.trim())
.then((user) => {
//Some redirects depending on my users role
})
.catch((error) => {
console.log(error, error.message);
if (error.code == "auth/user-not-found" || error.code == "auth/wrong-password") {
//Handle error
}
});
}
And my Logout method:
onLogoutClick = () => {
firebase.auth().signOut().then(function () {
this.props.history.replace("/")
}).catch(function (error) {
console.log(error);
});
}
They're pretty standard but seems like I'm doing something wrong. I've tried clearing the sessionStorage and the localStorage on the logout method but that didn't help.
UPDATE:
I've tried with some suggestions like doing:
firebase.auth().signOut().then(() => {
firebase.auth().signInWithEmailAndPassword(email, password).then((user) => {
//My redirects and everything
})
})
But this doesn't work.
Also, I've noticed that when I log in and use wrong credentials, the sessionStorage gets an entry with the previously signed in user, even though I signed him out.
I'm pretty sure that during the initialization of a new login session, until it is complete, currentUser hasn't been updated yet; use the user parameter when one is passed in on those methods. Because the login is still in progress, there is not yet a currentUser, so it passes the user in progress via the user parameter. (I think this means it is likely that it will be null the first time someone logs in, and it will be the previous one thereafter, unless it's cleared on logout by some code.)
Use the user parameter when it is provided, such as in the onAuthStateChanged handler. See the first example here, and the starred note in the blue box farther down that same page.

using event.preventDefault() in ui-router causes infinite loop

error:
Yes i know there have been posts similar to this one but they do not address my issue. I want to take full control of the app's routing.My code is as follows:
a few things to note would be that i have attached a custom property to my states called authenticate which has a true or false value. I have also created a simple function, get user. All it does is retrieve the user from the api.
$rootScope.$on('$stateChangeStart', function(event, toState) {
event.preventDefault();
let token = $cookies.get('token');
if (toState.authenticate) {
if (token) {
getUser()
.then(user => {
$rootScope.user = user;
$state.go(toState.name);
})
.catch(err => console.log(err));
} else {
$state.go('login');
}
} else {
$state.go(toState.name);
}
});
I first check if the state requires authentication. If it does not we simply continue to the state. If it does require authentication we check if there is a token. if there is we fetch the user using the function I mentioned earlier. If there isn't a token we send the user to the login state.

Categories

Resources