nebular
nebular copied to clipboard
IsAuthenticatedOrRefresh doesn't work with firebase
Issue type
I'm submitting a ... (check one with "x")
- [*] bug report
- [ ] feature request
Issue description
Current behavior:
Throwing error Error: 'refreshToken' is not supported by 'NbFirebaseGoogleStrategy', use 'authenticate'
While if you autheticate without nebular with AngularFire this problem doesn't happen, and I think it could be related to this https://stackoverflow.com/a/37908468/2279488
Expected behavior:
Token doesn't expire until user signed out
Steps to reproduce:
- enabling NbFirebaseGoogleStrategy based on documentations
- calling
this.authService.isAuthenticatedOrRefresh()in authGuard
Related code:
import { NbAuthSocialLink } from '@nebular/auth';
import { NbFirebaseGoogleStrategy, NbFirebasePasswordStrategy } from '@nebular/firebase-auth';
const socialLinks: Array<NbAuthSocialLink> = [{
link: 'google',
icon: 'google',
title: 'google',
}];
export const defaultAuthSettings: any = {
forms: {
login: {
strategy: 'password',
rememberMe: true,
socialLinks: socialLinks,
},
register: {
strategy: 'password',
terms: true,
socialLinks: socialLinks,
},
logout: {
strategy: 'password',
},
requestPassword: {
strategy: 'password',
socialLinks: socialLinks,
},
resetPassword: {
strategy: 'password',
socialLinks: socialLinks,
},
validation: {
password: {
required: true,
minLength: 6,
maxLength: 50,
},
email: {
required: true,
},
fullName: {
required: false,
minLength: 4,
maxLength: 50,
},
},
},
strategies: [
NbFirebasePasswordStrategy.setup({
name: 'password',
login: {
redirect: {
success: '/',
},
},
register: {
redirect: {
success: '/',
},
},
logout: {
redirect: {
success: 'auth/login',
},
},
requestPassword: {
redirect: {
success: 'auth/login',
},
},
resetPassword: {
redirect: {
success: 'auth/login',
},
},
}),
NbFirebaseGoogleStrategy.setup({
name: 'google',
}),
],
};
Other information:
npm, node, OS, Browser
<!--
Node, npm: `node --version` and `npm --version`
OS: Windows (7/8/10). Linux (incl. distribution). macOS (El Capitan? Sierra?)
Browser: Chrome/Safari/Firefox/etc?
-->
Angular, Nebular
"@angular/animations": "~11.0.5",
"@angular/cdk": "^11.0.3",
"@angular/common": "~11.0.5",
"@angular/compiler": "~11.0.5",
"@angular/core": "~11.0.5",
"@angular/fire": "^6.1.4",
"@angular/forms": "~11.0.5",
"@angular/platform-browser": "~11.0.5",
"@angular/platform-browser-dynamic": "~11.0.5",
"@angular/router": "~11.0.5",
"@nebular/auth": "^7.0.0",
"@nebular/eva-icons": "^7.0.0",
"@nebular/firebase-auth": "^7.0.0",
"@nebular/theme": "^7.0.0",
Facing similar issue, any update on this bug report? currently on version 9.1.0-rc.8
My solution:
I extended the original class with the refresh implemented, they didn't had implemented it
import { Injectable } from '@angular/core';
import firebase from 'firebase/compat/app';
import { Observable, of as observableOf, from } from 'rxjs';
import { catchError, map, switchMap, take } from 'rxjs/operators';
import { NbAuthStrategyOptions, NbAuthStrategyClass, NbAuthResult } from '@nebular/auth';
import { NbFirebaseBaseStrategy, NbFirebaseIdentityProviderStrategyOptions } from '@nebular/firebase-auth';
@Injectable()
export class FirebaseGoogleStrategy extends NbFirebaseBaseStrategy {
protected defaultOptions: NbFirebaseIdentityProviderStrategyOptions = new NbFirebaseIdentityProviderStrategyOptions();
static setup(options: NbFirebaseIdentityProviderStrategyOptions): [NbAuthStrategyClass, NbAuthStrategyOptions] {
return [FirebaseGoogleStrategy, options];
}
authenticate(data?: any): Observable<NbAuthResult> {
const module = 'authenticate';
const provider = new firebase.auth.GoogleAuthProvider();
const scopes = this.getOption('scopes');
scopes.forEach((scope) => provider.addScope(scope));
provider.setCustomParameters(this.getOption('customParameters'));
return from(this.afAuth.signInWithPopup(provider)).pipe(
switchMap((res) => this.processSuccess(res, module)),
catchError((error) => this.processFailure(error, module)),
);
}
refreshToken(data?: any): Observable<NbAuthResult> {
const module = 'refreshToken';
return this.afAuth.authState.pipe(
take(1),
switchMap((user) => {
if (user == null) {
return observableOf(
new NbAuthResult(false, null, null, [
"There is no logged in user so refresh of id token isn't possible",
]),
);
}
return this.refreshIdToken(user, module);
}),
);
}
protected refreshIdToken(user: firebase.User, module): Observable<NbAuthResult> {
return from(user.getIdToken(true)).pipe(
map((token) => {
return new NbAuthResult(
true,
null,
this.getOption(`${module}.redirect.success`),
[],
this.getOption(`${module}.defaultMessages`),
this.createToken(token),
);
}),
catchError((error) => this.processFailure(error, module)),
);
}
}