How do I do auth for SPA + API? - authentication

Okay, so long question ahead.
I'm working on an Angular + .NET Core app and I'm a little confused as to what is the best way to do authN & authZ for my app.
For a while before, what I would do is have a page on my frontend which requests the E-mail and Password and send it via POST to my backend, where I would generate a JWT Token. Then, I would store this token in the localStorage and use it for requests.
But, after reading some articles, I noticed that people tend to do it in another way. From what I understand, it goes something like:
Create a traditional auth app
When the user wants to log in on the SPA, redirect them to the auth app, where they log in
After logging in, redirect back to SPA and store the token in memory
Use the stored token to authenticate & authorize requests
Profit
I've also been reading and getting into using Auth0, which seems to be using the latter approach. My problem with Auth0 currently is that I need to have an Users table in my local database for things like getting additional user data (I know about the metadata that can be added in Auth0, but isn't it slower to have to get data from Auth0 everytime I need to use user metadata?) & relationships, but the Hooks don't work when my app is on localhost.
Anyways,
TL;DR
Is there a standard way of doing this that is currently recommended everyone does
Do I understand correctly how the latter approach actually works
Is the way I was doing auth that insecure? From what I understand, the insecurity comes from storing the JWT Token in localStorage, but the token actually needs a secret key to be generated, so does it matter if an ill-intentioned user can see their token? They can't tamper with it without the secret anyways

I would check out these two resources and I do agree with the conclusion to put all of the token handling in the backend, not in the SPA client.
alert‘OAuth 2 0’; // The impact of XSS on OAuth 2 0 in SPAs
SPAs are dead!?

Related

Best practice for storing custom authentication token

I'm feeling really stupid right now - I'm an experienced javascript & PHP developer but I just can't get my head round this one!
I have developed a system that allows users to create widgets and embed them on their own sites by including one dynamically-generated javascript file. I have now incorporated an authentication system so users of these widgets can register and login on my client's sites. The registration details are stored on my server.
When a user registers or logs in, I was planning on sending back some kind of encrypted token (of their unique ID) so that when they next access a widget on the same site the code will automatically log them in by sending the token to my server and decrypting it.
However, if this token is stored in the browser via localStorage or a cookie, it will be copy-and-paste-able to anyone that can get their hands on it, resulting in them being able to log in as that user. Is there any way I can achieve what I want without this risk?
Thanks in advance!
You can use JWT. Server generates JWT to frontend and when frontend receives JWT it will store it to localstorage. Localstorage is safe place to keep JWT as long as you make sure that user can't perform any XSS on your application.
You can also solve CSRF with JWT if you send it in HTTP header. That makes sure that unauthorized requests won't go through on other domains. You should check this PHP JWT library out. I have used it on my own projects.
PHP-JWT
I decided to send back a hashed token made up of the user's (encoded) id, password, and salt. I store their encoded id and token, then send both details to the server when automatically authenticating. Should the user's account be compromised through use of this token, they can change their password to invalidate it.

Authenticating a Vuejs frontend with an Express Backend

I am looking for some advice on implementing authentication when the client and the server live in separate projects.
The Server
This API was built as an Express Server. It has routes for CRUD operations with a MySQL database. It also has a user model that utilize bcrypt to encrypt passwords. There is no Frontend, in this project.
The Client
This is a Vue project made with the vue-cli and hits the above API to get the data to display.
The Issue
I need to add authentication. I was thinking I would do this with express-session, but I am a little confused with how exactly it works. All of the tutorials I have seen use express-session in combination with passport. This seems fine, but in all the examples passport forwards to a login page that lives on the server. This is usually written in handlebars or some other templating framework. I am not sure the best way of implementing since the login page lives in the client project.
How I thought it worked (Am I missing something?)
I was originally of the impression that for a new user express-session would create a token that I would save in the users table (maybe generated at login and stored temporarily). Once the user logs in with the correct password this token is passed to the client to be stored as a cookie. When the client wants access to restricted data, it would pass the token as a Authentication header to the server to get permission.
The Questions
Since my projects are separated is passport still useful for my use case?
Is it secure to create the session cookie on the server and send the token to the client as a response to the client's login POST?
Do I need to store the session token in the database?
Is there a better option?
In my project I have almost the same setup, and I ended up with JWT to generate an access token.
The cycle begins with the user sending his/her email and password to my login endpoint.
In this stage I hash the password using some secret string, fetch the user from database and check if authentication succeed.
After that I generate an access token with an expiring time set, and I expected this access token in all protected routes.
With this approach you can easily implements refresh token to exchange at time to time, saving the refresh token in your database.
This is very simple and Is good to you understand how the process of authentication is done.
jsonwebtoken

API Authentication for PWA

