API Token Safety in Angular application - api

I'm building an Angular app with an API backend. On a combination of pieces of advice, I built the API with a flavor of token authentication. The flow is roughly as follows:
POST to login endpoint with credentials
Validate credentials and authorization, then generate a new token
Return token to client
Client uses token via HTTP Basic to access API resources
This is all working well. The problem arises in creating a session based on this token. I don't believe I should simply hold the token on the client in a cookie, but I do need a session to persist between page refreshes, etc. My Angular app is stateless and completely populated via API calls.
I'm looking for a recommendation as to hanging on to this token on the client. I feel there's danger in holding the token in a cookie because the cookie could be stolen and simply used to authenticate as someone else, but perhaps this is incorrect.
Thanks in advance for your assistance!

The only known way for me to identify a user is to use some token on the client.
HTTP is stateless and can't know which request is coming from which user (browser). You can't identify the user by his ip address (many users are behind a router and share a connection). You could try browser fingerprinting, it can work on some browsers but not on all.
I would recommend using a cookie to store this token on the client.
They are send to the server on every request and you can do some protection to keep them from getting stolen.
To protect this cookie from man in the middle attacks you need to use an encrypted connection over HTTPS to the server.
Set the following attributes on the cookie:
HTTPOnly: cookie can't be accessed by javascript (XSS protection)
Secure: cookie will only be send over https
Path: cookie will only be send on specified path e.g. /login
I would also define an expiration date on the cookie, so the cookie is invalid in like 2 days or something.
But you are right. If this token gets stolen someone else can login as this user.

Since its an Angular app, I'd assume all authenticated methods will only be served to ajax requests (you can tell your server to only respond to ajax) in which case CORS will help you.
The only way to be completely secure is HTTPS, however this method is probably more secure than you think. Read up on CORS a bit for more info, but essentially the idea is that servers will only respond to ajax requests coming from html pages that were served by that same domain.
Pre-flight OPTIONS requests are often sent to verify this. The browser sends an OPTIONS request with an Origin header (the origin of the page) before the actual request. If the origin matches the domain of the server receiving it, the subsequent request is allowed. Otherwise, it violates the Same Origin Policy and will be rejected.
This prevents someone from sniffing out the token and sending a request with the token from a page that your server didn't serve (like something running on the hackers local machine).
If you are doing credit card transactions or anything super secure, you should use HTTPS though.
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing

Related

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.

Using JWT authentication across multiple microservices

I have search the web for an answer about this issue, but nothing is quite similar to the setup I have.
So I have a single page application and 3 services:
Backend service - service A
Service for serving static files of the SPA - service B
Authentication service - service C
The flow is as follows:
A user visits the site by going to the / of service B gets redirected to the /login of service B.
The user enters the credentials and they are sent to service C to perform the authentication process and to get the permissions for the user, this data is sent in a JWT.
Service B then puts it in a cookie and returns it to the user's browser.
Then the user performs a task which requires that JWT, so I have to send that cookie to service A, but there is a problem, I can't do it, the cookie is only for service A.
https://auth0.com/docs/security/store-tokens - this link is an example of a source I found that is talking about the issue of where to store the tokens for SPA.
It says there that I should use a cookie to store the JWT if :
If have my own backend
If the backend is in the same domain as the site itself.
The problem is that my backend has a different URL, it is a completely different service, so using cookies wont be the solution, or at least that is what it seems to me.
Then it says:
If your single-page app has a backend server at all, then tokens should be handled server-side using the Authorization Code Flow, Authorization Code Flow with Proof Key for Code Exchange (PKCE), or Hybrid Flow.
The problem here is that they don't even mention how and where to store the JWT so I can access it from multiple domains.
I have not found a clean way to save that JWT on the user's browser and send it in every request that I am doing to the backend.
The solution I need is to save the JWT in a secure way in the browser of the user, allowing me to send it to any backend service I need to.
Thanks for reading thus far and for helping!
One solution is to send the requests to the backend service with JWT in a query param.
You can then have a middleware in the backend service that converts it to an Authorization header so that libraries that look at it continue to work.
So that is the way I chose to implement the solution, but first, few clarifications.
When a browser tries to visit the site, as stated in the question, will be redirected to the /login route to verify the user.
But if the user is nonexistent, then I will let the user to see the site but with minimum permissions.
So if the user is authenticated, the cookie with contain the jwt with the needed data.
If the user is some sort of a guest, service B will still return a cookie, but will indicate that the user is a guest.
The way I chose to implement it is:
Because of the explanation above, we always get the cookie from service B, meaning we can always tell our site save it in the LocalStorage of the browser, so I decided to save the JWT in it.
For each fetch request that I make to service A, I will set a header named Authorization that the value of it will be Bearer <the jwt token> (insert the jwt inside <the jwt token>) as stated in this MDN article about authorization.
About security:
So because saving the JWT in a cookie that is related to service A is not possible (service B and A are from different domains), we are left with the LocalStorage option.
LocalStorage is not the most secure way, it is by default vulnerable to XSS attacks,
but, as stated in this answer, by mikejones1477, modern browsers have strong defense against XSS, and the LocalStorage is not vulnerable to CSRF.
So, essentially, there should be extra care about XSS attacks, but that is the way its made possible to pass the token between services from different domains.

Api Token Authentication - through parameters or headers?

