Does a single token protect against csrf in a RESTful API? - rest

Consider I'm creating a RESTful API (like Twitter API) and I need only a single key token to access the endpoint GET /messages.
The token needs to be sent via header access_token for example.
If I don't pass the token I'll get an 4xx error.
In the RESTful API scenario, is this all needed to protect against CSRF attacks? I mean, in RESTful APIs I'm not using Cookies to manager a user session, since the idea here is to not be a session (Stateless is one of the principles of REST).
Am I forgetting something or is this correct? I don't see why I would need a anti CSRF token besides my access token.
Thanks in advance!

Short answer: if your access_token is not a cookie, yes, it's enough to protect you against CSRF.
Long answer:
A CSRF attack can only happen when HTTP client automatically sends some authentication data(usually cookies) to server. The key point is attacker do not need to know the Cookie, it's is automatically sent if web user accesses 2 sites(your site and the attacker's site) using the same browser.
To anti CSRF, server sends to client a private token that browser does not automatically send it to server(so it's must not be a cookie). The developer has to write code to attach the token to each subsequent request.
CSRF is an issue for using Cookie by Web browser, if you are developing restful API that is not used by web browser, usually, you do not need to care about CSRF

#Bart Firstly CSRF attacks are usually from a trusted user. Which means that the client has successfully authenticated himself by maybe passing a valid token in case of a rest API. The attack could be by passing let's say a javascript which can change the state of a resource. So just having a single key token won't really help to avoid CSRF attacks.
Please refer to below URL for more reference on CSRF :-
https://en.wikipedia.org/wiki/Cross-site_request_forgery
Most of the frameworks like Spring have inbuilt support for CSRF.

Related

How do anti-CSRF tokens work in SPA-API communications?

Recently I'm studying some basics of Web security and there is something I couldn't understand.
How do anti-CSRF tokens work in SPA-API communications?
As far as I understand, anti-CSRF is used in SPA-API communications as followings;
The browser sends a login request to the API.
The API servers generates a token and sends it back to the browser.
The browser stores it, and when the browser makes the next request, token with be sent together.
The API can make sure that the request came from the genuine front-end because it contains the token.
A question pops up in my mind--how can it prevent CSRF?
If the token is stored in cookie, it will automatically be sent to API whenever a request happens, like usual session cookies. And even if it's stored in other storage(like session storage or local storage), it can be accessed using JavaScript.
So once users are attracted to the attacker's site, anti-CSRF tokens are completely useless.
On the top of that, I can't understand what's the difference between anti-CSRF token and usual cookies used in authentication/authorization……
Maybe I've made a terrible misunderstanding about how anti-CSRF tokes work. Please put a finger on what's wrong about it.
One of the most common CSRF vulnerabilities exists when an attacker can submit a request to an endpoint using an authenticated user's cookies. If you're not using cookies (i.e., to authenticate a user's request) or some other automatic authentication technique (like HTTP Basic Authentication), then there's generally no need for CSRF tokens.
Example #1:
Let's say you're using a REST API that depends on an access token or bearer token for authentication. This token is usually submitted in the HTTP Authorization header (not a cookie). In this case, as long as authentication isn't automatic (e.g., using a cookie), then there's no need for a CSRF token.
Example #2:
In this case, let's say the browser does send a session cookie to a web service/API to authenticate the request. Then, yes, you would be vulnerable to CSRF if anti-CSRF controls aren't implemented. One way to prevent this is to provide an anti-CSRF token to the browser when the SPA is loaded. The browser can then send that token with the request to the endpoint. The web service will then have to validate that token when the request is received.
There are a number of ways that this validation can occur. This could be done using double-submit cookies, a cookie-to-header token, cryptographic techniques, or even a shared database.
Using Anti-CSRF Tokens:
Anti-CSRF tokens generally should not be stored in cookies. As stated in the OWASP CSRF Prevention Cheat Sheet:
A CSRF token can be included in the <meta> tag. All subsequent calls
in the page can extract the CSRF token from this <meta> tag. It can
also be stored in a JavaScript variable or anywhere on the DOM.
However, it is not recommended to store it in cookies or browser local
storage.
For example, an anti-CSRF token might get embedded in the page as:
<meta name="csrf-token" content="{{ csrf_token() }}">
Where the csrf_token() calls some server-side function that embeds the token in the tag.
It can then be read in JavaScript using:
let csrf_token = document.querySelector("meta[name='csrf-token']").getAttribute("content");
And then transmitted to the server when an API request is made (e.g., in a X-CSRF-Token header in a POST request). In addition, the token should be unique to the session.
However, even if a token were to be stored in a cookie, the cookie could be set with the HttpOnly header. This prevents the cookie from being read by JavaScript. This is more so useful in mitigating cross-site scripting (XSS) attacks.
Additional Info:
This StackExchange Security question includes a lot of good info on using CSRF protection in REST APIs.
Other good resources about CSRF in general:
https://portswigger.net/web-security/csrf
https://owasp.org/www-community/attacks/csrf

How to protect an Auth0 authenticated REST service from XSRF and Session Hijacking?

A common situation: SPA + REST. If one were to forego Auth0 and authenticate the web users with JWT's, one would have to store an XSRF token provided by the server on login in a cookie, and send it in the request headers, along with the JWT.
In the relevant official Auth0 guide, https://auth0.com/docs/architecture-scenarios/spa-api, the XSRF tokens are not mentioned at all. What if someone steals the Access Token from a user? Will they have access to my REST API for that user?
Auth0 has another guide Preventing Cross-site Request Forgery (XSRF or CSRF), but it's strangely brief, and I'm not seeing how it solves the problem I described.
the strategy Auth0 uses to prevent CSRF attacks is by the use of a nonce, which they call a state parameter. This state is generated with the authentication request, and then used to correlate the request with the response received from the authentication. (from Auth0 docs on how to mitigate CSRF attacks)
Relevant info from the Auth0 docs on the state parameter:
a unique and non-guessable value associated with each authentication request about to be initiated. It’s that unique and non-guessable value that allows you to prevent the attack by confirming if the value coming from the response matches the one you expect (the one you generated when initiating the request).
If you are using Auth0.js in your SPA this nonces or state generation and validation is automatically handled for you.

Can the access token returned to an AngularJS app be used by an attacker?

We are looking into integrating keycloak to protect a front end AngularJS application which is served by a nodeJS application and also makes API requests to this server.
Having watched some tutorials, we see we need to use the javascript adapter for the AngularJS app to handle the user auth flow, and then protect our nodeJS application using the bearer only strategy, ensuring angularJS outgoing requests to our Node application contains an Auth header with the bearer token value present.
I have a question\concern about the way in which the token is being served back to the client as I can see it gets saved into a cookie which I assume is what the javascript adapter reads from in order for us to be able to write the Auth header into subsequent requests from the angular app.
My question is can this token value be easily read from the browser cookie and used maliciously by an attacker trying to make api requests?
Am I right in thinking it would be highly unlikely since the attacker would need to know the secret which is stored on the nodeJS side?
You don't need to know the client secret to use access token. That secret is used only to issue access token. If someone has your unexpired access token, then that someone will be able to use your identity until token expires. But you can minimise the possibility of the stolen access token by using https, httponly cookies. Also, you can use a short token lifetime (for example 5 minute). But then you will need to implement refresh tokens; otherwise, the user will need to re-login whenever access token expires.
I think the proper implementation is not trivial. I recommend using of some reverse auth-proxy, which will handle authorization and authentification in front of your app. Tip: https://github.com/gambol99/keycloak-proxy

How to communicate frontend with microservice architecture?

I'm struggling with setting up reliable and performant solution to communicate frontend with different microservices. I do not really now how to maintain (maybe not need) CSRF between my frontend and end services
Solutions stack: PHP, Laravel Passport, JWT, oAuth 2.0, Axios
Current approach:
Actually I've started up with approach from Laravel's passport
https://laravel.com/docs/5.4/passport#consuming-your-api-with-javascript
Using oAuth 2.0 to authorize user from website A to service B.
JWT token is returned for further communication.
Token is saved in cookie within website A
Once user is authorized website A uses JWT token to manage requests without additional to oAuth server, by sending JWT token as cookie using HTTP headers (withCredentials) to authorize user.
For each website A's request there was CSRF token created from service B since user is authorized and cookie could be applied by another unauthorized website to access service B. That was killing my performance since it has to retrieve CSRF for each request made. (that what I actually assume from laravel passport approach and need to create CSRF with JWT token - maybe that was mistake)
My concerns:
Regarding to of James Ward post:
http://www.jamesward.com/2013/05/13/securing-single-page-apps-and-rest-services
The easiest way to do authentication without risking CSRF
vulnerabilities is to simply avoid using cookies to identify the user.
Cookies themselves are not the cause of CSRF vulnerabilities. It’s
using the cookies on the server to validate a user that is the cause
of CSRF. Just putting an authentication token into a cookie doesn’t
mean it must be used as the mechanism to identify the user.
From my understanding setting JWT with website A's cookie with its domain set could not be accessed via any other site from outside. Since that there is no possible way to make request to service B without accessing JWT.
So do we really need CSRF then to secure potential attack to service B while using JWT?
If so, how could I achieve the best (in term of performant) way to generate CSRF through different services to be sure that communication would not be vulnerable for attack from different sites?
Any advice will be appreciated!

JWT authentication & refresh token implementation

I am developing a REST application with its own authentication and authorization mechanism. I want to use JSON Web Tokens for authentication. Is the following a valid and safe implementation?
A REST API will be developed to accept username and password and do the authentication. The HTTP method to be used is POST so that there is no caching. Also, there will be SSL for security at the time of transit
At the time of authentication, two JWTs will be created - access token and refresh token. Refresh token will have longer validity. Both the tokens will be written in cookies, so that they are sent in every subsequent requests
On every REST API call, the tokens will be retrieved from the HTTP header. If the access token is not expired, check the privileges of the user and allow access accordingly. If the access token is expired but the refresh token is valid, recreate new access token and refresh token with new expiry dates (do all necessary checks to ensure that the user rights to authenticate are not revoked) and sent back through Cookies
Provide a logout REST API that will reset the cookie and hence subsequent API calls will be rejected until login is done.
My understanding of refresh token here is:
Due to the presence of refresh token, we can keep shorter validity period for access token and check frequently (at the expiry of access token) that the user is still authorized to login.
Please correct me if I am wrong.
A REST API will be developed to accept username and password and do
the authentication. The HTTP method to be used is POST so that there
is no caching. Also, there will be SSL for security at the time of
transit
This is the way most do it, so you're good here.
At the time of authentication, two JWTs will be created - access token
and refresh token. Refresh token will have longer validity. Both the
tokens will be written in cookies so that they are sent in every
subsequent requests
Storing the tokens in cookies I not dangerous in itself, but if you somehow get you JWT module on your server to read them from there you vulnerable to CSRF attacks where any webpage can trigger a users browser to send a form + you sites cookie to your server unless you use CSRF tokens. So generally they are stored in localStorage and "manually" added to request headers every time.
On every REST API call, the tokens will be retrieved from the HTTP
header. If the access token is not expired, check the privileges of
the user and allow access accordingly. If the access token is expired
but the refresh token is valid, recreate new access token and refresh
token with new expiry dates (do all necessary checks to ensure that
the user rights to authenticate are not revoked) and sent back through
Cookies
Apart from the cookie dangers, it seems safe.
Provide a logout REST API that will reset the cookie and hence
subsequent API calls will be rejected until login is done.
You don't even need to make an API call, you can simply just purge the cookies or the localStorage object and make sure your client doesn't break on missing tokens.
The standard for the express-jwt module expects the tokens to be in its own "Authorization: Bearer [Token]" header, which I would strongly recommend over cookies. The localStorage API is available all the way back to IE8 so you should be good.
Edit:
First, it's important to know the difference between XSS and CSRF attacks since they're often believed to be the same thing.
XSS is when users get unsafe JS running on your domain in other users browsers when that happens neither JWT in localStorage or sessions and JWT in cookies are safe. With httpOnly flag on cookies, you can't directly access them, but the browser will still send them with AJAX requests to your server. If this happens you generally out of luck. To prevent this, make sure to escape all user input if it's sent to the browser.
If you load 3rd party JS with script tags or iframes this might compromise localStorage unless you are careful, but I haven't worked enough with this to help you here.
CSRF is only when other domains are trying to send normal HTML forms to your server by getting the browser to send cookies automatically. Frameworks prevent this by inserting unique random strings as hidden fields and checking them again when it's submitted. JWT's in localStorage is safe from this since each domain gets its own separate localStorage area.
But ultimately all this depends on if your service will be using one single domain, in which case httpOnly cookies will be plenty secure and easier to set up, but if you wanna spread your service out on multiple domains like api.domain.com + app.domain.com or add a native app you're forced to store you're JWTs in localStorage or some other native storage area.
Hope this helps!
I asked this question two years back and also accepted the answer. However, based on my experience and study in the last two years, I'd like to answer this just in case someone stumbles on this thread with the same question.
The approach mentioned in the question is similar to the "Resource Owner Password Credentials" grant type of OAuth 2.0. However, I think it is better to use the "Authorization Code Grant" type instead and Cookie to store the tokens instead of browser localStorage or sessionStorage. I have detailed my reasons, implementation points, security considerations and references in this StackOverlow answer.
Like OP I been using resource owner password grant.
I learned so much from Saptarshi Basu's other answer in a different post I think anyone looking into OAuth Code Flow should take a look at it, it has outlined a very solid approach to auth SPA and resource servers. It primarily relies on your backend(resource server) to handle authentication with the auth provider as a private client.
However, I will just add that people looking at implementing authentication with SPA should also consider OAuth Code Flow with PKCE. The main goal of PKCE is to allow public client such as SPA to authenticate directly with auth provider. All PKCE adds, is that when a SPA app initiates authentication, a hashed value is sent to the auth provider when the user is authenticated. And after user authenticate with the authorization provider, it redirects the user back to SPA with that hashed value as well as authorization code. Now, for the next part where the SPA calls auth provider to exchange code for tokens, instead of providing client secret, it has to provide the key that was originally used to create the hashed value. This mechanism guarantees the code cannot be used by someone who intercepted the code, and the SPA doesnt need to store a client secret like a server-side app does.
Now the only thing I'm not certain at this point is which is technically more secure, server-side authentication using standard Code Flow without PKCE or SPA authenticating directly using PKCE? Most resources I could find online currently describes and recommends the latter . However I feel that letting a private server side client handle authentication (as Saptarshi Basu described) might still be more secure. I would love to hear his opinion on this as well.
My understanding of refresh token here is:
Due to the presence of refresh token, we can keep shorter validity period for access token and check frequently (at the expiry of access token) that the user is still authorized to login.
Please correct me if I am wrong.
Assuming you're talking about using JWT as Bearer-token in OAuth (and I would strongly advice to follow the OAuth 2.0 protocol), that's right.
With an additional auth-time (timestamp of authentication) claim in your JWT, you could even drop the second token and sent your access- as a refresh-token (the auth-server could then issue a new access-token if token is valid & auth-time within allowed range)... but sure, it's also good to follow the standard ;)
Anyway, there are certain additional aspects (that tend to get difficult or are even against the fundamental ideas of JWT) you should consider before using JWTs as refresh-token, as this basically means you introduce long-living JWT:
do you need to have something like forced user logout/ token revocation by subject (e.g. if user got identified as fraudulent)?
do you need to have something like revocation of a specific token (e.g. if a user looses a device)?
...
Dependent on your use-case you should consider all the possible implications, long-living tokens have as they usually require you to introduce some kind of state on your server-side (e.g. to allow revocation/ blacklisting). Keep in mind the beauty and security of the JWT concept lies within JWTs being short-lived.