JWT Authentication on page load - javascript

I'm using JWT authentication in my node site with passport and am not sure I am understanding the concepts.
Say I'm an authenticated user with my token saved in local storage. Say I then navigate to a /user page, which will display data about my user. Normally, I would check if the user is logged in, and if they are not, they would get redirected to a login page. But in this case, since I can't send the authentication token from a page request, I have to load my /user page, then the page makes a request for user data, and if the data is not found, I redirect them to the login page via javascript.
Am I correct in how I would handle this? It seems like a bad user experience, having to wait and redirect twice. Is there a way around this? Is JWT just not what I'm looking for my implementation?

If you want to render the page server side, you should set the JWT as a cookie instead of using local storage. You would be able to catch, verify and use it when a user request a page.
But I have to say that modern web applications use client side rendering. So there's no need to store the JWT as a cookie. When requesting a page, you will recieve only the static assets and you will get data by queryng an API that could response with 401 (Invalid or Expired Or Missing Token).
It seems you were using server side rendering before. Now you want to use JWT and you have read somewhere that a common practice is to store it in LocalStorage (that's true). Now you are dealing with a server side rendered application architecture while tryng to mix client side rndered applications concepts.
You are not doing huge errors, but you should consider to fully render your application server or client( I suggest ) side. For the second option, google "Build single page application"

Related

How is nuxt/auth really secure?

Let's imagine a client opens your nuxt.js website on the index page. From there, they authenticate (you used #nuxtjs/auth-next for that purpose). Then they move to a secure page that only authenticated users can see. This secure page is a .vue file in your "pages" folder with middleware: ["auth"].
Now, how is this page really secure ?
I mean, couldn't a malicious user temper with the page and access it without being authenticated anyway ? Because the "security" in this scenario is only implemented on the client side right ? [Edit]
Your application being an SPA at the end, if you want to bypass a middleware with it's security checkup, you could disable the JS on the page. But then, since no content is generated directly, you won't see anything because it's not here (as a static file).
If your app is isomorphic (basically has a ssr: true), the auth module will still disable the access to those pages (you can double check).
At the end, the critical info is received when:
you do have a valid JWT token (after some login)
you submit an HTTP query to the backend
the backend acknowledges it and the token is valid
the backend gives you the sensitive info via an HTTP response
At the end, your client side code doesn't need to be secure. If somebody somehow hacks your client side state and reaches the sensitive page, he will still not have a valid JWT token since the verification still happens on the backend.
The one that can be generated only when sending the proper credentials to the backend and having the backend validating those.
Now, how is this page really secure ?
The protected content is served from a request if a valid access token has been provided by the client.
The protected content is provided at runtime.
Because the "security" in this scenario is only implemented on the client side right ?
The security is not only implemented on the client side.
The premise is: The access token has been obtained securely through an authentication flow with an auth-server.
I recommend to read more about auth flows if this sounds unclear.
Auth0 has some good documentation on different flows.
https://auth0.com/docs/authorization/flows
Then, what is the best way to show a complex page to authenticated users only ?
The content is provided at run-time. Server-side or client-side.
There are some setup guides here for Nuxt.
Here is the first (Auth0) I found from the list.
https://auth.nuxtjs.org/providers/auth0
I don't know how updated those guides are, but the auth service providers tend to have updated guides themselves.

How to handle facebook login with a subdomain?

My application client side serve using aws cloudfront/s3. www.example.com
My server side is nodejs in ec2. api.example.com
I want to do login with facebook.
I set facebook to redirect after login to api.example.com/api/facebook/return.
Now when I on api.example.com/api/facebook/return I need to get back to my application www.example.com with the user loggedin.
How to do it?
I don't want to use lambda (lets say this is not the solution for me).
I can't access to the localStorage to store the token and the user - cause safari doesn't support Hub in access to another localStronge domain.
Can't use cookie because I have LoadBalancer and stateless servers.
I try to send a 10 seconds token to the client and return back to the server (confirm the token) and then back to the client (access token).
but sometimes the computer is slow and I get expired.
I was thinking about one time token, but how to implement such a thing? or any other idea how to handle this?

How to make token based authentication when someone open a page directly

There is a sensitive page in my website, so I want to authenticate visitors before they opening a link like: www.examples.com/builder.
I know if I use cookie based authentication everything will be simple, as the browser will send the credential message in cookies automatically. But in my situation, I have to use token based authentication. Browser don't send token if there is no pre-load script.
So my question is how to achieve token based authentication when someone open a sensitive page directly.
As far as I can understand,
you're looking for a way to avoid double roundtrips to send authentication headers to your web-service.
If I am correct, then this would only be possible via service worker which is a not widely supported feature. https://developers.google.com/web/fundamentals/primers/service-workers/
If, depending on your requirements, you can't go for service workers, then, the only left option is to use cookies.
I normally have a secondary authentication flow which uses cookies allowing a web service to authenticate a user on its first get request (the one made by the browser).
There are also some spa framework which implement routing resolvers but this will require a double roundtrip (1. load javascript, 2. send the token).

OAuth2 flow in web frontend and REST API

I'm working on a project based on Phalcon which consists in two different stand-alone subprojects: a php + angular frontend and a php REST API.
I protected the API with OAuth2, using PhpLeague OAuth2 Server. The API server is the OAuth2's authorization server AND resource server.
This is the actual flow:
The user can browse the public endpoints of the frontend, and when hits a private page, gets redirected to the login page;
The login page has username and password, POSTs them to the frontend server;
The frontend server calls a public method on the API server, which is expecting a Password Credential Grant: it validates the credentials and sends back an access token and a refresh token;
The frontend server caches both the access and refresh token in session and uses it for some API calls: the first of those is the '/users/me', which gets info about the current user and its ACL on the frontend sections;
The frontend server sends the page to the browser, which loads its javascript files.
Now, OAuth2 states that access tokens should be short-lived and refresh-token should be long-lived: in the frontend server logic, the API calls which receives a 401 (caused by the expired access token) are retried by sending first the refresh token to obtain a new access token via a Refresh Token Grant. If this second call is rejected, I assume the user is no more logged in (refresh token expired / revoked).
The pages are using Angular to perform data and ux/ui management. My question is:
should the Angular code call directly the API server?
Actually the first thing my javascript code does is to get a config object from the frontend server, which contains the access token too, and uses it to make the calls to the API server. The problem with this is that i should rewrite again the "refresh token logic" in javascript (after it expires, i get 401s), and by what I have read on the subject i understood that it is better to not make the refresh token visible to the client (as it can generate new access tokens).
So i was thinking about a "two step approach", where every javascript API call goes to an endpoint on the frontend server which relays it to the API server, but this is obviously slower (JS -> FRONTEND -> API and API -> FRONTEND -> JS).
What is the correct approach? It's not very clear to me if the frontend should be considered as two clients (php + js) which should work separately or not, as I imagine that an hypothetical iOS app would be making calls 100% against the API server.
I have used the same approach in my own projects. The problem that we have is that the client is not secure. In order to generate / refresh a token, you need to pass secure information to the authorization server.
I have done the same as you basically, let the back-end handle the tokens and their temporary storage. You cannot and should not trust the client with important information which lets you generate tokens. In terms of delays, I wouldn't worry about it too much since you're not going to be doing that much extra work, you won't even notice the delays. I have a system like this built and used by hundreds of thousands of users with absolutely no issues.
Now, you have said a few things in here which make me wonder what you are doing.
OAuth2 is not a user authentication system, it's an application authentication system. You don't pass a user and their password and generate a token for them, you pass a ClientID and ClientSecret and they generate a token for you. Then you have an endpoint which gives you the user details for this user, you pass your userid or username and get the details of that user.
A token expired does not mean your user is logged out. Those are two completely different things. How are you going to expire a token for example, when your user wants to log out? You can't, your token will still be valid until it expires after the set amount of time has passed.
A token can be used for let's say half an hour, but your user may use the website for 1 hour. So before you hit any API endpoint, you could check ... has this token expired yet? if yes then you can go and refresh it and keep working without having to bother your user with a new login screen.
The whole point of an OAuth2 system is to make sure that only authorised clients can access it. A client is not a user, it's an application. You can have a website for example and you only want users of that website to access your API.
You can have endpoints like ValidateUser for example, where you take a username and a password and return a yes or no and then you log your user in based on that.
Irrespective of language/framework, second approach is secure and better than first one because to get access token by providing refresh token to Authorization server, it still requires Client ID and Secret which should never be passed to Browser for security reasons.
In first approach, to make a direct call it will not work if your Authz Server is hosted on different domain than your frontend server because of Same Origin policy of browsers. Even if they are on same domain, still you are exposing Client ID and Secret which will compromise your frontend server

Using a REST API and a Javascript client, how to stay logged in after a page refresh?

Currently, my authentication flow is as follows:
User fills in a login form in the client browser app (AngularJS, to be precise), username and password are stored into the browser's memory (plain Javascript variables).
When accessing protected API resources, the request is authenticated with HTTP Basic Auth over SSL using the credentials stored in memory.
The problem is, when the user refreshes the page, her credentials are wiped out and she needs to sign in again. Am I missing something obvious here?
Few solutions I've found so far:
Store username and password into a cookie: this seems obviously insecure, even when using secure cookies and/or encryption.
Use session cookies: this seems to be against the RESTful principle of statelessness.
(I guess OAuth has the same problem with securely storing access tokens in the client?)
Session cookies are totally fine here. Once installed you dont care of them, browser will send them with each request via headers.
Inspired by this answer, I ended up doing something like this (link opens a rather large picture).
In short, client stores Access Token in a javascript variable, but Refresh Tokens are stored in a server-side session (on the server hosting our client app, not on the API server).

Categories