Reputation: 473
I'm trying to impliment auth with persistance in angularfire with this code:
constructor(private auth: Auth, private router: Router) {
if (auth.currentUser) this.router.navigate(this.redirect);
}
async loginWithGoogle() {
const provider = new GoogleAuthProvider();
try {
await setPersistence(this.auth, browserLocalPersistence);
await signInWithPopup(this.auth, provider);
this.message = 'Sign in successful';
await this.router.navigate(this.redirect);
} catch (error: any) {
console.error(error);
if (error.code) {
this.message = `${error.code}: ${error.message}`;
} else {
this.message = 'There was a problem signing in. Please try again.';
}
}
}
However, i always get this error, no matter the placement of the setPersistence
method:
Class constructor BrowserLocalPersistence cannot be invoked without 'new'
I followed the docs (https://firebase.google.com/docs/auth/web/auth-state-persistence) to the T; what am i doing wrong?
I am using Angular 13, Angularfire 7 and Firebase 9.
Upvotes: 6
Views: 2273
Reputation: 522
this is the correct format:
this.auth.setPersistence(browserLocalPersistence).then(e=>{ ...... .... })
https://github.com/angular/angularfire/issues/3131
Upvotes: 2
Reputation: 7491
I have experienced this exact issue - unclear on the cause but I found that if I imported the methods directly from the firebase libraries I could resolve them.
Specifically I import these features like so:
import { browserLocalPersistence,browserSessionPersistence, setPersistence } from 'firebase/auth';
as opposed to from '@angular/fire/auth'
Then it all works perfectly (as it would in a vanilla javascript application).
Upvotes: 6
Reputation: 993
I have left my implementation of login with provider below.
Although I have not migrated to the Modular Firebase V9 in this project yet, the auth persistence still works the same- users who have logged in once don't need to re-login each time they come back.
I have found it to be good practice to leave auth logic in services that can be injected into your components or modules.
In the constructor you can find a nice way to determine if your users' are logged in and have a profile associated with their auth ID in Cloud Firestore.
export class AuthService {
analytics = firebase.analytics(); // this declaration works better than constructor init from import
userCredential; // to store the promise returned when signing up/ in with email & password
// type: User from the model
user$: Observable<User>; // defined as observable as it can change when user signs in/out
constructor(
// inject imports for fire store auth service in constructor
private afAuth: AngularFireAuth,
private afs: AngularFirestore,
private router: Router
) {
// Get the auth state, then fetch the Firestore user document or return null
this.user$ = this.afAuth.authState.pipe( // define the observable state
switchMap(user => {
// Logged in
if (user) { // if user is defined
// point to document with matching ID
return this.afs.doc<User>(`users/${user.uid}`).valueChanges();
} else {
// Logged out
return of(null); // allows us to tell when user is not logged in
}
})
);
}
/**
* Authenticate users with Google O-Auth provider
* @param {boolean=} [registration = false] - whether this is the first sign in or not
*/
async googleSignIn(registration: boolean = false) {
// reference google auth provider
const provider = new auth.GoogleAuthProvider();
// pass provider to sign in with popup functionality
this.userCredential = await this.afAuth.signInWithPopup(provider);
if (registration) { // if the request is coming from the registration page
try {
await this.insertNewUser(this.userCredential.user, this.userCredential.user.displayName);
await this.verifyEmail(); // send a verification email to the user when registering
await this.router.navigate(['/user-profile']);
} catch (err) {
console.log(`Error: ${err.errorMessage}`);
M.toast({html: `Error: ${err.errorMessage}`, classes: 'rounded materialize-red'});
}
} else { // user is logging in again
try {
await this.router.navigate(['/user-profile']);
M.toast({html: `Signed in as ${this.userCredential.user.displayName}`, classes: 'rounded blue'});
// let user know that they haven't been verified
if (!this.userCredential.emailVerified) {
console.log(`user's email has not been verified`);
M.toast({
html: `Your email has not yet been verified. Please check your inbox.`,
classes: 'rounded orange darken-2'
});
}
} catch (err) {
console.log(`Error: ${err.errorMessage}`);
M.toast({html: `Error: ${err.errorMessage}`, classes: 'rounded materialize-red'});
}
}
// track the login event with analytics
this.analytics.logEvent('login', {serviceName: 'Google Login'});
} // end of sign in function
} // end of auth service
Upvotes: -1