ExpressJS and Firebase Auth, beginner queries - express

I am trying to learn ExpressJS, so I creating a simple website with login functionality...
I want to use Firebase for the accounts and database(Firestore)
My problem is that, Firebase Auth seems to be client-side only and the backend has no idea if the client is logged in or not...
I want to limit the HTML rendered to the client if he is not logged in, but I can't figure out how to check if he is logged in
I know that I can use
firebase.auth().onAuthStateChanged(function(user){
if (!user){
window.location.replace("/login");
}});
on the client side, that doesn't look "Secured" enough to me and I would like to do it in ExpressJS
On firebase documentation I found this about Verifying ID Tokens
but I don't understand first of all how would I send the token to ExpressJS and second, how would I send it before the request to a route is made...

You have to pass the ID token to your backend. You then verify the ID token as explained in https://firebase.google.com/docs/auth/admin/verify-id-tokens#retrieve_id_tokens_on_clients.
You pass the ID token in the request header if your application is a single page app everytime a request is sent.
If you are building a more traditional web app, you can set the ID token via a cookie and retrieve it and check in on your backend with each request. You have to do the following:
Proactively refresh the ID token by calling getIdToken(true) before the token expires. The token typically lasts an hour. You would need to refresh it before expiration and update the cookie so a redirect will still consider the user signed in.
If the user visits your website after a while (longer than an hour), the cookie would be expired, you would redirect to a temporary page where you set onAuthStateChanged and if the user is logged in, call getIdToken(), update the cookie and redirect to the intended destination, otherwise consider the user signed out.

Related

FusionAUth : How to merge user signup + sign in FusionAuth, to make user Auto login to web application

We are trying FusionAuth & looking to have a single step flow for Sign up + Sign In.
After user signs up, we want to show/land him directly to our application's dashboard page (without showing him login page in between the flow). The authentication should happen but internally i.e we are expecting OAuth2 standard IdToken in response to "WebApplication" so that web application can use IdToken to allow user to application.
Please note that we don't want to use approaches where we need to pass Username/password to our web application, don't want to handle user credentials. Also that we dont want to use Authentication Tokens returned in Registration flow because AuthenticationTokens are not that secure, looking to use OAuth2 based IdToken instead.
I have came across this post "https://fusionauth.io/community/forum/topic/165/taking-a-user-directly-to-the-registration-page/3" and tried following request, but it is showing Login page instead of registration.
/oauth2/register?client_id=<Configured_client_id>&redirect_uri=<Configured_redirect_uri>&response_type=code
(I have not used CSRF parameter though)
Please can you suggest why its showing Login Page?
You should be able to have a user register and be sent directly to your application, as long as you set the correct redirect_uri and put that on the registration URL:
https://local.fusionauth.io/oauth2/register?client_id=c50329fa-93e5-4618-8d9f-73d0ab069a23&response_type=code&redirect_uri=https%3A%2F%2Fapp.example.com%2F
The application will then receive a code that can be exchanged for an access token. You can call the userinfo endpoint with that token and get user information like email address, etc.
What you won't get that it seems like you might want is an id token. For that you'll have to send the user through the login process with a scope of profile. However, you could mind your own 'id token'-lite using the values from the userinfo endpoint and the JWT vending: https://fusionauth.io/docs/v1/tech/apis/jwt/#vend-a-jwt

Detect expired cookie and logout user

After log in, I have a cookie . I am wondering, if it's possible for my app to detect if cookie has expired, and then force logout action? Or just force router push to /login
Does it needs to be done with axios interceptors response or in router guard?
You have two options that I know of.
Option 1 (recommended)
Setup an axios interceptor on the response object and listen to the returned responses from the server. Particularly error codes. If the server sends a 401 you can logout the user or request for a new access token to keep user logged in. You can use this npm library to implement the axios interceptors. With the library you can mention the error codes you want to listen to. So, I usually send a 498 error code from the server for all cases that involve expired access tokens, so its easier for me distinguish between expired and unauthorized tokens.
Option 2 (not recommended)
You can use this npm library to decode the JWT on the frontend and extract the expiry time from the token. Create a setInterval() function that regularly checks if the current time is greater or equal to the expiry time. If it is true logout user or request a new token.
Go with option 1 because authenticating a token or its expiry time is the job of the auth server and nobody else. The front-end shouldn't be in charge of deciding whether the token is valid or not. Plus, you don't have to work with setInterval() or setTimeout(), because you'll have to take into account additional edge cases as well.

JWT Refresh token and Multi-Page Application

