CSRF Protection: Methods to send CSRF token for each request - java

My initial code generated tokens for the requests that could alter state of my database, like CRUD operations. The token was generated for each request. Sent to client side in JSON-format along with other data and I expected this token to be returned with the request and changed it after completion of the request. But, as I implemented it to only parts of my code (CRUD operations), I was told to redo it and make it web-app wide. I think the best way to do this is with filters.
My problem is, how do I make the client send "the token" for each request? Do I set it in cookies? What are my options? Please advice.

best way is , all links should be GET request, and within get requests no modification should be made to application state. So for GET requests there will be no need for CSRF tokens.
For POST request s which make modifications in application state you have to generate, csrf hidden fields in your forms and validate the token in server during form submit.

Related

Persisting the refresh token of the Spring OAuth2RestTemplate

I have a mobile application that uses my Spring Boot backend for things like authentication and accessing data. A part of the Spring Boot application accesses data from a resource server using OAuth2. I stumbled across an oauth2 client library for Spring that does its magic and everything just works out of the box.
As I'm trying to figure out how this library does its work, I can't seem to find an answer to the way it handles refresh tokens. I'm aware that the oauth2client is bound to a session for each user but what happens when the session ends? Wouldn't the access and refresh tokens get lost?
I was looking for ways to persist the refresh token for each user in my database but I didn't find any support for that in the library. This leaves me wondering if I have to implement this myself or if there's even a need to do so.
Any advice is appreciated!
Basically OAuth2 architecture is used for 3rd-party authentication and authorization. In this mechanism the credentials remains secured and aren't passed on while everything works upon tokens! But you can use it to work implicitly for your own authentication too.
In your case first when you hit "/oauth/token"(default endpoint) along with the client-secret and client-Id and rest of the user credentials the algo checks for the user details in the DB and matches the secret and Id present in the header of the request. If everything goes fine it'll generate a bearer type - access and refresh token and will store these tokens in different collections in the database.This particular user is mapped to these tokens and can access /api's using them only.No user creds are required. You can use MongoTokenStore if you're using MongoDb for storing and accessing stored tokens.
Next you have to configure WebSecurity/AuthorizationServer/ResourceServer for checking endpoints and header tokens tokens, authentication and authorizaton of users and providing valid tokens access to the resource respectively.
Lastly when you have a valid access token and hit an api with a correct header request the server grants you permission to access the resource!
This is the basic functionality of the OAuth2.0.
Normally Access Tokens have a shorter lifetime while refresh tokens have comparitively larger lifetime. Once Access Token gets expired a new Access Token can be generated using the Refresh Tokens. If the Refresh Tokens gets expired then you have to hit the "/oauth/token" api again,complete the flow cycle and generate tokens again.After expiry when you hit an api with existing access token they are removed from the collection. This is the default architecture of this mechanism, rest you can make custom classes and modify its functionality according to your needs! This architecture is quite secure and is a good practise.
Screenshot Flow Diagram
Check this post from digitalocean.
Edits ----
Personally I used MongoDB where I made two collections -
AuthAccessTokens and AuthRefreshTokens namely where these two were
stored. Access Token object has an Id of associated RefreshToken
which helps to map these two together. Rest custom additional Info.
can also be added using TokenEnhancer. Therefore tokens will always
be present in the DB unless expired. And in layman's terms if you
are just focussing on Backend stuff you can always check for your
access tokens by hitting "/oauth/token" with correct user creds and
it will return the assigned token by fetching it from the DB, else
if you're developing full stack after generating the tokens on first
step just store them on client end either in browser's local storage
or app. And if you want to deliberately end the session like for
example in Logout just remove these tokens from their respective
collections.

On refresh browser go to last finished step using cookies(java + react)

Ok, so I have simple website which force user to start from last finished step. Whenever user refresh page he needs to call at application initialization to:
REST /user/{id}/step
This endpoint will tell where user finished. The problem is I am using http only cookie. So I cannot get this {ID} from cookie in javascript.
At the moment I have added additional cookie(NOT http only) named clientId. So application can get his id from cookie, and call to this particular endpoint.
It is working but I feel that it is kinda not best approach. It has few side effects like taking care of clearing this stupid cookie on logout, etc situations.
What is best practice ? I've been thinking about creating additional endpoint which will be used on every application initialization
REST /user/status
// I want to be restfull, so I dont want REST user/logged/step
which will return setCookie clientId="" or setCookie clientId={ID} whenever user is logged or not, in this case I even don't need to care about clearing cookies on frontend side, any ideas?
The problem is I am using http only cookie.
So this http only cookie contains what? I presume a user's session? Then why do you need to specify this user ID in the URL if you should be able to get the ID from the session token?
I believe you should just have the following endpoint REST /user/step which returns the step number for a current user (defined by the session token in the http only cookie) or it returns 401 code (Unauthorised) if the user is not logged in..

