Feature Request: Support server-side authentication in AngularFireAuth #1500
Replies: 23 comments 5 replies
-
I have the same problem, looking for solution of this scenario :) if we can fix this, it will be completed eco system for angular with minimum cost. what about angular state transfer ? |
Beta Was this translation helpful? Give feedback.
-
While not an official solution, I have used dependency injection + firebase admin to work on server side See: The idea is, you only need to use the |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
How do you intend to transmit a Authorization header from the first server request? The web browser WILL send stored cookies, but has no ability to know you intend to send an Authorization header. Cookies are also more secure in general. I highly recommend you use Cookies in your universal application. |
Beta Was this translation helpful? Give feedback.
-
@davideast do you have any suggestion sir? |
Beta Was this translation helpful? Give feedback.
-
Like @hiepxanh mentioned above... This would complete the SSR + Angular + Firebase visionquest. The only thing I've come up w/ so far (and this just a hack to get rid of auth'd refresh flicker) is to canActivate(): Observable<boolean> | boolean {
if (typeof window !== 'undefined') {
return this.afAuth.user.pipe(
take(1),
map(state => !!state),
tap(loggedIn => {
if (!loggedIn) {
this.system.log('You must be logged in.');
this.router.navigate(['/login']);
}
})
);
}
return true;
} This just flips the problem around, to where when you hit a route-guarded page without auth, it will flicker the unauthorized page on the initial render, and then kick you back to the login page once it's got the firebase user response in the client. Again, FYI - This is a total hack. |
Beta Was this translation helpful? Give feedback.
-
Just checking back in here to see if anyone has made any progress on this? |
Beta Was this translation helpful? Give feedback.
-
I've looking into this BTW. For server side auth right now I recommend a cloud function that issues a cookie via the admin SDK. I'll come up with some recommendations / put some work into the Auth module soon to make it work better out of the box. |
Beta Was this translation helpful? Give feedback.
-
I will also be writing a module for this soon - will post back here once its ready :) |
Beta Was this translation helpful? Give feedback.
-
just saw these... 🤔 |
Beta Was this translation helpful? Give feedback.
-
Hey @jrodl3r , did you try this new things out? Is it working with ssr? Thanks |
Beta Was this translation helpful? Give feedback.
-
hi @simkepal, currently setting up a system w/ latest angular-universal (8) on a gcloud app-engine instance - so far, SSR is working great with node 10. will update after setting up auth and testing out new guard stuff 👍 |
Beta Was this translation helpful? Give feedback.
-
@jamesdaniels so, this works on local angular + SSR from gCloud instance: const isAdmin = () => pipe(customClaims, map(claims => {
return claims.admin === true ? claims.admin : ['/'];
}));
const routes: Routes = [
…,
{
path: 'admin',
component: AdminComponent,
canActivate: [AngularFireAuthGuard],
data: { authGuardPipe: isAdmin }
},
]; however, the pre-built ones like const redirectUnauthorizedToLogin = redirectUnauthorizedTo(['login']);
const routes: Routes = [
…,
{ path: 'profile', component: ProfileComponent,
...canActivate(redirectUnauthorizedToLogin) },
]; this has been crashing my canary tab regularly =\ const redirectUnauthorized = map((user: IUser) =>
user ? ['profile'] : ['login']); great news that we can verify the admin claim, just need to fix verifying the logged-in user. Update: this works in both local Angular + gCloud SSR instance 😄 const isLoggedIn = () => pipe(map(user => !!user ? true : ['/']));
const isLoggedOut = () => pipe(map(user => !!user ? ['profile'] : true));
const isAdmin = () => pipe(customClaims, map(claims =>
claims.admin === true ? claims.admin : ['/']
));
const routes: Routes = [
{ path: '', component: HomeComponent },
{
path: 'login',
component: LoginComponent,
canActivate: [AngularFireAuthGuard],
data: { authGuardPipe: isLoggedOut }
},
{
path: 'admin',
component: AdminComponent,
canActivate: [AngularFireAuthGuard],
data: { authGuardPipe: isAdmin }
},
{
path: 'profile',
component: ProfileComponent,
canActivate: [AngularFireAuthGuard],
data: { authGuardPipe: isLoggedIn }
},
{ path: '**', component: ErrorComponent }
]; also works on lazy-loaded module routes 👍 const routes: Routes = [
…,
{
path: 'admin',
loadChildren : () => import('./components/_admin/admin.module').then(m => m.AdminModule),
canActivate: [AngularFireAuthGuard],
data: { authGuardPipe: isAdmin }
}
} |
Beta Was this translation helpful? Give feedback.
-
I am so confused, could someone wrap it up? does |
Beta Was this translation helpful? Give feedback.
-
I found a good stopgap solution, until there's a good way to check auth server-side with Angular Universal. Assuming your guard redirects to login, on your login page, show a loading spinner until the frontend can resolve auth. Then what happens is, if you try to load an auth-protected route, the user sees a loading spinner momentarily until auth resolves. To make this work, you have to set up your login template to ensure it prerenders showing the spinner. This is ok, since you should not need SEO on your login route. I did it like this: login.component.html: <ng-container *ngIf="authResolved; else showLoading">
<!-- login form here -->
</ng-container>
<ng-template #showLoading>
<!-- this is a component that holds a spinner -->
<app-loading-overlay [loading]="true" behavior="full"></app-loading-overlay>
</ng-template> login.component.ts: authResolved = false;
constructor(
private afAuth: AngularFireAuth,
@Inject(PLATFORM_ID) private platformId,
) {}
ngOnInit() {
if (isPlatformBrowser(this.platformId)) {
// show spinner till frontend can determine if user is logged in
this.afAuth.authState.pipe(
map(user => !!user),
take(1) // this way the observable completes and we don't need to unsubscribe
).subscribe(() => {
this.authResolved = true;
});
}
} |
Beta Was this translation helpful? Give feedback.
-
Thanks that helped me a lot |
Beta Was this translation helpful? Give feedback.
-
Are there any plans to make the AngularFireAuth Service work on server for SSR? |
Beta Was this translation helpful? Give feedback.
-
I'm also getting stuck with the same issue in Angular SSR. Is there any solution for it? |
Beta Was this translation helpful? Give feedback.
-
I'm hoping to add official support for it in a future release but I'd suggest cookie auth for SSR. |
Beta Was this translation helpful? Give feedback.
-
Is there any progress on SSR with authentification? An official solution would be much appreciated. I'm using AngularFire with email + password authentification and would like to add SSR if there is an easy solution. I read that we can use SSR without authentification out of the box and can even "activate" a cloud function. But I'm unsure what the cloud function does. SSR is actually new for me so I would very much appreciate any advise on how to implement SSR with authentificiation. Probably this is already working out of the box and I just missed something, did I? Love AngularFire btw. Great work. |
Beta Was this translation helpful? Give feedback.
-
Hi @jamesdaniels, are there still any plans for this feature request? Thank you in advance. |
Beta Was this translation helpful? Give feedback.
-
@jamesdaniels It's been a year since the last update. Any chance official SSR + Auth will be looked at soon? |
Beta Was this translation helpful? Give feedback.
-
We now have FirebaseServerApp, you can combine this with Service Workers to pass an authorization header! https://firebase.google.com/docs/auth/web/service-worker-sessions#web-namespaced-api_5 Added to the documentation here https://github.com/angular/angularfire/blob/master/docs/auth.md#server-side-rendering |
Beta Was this translation helpful? Give feedback.
-
I am currently developing an angular universal app powered by firebase and angularfire2 (for authentication and database/firestore).
For the server side rendering i am using NodeJS.
I have the following scenario:
There is many routes and many components inside the project! For the following scenario i will consider only 3 routes/components
1- Home Component (authentication is not required)
2- UserProfile Component (Authentication is required)
3- Login Component (used as fallback route to authenticate the user that are trying to access the user profile without to be logged in)!
To make things working with an authentication process within an angular app, we use the "canActivate guard"!
Workflow in the canActivate guard:
this.auth.user$ is equal to
However, client side rendering is working like expected but no the server side!
Since in nodejs the firebase authentication's credentials are not known, the user$ Observable is never fired on the server side (the credentials are located in the local storage of the browser under the key firebase:authUser......).
Angular Universal - SSR - canActivate Result:
when the guard is triggered on the server side, the login page will be rendered and then after few seconds the client side render the whole thing again and will be redirected to the user page.
Than means, by refreshing and rendering every time the user will see first the login page then the user page! This is happening one more time because on the server side are NEVER authenticated..
How can we solve the above described scenario?
Request
Please support firebase authentication on the server side too
Note (ideas): supporting firebase authentication for angular universal app through JWT - headers / cookies ????
Beta Was this translation helpful? Give feedback.
All reactions