I am on the way to create my first Progressive web app which uses firebase for storing data. I am also using Gmail
as an entry point for all the users that would us
I had almost same behavior on my pet web app. For my self I solve it by the next steps:
app.module.ts
@NgModule({
...
providers: [
{ provide: APP_INITIALIZER, useFactory: appConfig, deps: [AuthService], multi: true }
]
})
export function appConfig(authService) {
const app = firebase.initializeApp({
apiKey
authDomain
});
return () => new Promise((resolve, reject) => {
firebase.auth()
.onAuthStateChanged(data => {
if (data) {
firebase.auth().currentUser.getToken()
.then((token: string) => authService.setToken(token););
}
resolve(true);
}, error => resolve(true));
});
}
auth.guard.ts
export class AuthGuard implements CanActivate {
constructor(
private authService: AuthService,
private router: Router
) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if (this.authService.isAuthenticated()) {
return true;
} else {
this.router.navigate(['/signin']);
return false;
}
}
}
auth.service.ts
export class AuthService {
token: string;
signinUser(email: string, password: string) {
return new Promise((resolve, reject) => {
firebase.auth().signInWithEmailAndPassword(email, password)
.then(resp => {
firebase.auth().currentUser.getToken()
.then((token: string) => {
this.token = token;
resolve(resp);
}).catch(reject);
return resp;
})
.catch(reject);
});
}
signoutUser() {
return firebase.auth().signOut()
.then(resp => this.token = null);
}
getToken() {
firebase.auth().currentUser.getToken()
.then((token: string) => this.setToken(token));
return this.token;
}
setToken(token) {
this.token = token;
}
isAuthenticated() {
return this.token != null;
}
}
I hope it will be helpful for you.
Looks like on mobile your app opens authentication not a new tab of your current browser but in a new browser, so it cannot make a valid redirect back to your initial browser after authentication with Google. If you will sign in with redirect you will stay in the same browser, so you need to change your service to:
loginWithGoogle() {
return this.afAuth.auth.signInWithRedirect(new firebase.auth.GoogleAuthProvider());
}
The redirect auth does not work on PWAs (likely uses different browser instances in some cases). You can get around this by using the pop-up auth flow:
https://firebase.google.com/docs/auth/web/google-signin
It would look something like this:
firebase.auth().signInWithPopup(provider).then(function(result) {
// This gives you a Google Access Token. You can use it to access the Google API.
var token = result.credential.accessToken;
// The signed-in user info.
var user = result.user;
// ...
}).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
// ...
});
Only flow difference is that it launches a pop up browser window, instead of redirecting the current instance. This simplifies some of the logic for getting the auth result as well. If you prefer to retain the normal flow on non-PWAs, you can detect if the app was launched from home screen:
https://developers.google.com/web/updates/2015/10/display-mode