Implementing a token style security when doing GET requests

I'm implementing a temporary and very simple token-style authentication mechanism for an application.
The idea is very simple. Whenever a user logs in to the application, a token is returned to the client, which stores it in the sessionStorage data structure of the browser.
Now, whenever I do a request through AJAX I can send the token with the request and the server can verify if this token is associated with an authentication or username. If it is, it parses the request normally, if not, a error page or the initial page is returned or displayed.
I'm not sure if this is the way that token-style authentication and authorization is implemented in real or serious applications, but I've now no idea how to send the token when doing GET requests by just clicking on the link of a view.
My only idea would be to intercept the get requests so that I can fill them with the token, but this all seems to be quite odd, and I've already a lot of links and views.
Search for Json Web Tokens and for implementations on java. This is exactly what you need.
If you want to send to the user some sensitive data inside the jwt, use Json Web Encryption.
You can send that token on each request header or as a request parameter
You can set a cookie, ensure to set it httponly (ans secure if you are on an https site) and read the cookie on every request that reach the server.
You can use JWT token (see https://jwt.io/introduction/). JWT is basically a JSON data structure. Usually, the token is passed along in the authorization http header.

Why is my request working without requesting a new XSRF token?

Is it enough to request one XSRF token from the server and reuse it over the whole session or should I request for each protect-worthy action like save, edit or delete a new XSRF token first and then perform the actual request?
This question arises because I don't understand why my XSRF protected request is working even though I am not requesting a new one:
public void saveName(Long shopId, Long languageId, String name, OnSuccessCallback<String> success, OnFailureCallback failure) {
Request.<String> doRequest(this.shopService,
asyncCallback -> {
this.shopService.saveName(shopId, languageId, name, asyncCallback);
},
(String result) -> {
// ..
success.onSuccess(result);
}, failure);
}
Here Request#doRequest() will simply perform a request but won't ask for a new XSRF token first. I would have to change it to XsrfRequest#doRequest() which does the same thing basically but will request a XSRF token first.
The thing is that saveName() is supposed to be protected:
#XsrfProtect
#RemoteServiceRelativePath("shop")
public interface ShopServlet extends RemoteService {
// ..
String saveName(Long shopId, Long languageId, String name);
}
Please note: Before saveName() is getting called there are several other requests of which some of them already get XSRF tokens. But since I can save a new name without requesting a new one I have the feeling that the previous requested token is getting reused here. Is this okay that way?
Another thing I noticed is if I add #NoXsrfProtect to saveName()
#NoXsrfProtect
String saveName(Long restaurantId, Long languageId, String name);
that the request will still contain XSRF token information:
7|2|9|http://localhost:8080/app/|424F33664CAA93E2F8A4A94C57DA5827|com.google.gwt.user.client.rpc.XsrfToken/4254043109|..ShopServlet|saveName|java.lang..
Why is the token being sent here even though the method is declared as #NoXsrfProtect?
Could somebody clarify this to me? I don't want to make any mistakes - especially in security related matters..
Is it enough to request one XSRF token from the server and reuse it over the whole session or should I request for each protect-worthy action like save, edit or delete a new XSRF token first and then perform the actual request?
Lets ignore GWT RPC's built-in XSRF protection for a moment and look at the title question and this remark: What is XSRF and how do we protect against it?
What is XSRF
XSRF stands for Cross Site Request Forgery - the idea is that a malicious site could somehow forge a request, and force one of our users to correctly send it to our application, as if they had intended to do it themselves. For example, if all it took to transfer money from one bank account to another was
GET /transfer?from=me&to=attacker&amount=10000USD
then an attacker could very simply make a request to our server as an image, css, or js file, from their own site:
<img src="https://securebank.com/transfer?from=me&to=attacker&amount=10000USD" />
Setting aside other details ("okay, that works for a GET, how did they manage to send a POST to my GWT RPC service?"), lets look at the idea of a XSRF "token" preventing this attack: what is it that a friendly client knows or can do, that an attacker cannot know or do?
Mitigation
The idea is that the client should have a way to indicate to the server that it is trusted - that it knows something which only a valid client could know, which indicates that the user is willing to make the specified action. One option is to require the user to perform a captcha, in such a way that the action cannot be scripted by the attacking site, and the user must consciously perform. Another option is to make some data available to a real/trusted client, such as cookies (that can only be read from a page loaded on the same domain), or as part of the HTML page as it loads or some other request (which might be possible to be sent by some other means, but the results can't be read).
OWASP refers to this latter piece of data as a "Synchronizer Token":
The synchronizer token pattern requires the generating of random "challenge" tokens that are associated with the user's current session. [...] When the user wishes to invoke these sensitive operations, the HTTP request should include this challenge token. It is then the responsibility of the server application to verify the existence and correctness of this token.
So, in this case, we could write some value to a cookie so that only the client can see it, and the client can then use this to generate a token. That token then should be passed to the server on each request that must be verified. But from this description, we see that it isn't necessarily important to only have one valid token at a time.
But if the attacker can get an XSS, they can just read the token and force the request again! Or MitM!
That's true, but if they have an XSS, then any request that your own JS can make, the attack can make as well. You've lost, pack up shop, time to go home. Likewise if they own the connection between the user and application and can read and write at will. XSRF protection isn't a magic wand that solves all problems, its a specific attack, and only needs to be addressed on its own: a lock in your home isn't considered faulty if the window can be broken.
Okay, back to GWT
So how does GWT do this? As you've noted, the #XsrfProtect annotation marks a service type as needing to be checked on the server. The client then must request a token, and then make sure the client's service is aware of that token for future requests.
So how does the server generate a token? The XsrfTokenServiceServlet RPC service on the server generates the token, as part of each call to the server, as you've observed, XsrfProtectedServiceServlet.validateXsrfToken then verifies that this is correct. If you wanted custom behavior, you'd have to modify each side of that system, and you could build it to invalidate each token once it is used, but this is not the default (nor, according to OWASP, is it encouraged).
Another thing I noticed is if I add #NoXsrfProtect to saveName()...
Note that validateXsrfToken is only called in one place in GWT, from in AbstractXsrfProtectedServiceServlet:
#Override
protected void onAfterRequestDeserialized(RPCRequest rpcRequest) {
if (shouldValidateXsrfToken(rpcRequest.getMethod())) {
validateXsrfToken(rpcRequest.getRpcToken(), rpcRequest.getMethod());
}
}
The method shouldValidateXsrfToken then checks if the method expressly has the protection disabled. If so, it will return false, and no check will be performed. But when building up the RPCRequest object, RPC.decodeRequest always appends the token, even if that token happens to be null:
RpcToken rpcToken = null;
if (streamReader.hasFlags(AbstractSerializationStream.FLAG_RPC_TOKEN_INCLUDED)) {
// Read the RPC token
rpcToken = (RpcToken) streamReader.deserializeValue(RpcToken.class);
}
So if the client is configured to send the token, it will always be sent, though the server might ignore it.
More reading:
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) and https://www.owasp.org/index.php/CSRF_Prevention_Cheat_Sheet
http://www.gwtproject.org/doc/latest/DevGuideSecurityRpcXsrf.html

is it possible to check the authentication status of an HTTP post request before getting the response?

I'm using java.net.HttpURLConnection.
I first write the body of the post request to the OutputStream associated with the URLConnection object.
After I have done that, I close the OutputStream and then call getInputStream() or getResponseCode() or getHeaderFields(). That's when I find out if the provided credentials were considered valid or not valid.
This is problematic, because I don't want to make the same post request again (and have to re-upload its contents, which could include large files) in the event that the user credentials were rejected for some reason.
Since an exception is thrown if there is an attempt to call getOutputStream() after getResponseCode() or getHeaderFields() have been called, how can I ensure that the user credentials were accepted before attempting to upload the data?
Is there a way around this or is it just the way the server is configured?
The short answer is: You can't do that.
Basic auth is stateless. When you're doing a POST/PUT the user credentials are sent as headers for that HTTP request. They are not processed until the entire operation is complete (i.e. after you've sent the data payload).
In order to do what you're talking about you'd need to write a web service that managed login and file/data uploading separately through session management, allowing you to first authenticate (returning a session token of some sort) then send the data via a separate HTTP request.
Edit to add: In reality, you could hack your way around this by simply doing a GET to something that also requires auth. If it succeeds, you know the POST will also succeed baring the credentials being invalidated server side between the two requests. I would not advise this, but it would work.

Categories