The Setup
We’re building a PWA (progressive web app). The main components are the app shell (SPA) and the API. The REST API will supply the data needed for the app, while the SPA will handle the rest (as per Google recommendation).
The Problem
Authentication of the end-user seems problematic because the web browser needs to be accounted for. We want the user login to persist through closing down the browser.
We’ve done the research about the possible ways of going about it, however we’d like to ensure that we’re not going in the wrong direction.
Solutions we’ve considered
Session based authentication - the user sends username and password to /accounts/auth and receives a HTTP only cookie with the session ID. The session needs to be stored in a database or Redis. The issue with this option is that cookies are automatically sent by the browser therefore we need a CSRF protection in place. Using the Synchronizer Token Pattern a new token would be generated every time a state changing request has been made e.g. POST. This means that the application needs to supply a CSRF token with every request so that the PWA can send it via AJAX. We determined that it’s not ideal as the user can send multiple post requests in a quick succession making some of them fail and resulting in a bad user experience.
We could also use this method without the CSRF by limiting the CORS policy to same domain and adding a header requirement which technically should stop all CSRF, however we're unsure how secure it would be.
JWT token based authentication - the user sends username and password to /accounts/auth and a new JWT token is issued. The JWT then needs to be stored in localstorage or a cookie. Using localstorage means that JWT is XSS vulnerable and if the token is stolen, an attacker can impersonate the user completely. Using cookies we will still have a CSRF issue to resolve. We considered a double submit cookie method but the CSRF would only refresh every time the JWT is reissued which creates a window for the attacker to find out what the CSRF is. It is not clear which method is best to use.
Session based authentication + JWT token authentication - the user sends username and password to /accounts/auth, a session is created, a HTTP only cookie is set in the browser and a JWT token is sent back to the user. The PWA can authenticate requests with the JWT and whenever the JWT expires the app calls /accounts/auth again to acquire a new one. The /accounts/auth endpoint would still need to be CSRF protected, however the impact of it on usability would be minimised.
There seems to be a large amount of articles claiming that localStorage is insecure and shouldn't be used so why are high profile organisations like Amazon still recommending it? https://github.com/aws/amazon-cognito-auth-js - this SDK uses localStorage to store the token.
You don't need to generate new CSRF token each time a client make a request. It's much easier to use a scheme like token = hash(id + secret + current_day). You only need to update it once a day, or even employ mixed scheme (if the token is invalid today, but is okay for the previous day, the server accepts the operation and returns new token in a predefined header for client to renew it). You may also use the cookie as an id, making the token totally stateless and much easier to check, no need to store them in the database.
Here is how I look at it.
JWT token authentication : with this approach, you can always use a time-bound token with its expiration set to say 2 hours or something?
Or another approach would also be to try and see how you could use some of the approaches the Credentials Management API suggests for example, auto-sign-in of users whenever they come back.
Stuff like 2-step verification with OTPs for instance; for very important features in your web app can be a choice. In this case basic stuff are tied to whichever one time authentication method you have.
Actually, you can also use user-defined pins or short codes (seen a lot in banking apps) to grant access to some features in your web app.
Hope this helps, or sparks some ideation.

How are you supposed to store access tokens?

We are building an application with a React/Redux frontend and a NodeJS/Express Backend. I, not being a security expert, opted to go with Auth0 to handle Authentication.
Auth0 returns an ID Token and an Access Token when a user logs in, this access token is used to authenticate and access our backend API.
We've seen this Access token stored before in Local Storage but Auth0 then contradicts that here. Furthermore, in this answer it seems that some recommend storing in Local Storage, as does this one.
This has me terribly confused. How can we store and persist the token without storing it in memory? We could store it in Redux only but it'll clear on refresh which isn't a solution.
Here they show that the User Signs in and the Access Token is returned and that later it is to be sent along with API Requests, which I understand, but where is it to be stored in the meantime?
How are we supposed to store the access tokens so our application can access our API? Or are we not supposed to store it at all?
We decided to store access tokens in a React Context Provider. Looks like Auth0 has updated their quickstart guide to do the same.
The best way to store AT/RT is by using a distibuted cache memory for your client backend servers. By this way, you make sure that all API calls must transite by your backend application. In your frontend, you pass only the ID_Token witch has to be used to identify your end users.
User sends ID_Token --> Client (backend web app) checks the Id_Token and Get AT from cache memory --> Call the APIs with AT.

Seperate Front and Back-End - Persistent Authentication with Vue/Webpack/Hapi

I apologize in advance for the wall of text.
I'm working on a project for school. We are trying to create a messenger application with a separate front/back-end.
For the back-end we decided to use Hapi (NodeJS), which is now a working API that authenticates based on JWT.
Let's assume the back-end is running on http://localhost:3000.
To interact with the API and create an actual user-friendly messenger, we decided to go with VueJS, using Vuetify as a design framework.
We created a webpack template with vue create (Vue CLI3) and started designing a register/login page, which is served on http://localhost:8080.
I have now arrived at the point where I have to think about a way to show different content based on authentication. I can request a JWT from the API by logging in, but I don't want to store it in local storage, as that is insecure. The same goes for cookies, if they are not HttpOnly.
I feel like a messenger app wouldn't require a user to login every time they restart their browser, so I need some kind of persistence, which leaves only one option (please correct me if I'm wrong): HttpOnly cookies containing our session data, a JWT in this case.
Seeing as I can't set HttpOnly cookies with Vue (as it's JS), how would I go about creating persistent authentication?
We want a user to be redirected to a login page if they aren't logged in. If they are, they can access and see extra functions (Vue components). If they refresh, or restart their browser, they should still be logged in and able to access the functions the API offers (like sending messages to others, reading their own messages). This, while not being vulnerable to XSS.
I have unleashed my Google-fu for 2 days straight now and can't find a good answer. People use VueX which isn't actually persistent and only works persistently with local storage, which again, is insecure for storing a JWT.
Is this at all possible with a separate front/back-end? If I send back a cookie with Hapi, that might work and get stored in the browser, but that'll be HttpOnly so how do I read it with the front-end to determine if I am authenticated?
Please be as verbose as possible, as I seem to miss a lot of design principles and context that are apparently very obvious to everyone else on the internet. I honestly believe that if there is a very good answer to this, that it'll help other people starting out tremendously.
TL;DR: How to create persistent authentication with a Vue front-end and Hapi back-end, without sacrificing security?
as I know, HTTPOnly cookies can be set only on https protocol
source : https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies
and I think it is safe to store jwt token in localstorage as long as you use https
another related thread about jwt storing in reactjs : https://stackoverflow.com/a/44209185/10661914