Reputation: 163
I am using spring and enabled csrf with HttpSessionCsrfTokenRepository, I clearly know if the client is sending the csrf token either as _csrf parameter or X-CSRF-TOKEN header for the request spring picks up the token and validates with the token which was generated using generateToken(HttpServletRequest request)
But my question is how does spring does this internally.
My reason for this question being:
1.I have a Rest POST call which takes credentials and validates the identity of the user. But Since I want to add a csrf token to the rest call as a layer of security I wanted to add it in the post body to prevent csrf token leak.
So if I know how spring security filters these tokens internally it would be helpful. I revised the spring documentation but it is mostly how we can use CSRF token in a form with hidden field or meta tags and Ajax call with a header.
And I also would like to hear any comments on my design if it is good to have the token in body( I am convinced because it would not be a simple url parameter to leak the token ) or should I have it in the header. I just dont want to lean to use header just because its simple. Looking for the best solution.
Please shed some light.
Upvotes: 3
Views: 7651
Reputation: 109
Note: This info is for Spring Security 6
, but it's probably the same for older versions too.
The request type should be POST/PUT/DELETE
to debug the flow yourself. (Not GET
what I want to say)
Now, let's jump into the flow.
CsrfTokenRepository
interface implemented by two classes: CookieCsrfTokenRepository
& HttpSessionCsrfTokenRepository
CookieCsrfTokenRepository
will be used.loadToken(HttpServletRequest request)
will be called to extract the token from the cookie received from the request. (loadToken method is in RepositoryDeferredCsrfToken
class)DefaultCsrfToken
will be created. (new DefaultCsrfToken(this.headerName, this.parameterName, token)
)CsrfFilter
class.requestHandler.resolveCsrfTokenValue(request, csrfToken)
method extracts the CSRF token from the header/param. (The method looks like this below)@Override
default String resolveCsrfTokenValue(HttpServletRequest request, CsrfToken csrfToken) {
Assert.notNull(request, "request cannot be null");
Assert.notNull(csrfToken, "csrfToken cannot be null");
String actualToken = request.getHeader(csrfToken.getHeaderName());
if (actualToken == null) {
actualToken = request.getParameter(csrfToken.getParameterName());
}
return actualToken;
}
403 forbidden
status is returned as usual :(Upvotes: 0
Reputation: 999
There're multiple implementations for CsrfTokenRepository in spring if you want to look into into it. for eg:
IMO its good (safer - may be?) to keep Tokens on the header because of few reasons that i can think of..
You cannot set token on a body for your GET request. You want to be consistent of all your endpoints (you may not need it today but things change really fast)
Tomorrow if you want to change your Auth model, you dont want to to change your request body. when request body changes you break the contract with clients
If you change your auth model to a authorization server, you can add proxy server (like ngnix?) before your service and lets call it auth-proxy. You can leave all security related things to this auth-proxy and it will inspect the header and do the validations for you. You don't want the proxy to look into your request body and you can focus on your business implementation
It's just my opinion based on my experience.
Upvotes: 4