I wrote some API. It requires an API token.
I only access this API through backend.
Should I receive the API token through headers only, or is it ok to receive it from query string parameters?
Are there differences security-wise?
Edit: forgot to mention, of course I use SSL
All the Authorization is in Headers only headers are more secure
In query parameter these are expose for the public
for eg. if you send in Like a query it will be public to all
Don't do this Ever
curl -X GET http://localhost:5051/v1/user/verifytoken?token=bearer-xdrRxfdfdfdf
You may need a refresher on the differences between cookies and tokens to assist you in finding your answer.
The purpose of cookies is to bring state to what is inherently a stateless protocol which is http, the http protocol has no concept of state and it's only by introducing these cookies or tiny bits of data on requests that identify us to the server.
Cookies are included on all http requests by default, they manifest themselves as a property on the header of any request. A server can choose to place information on a users cookie that identifies them uniquely to that particular server.
So if they were logging into a website I were making I could stick some information into that cookie that says this is user13794 and on any follow up request they would have a cookie 13794 that says this is the same user coming back, it's another request from the same person.
Cookies are automatically included on all requests and very importantly, are unique to each domain, such as Google.com versus eBay.com. A cookie you have that is tied to google.com is not and cannot be shared by default with ebay.com, that is how we get some level of security on all of our requests. So if I logged on to google.com and then went to hacker.com, the hacker.com website could not lift my cookie from Google and hijack my session.
SO cookies cannot be sent to different domains, that is something that exists for security purposes so you cannot easily hijack peoples sessions.
Opposed to cookies are the ideas of tokens, this was introduced as a convention, to use tokens in place of cookies where cookies stop being useful.
There is nothing done automatically for us with tokens, we have to manually include a header with our token which might be a string of letters and numbers and we might include it on a specific header so we have to manually wire up our tokens at all times.
The benefits of tokens is that we can send them to any domain that we wish, so if I am on google.com and I want to make an authenticated request to an entirely different domain, I can do so by using a token.
I would make my request to that other domain, include my particular token and boom! I am authenticated on that other domain.
So that's my long winded way of saying, like with cookies, tokens are manually wired up through headers only, not query parameters.

Securing Express API

I'm writing a web app with a separate frontend and backend. The frontend is written in React, and the backend is a node.js server running an Express endpoint. How do I ensure that only my frontend can access the API, and not anyone else? My API URL is exposed in my frontend client side code, so anyone can see that.
I added JWT authentication to my API, but I still need to have an unprotected /login endpoint in order to generate the JWT token, and in order to login to generate the token, I must post both a username and password from my frontend, which other users can see, since it's done from the client side.
What is the proper way of securing an API that is hosted on a separate backend like this, so that only my frontend can access it, in a way where nobody can see what credentials are being used to access the endpoint?
You can't. Your API is on the internet. Anyone can access it. You can require an account and login credentials for the account before allowing access to the API, but once someone has an account and credentials, they can access the API from their own script rather than via your web page. This is how the web works. Not much you can do about it. And credentials being used by the client cannot be hidden. All data that is EVER on the client can be looked at by a hacker on the client. This is the way of the web.
Larger companies will typically monitor their API usage to look for inappropriate use. This includes rate limiting, detecting behaviors and sequences that are not typical of a regular human user. When they detect inappropriate use, they will often disable that action or ban the offending account, either temporarily or permanently. This is also why some pages use techniques to detect if an actual human is individually causing the operation such as reCaptcha. For example, on stack overflow, when editing comments or posts, I often run into rate limiting where it tells me that I have to wait a bit before it will accept my edit.
There is no absolutely secure way to store credentials in a client. The most common scheme for credentials is to require username and password (securely over https) and then when that is accepted on the server as legit credentials, some sort of token is issued to the client which can be used for future API calls. That token may be in a cookie or may need to be manually included with each subsequent API call (the advantage of a cookie when using APIs from a browser is that the cookie is automatically sent with each subsequent request).
If the token is a cookie, then the cookie is stored in the browser's cookie storage and an expiration can be set for it. The browser's cookie storage is protected from access by web pages from other sites, but can be accessed by someone on the local computer (it's stored in the file system).
If the token is not a cookie, just returned as a token, and the client wishes to store it, there are a few other places that Javascript provides access to in order to store it. Local storage has similar security as cookie storage. It is protected from access by other web sites, but can be accessed by a person on the local computer.

Passing Foursquare token in HTTP Authentication header. Is it possible?

I'm constructing an application with 2 sides: client (iPhone) and Server (PHP). Communication using https. The mobile phone gets a 4SQ access token. Then, it sends that token to the server, and the server will make 4SQ API calls using it. My question is about how to send this token.
My idea was to include the token in the HTTP Authentication request's header, but after reading about basic/digest authentication, I suspect it isn't the way of doing it. Actually, the calls to 4SQ API are done using a request parameter
oauth_token=ACCESS_TOKEN
instead of putting the token in Authentication header, or any other place. I'm sure there's a good reason for that, but I can't find it.
Then, which option is the best?
Phone sends token to PHP server as request parameter, like 4SQ does
Phone sends token to PHP server in Authentication header (which kind oh authentication is?)
Any other way
Many thanks in advance, and best regards
I think the most secure and reasonable way would be a HTTPS POST. When the token is part of the query string in a HTTPS request, it is also encrypted. But it will appear clear text in the server log, or, when a browser is used, it could also appear in the browser history. Depending on the HTTP helper library, it could also log the HTTPS URL, when, for example, a request fails.
In my eyes, sending the token in the Authentication header would be strange, since it is not used for authentication between the server and the client.