I am going to implement JWT authentication for several independent services.
There will be auth.example.com and service1.example.com, service2.example.com etc.
My assumptions:
JWT can be kept in cookie for ".example.com"
JWT expire time should be small (like 15 mins) because there is no reliable way to logout user with JWT token (revoke token).
Refresh tokens should be used to reissue JWT tokens
Refresh token cookies should be accessible only by auth.example.com for security reasons and because https://www.rfc-editor.org/rfc/rfc6749#section-1.5 says
"Unlike access tokens, refresh tokens are intended for use only with authorization servers and are never sent to resource servers."
Next, if I have a service - multi page application (i.e. not SPA), where some URLs are called "traditional" way, not via Ajax and render HTML
based on some server side logic, which, of course, include checking of user authorization.
then, say, there will be an action service1.example.com/user/showpage
if (user.logged_in) {
render_some_html(get_some_data(user.login))
}
else {
render_anonimous_uses_page()
}
Problem is:
If site user close all site tabs and, then after hour or so, go directly to page /user/showpage (or maybe he
suspend laptop and wake it up in an hour and go to that page).
What if by that time JWT token will expire. Then to refresh it by Refresh token we need to make Ajax call to auth.example.com (because Refresh
token is stored only in auth.example.com cookie) and this is just unaccessible in server side rendering (that pseudocode that I posted above, it's server side, and it's just impossible to make client ajax call in the middle of execution of server code. it's just not applicable here). This way user will be considered logged out
on this stage.
Redirect could be one solution.. but what if site should work for anonymous out users too, and anyway looking for something better.
This problem not exists for SPA application, because before every Ajax call to internal API, it can check JWT and make call to refresh JWT token.
And question is: is this true that JWT in general should not (cannot) be used in Multi-Page (traditional) applications because of this issue? or there is good way to workaround this? or this is not a problem at all (users don't close tabs too often, or they expect site to log them out or redirect etc)?

Authorization between nuxtjs and the backend API

I have a Vuejs application created using Nuxtjs. I am also using Django as the backend server, and I made an API to interact with the backend server (Django) and front-end app (Vuejs/Nuxtjs). And any API related fetch are done in the AsyncData function of the page to render the data on the server-side using axios. Also, I am using json web token authentication, and the API generates a jwt token after successful login which is stored in the cookie. So on the backend, it will always check for the request's authorization header for the token. If the request is from a logged in user (authorized token) then return authenticated json data, or else return non authenticated data.
The problem:
When the user navigates to the app, I would like to check if the user is authenticated. If the user is authenticated, render the authenticated page. If not then display non authenticated page.
My thoughts:
When the fetch is done from the App on the AsyncData function, I would check whether there is any value for the cookie. If there is then send the token with the request's authorization header. But, since the page will be rendered on the server first, and not on the client side (where the cookie actually is) it will never find the token for the authorization.
How can I check if the user is already logged in or not so that I can get authenticated and non authenticated data respectively from the API?
Update
When I successfully log in (post authorized email and password), I get a json response back with the token, which I set in the cookie like this:
this.$cookie.set('my_auth_token', this.token, {expires: 15})
How can I retrieve client side cookie and into the nuxt server for server side rendering?
Cookies are exposed in the (Express) Nuxt server through middleware.
Specifically, they can be read from the req.headers.cookie property. You can see an example implementation of this in the Nuxt documentation.
Regarding your implementation: fetching the privileged data from your API using Node would seem to be the ideal way to delegate session handling to that single service (rather than both) and provide SSR for your users.
If you've chosen to instead implement your session handling on the Django service then you'll need to "forward" your cookies by passing them into your axios request headers.
I did something similar using Firebase authentication. There is an example project on Github as well as a blog entry outlining the important files and configuration used in the application.

What does Ember-simple-auth check against?

I have been looking for answer of implementing ember-simple-auth (oauth2-password-grant) for days without luck. I use firebase to sign up users, which is successful. However on the log in page, the action of this.get('session').authenticate('authenticator:oauth2', credentials) seems to cause a json error (SyntaxError: Unexpected token < in JSON at position 0).
So my first question is, in theory, how does this authentication check if the user's email/password is correct? Meaning, in which file is the "answer" located? Am I supposed to define a token? If yes, I already tried "serverTokenEndpoint: 'http://localhost:4200/' or serverTokenEndpoint: 'http://localhost:4200/token" and nothing works. Thanks.
Ember simple auth sends login request to API(in your case Firebase). If entered credentials are valid your API will authenticate user, create and save auth token. Authenticated user with created token will be sent to Ember and token will be saved in local storage by Ember simple auth. Every subsequent request from Ember after login needs to include that token in its header and API will authenticate your request based on that token(comparing token from Ember with the one saved in API).