I'm debugging a scenario in my production environment where I intermittently see unexpected HTTP 401 responses from my resource server. I'm using Spring Security OAuth2 (the "old" OAuth libraries; pre Spring Security 5.2.x and its implementation of OAuth2) to handle requests and perform Authn.
What I'm observing is the following:
A user logs in at time x (time in seconds here) and obtains an access token. That access token expires at time x + 900 (15 minute validity).
At time x + 480, the user makes a request to a protected endpoint.
The request takes a long time to complete, such that it's still being processed when the token expires. At time x + 900, the server returns a HTTP 401 response.
Questions:
Is this really how Spring Security OAuth2 works? To be more specific, does it track the token's expiration time and return a 401 if the request is still being processed when the token expires? Or on the other end of the security filter, when the response is being prepared?
Is there a way to disable this behavior, so that the token is only checked when the request is first processed?
I had a look at the source code for spring-security-oauth2 and this is not how it works. The token expiration is only checked one time, at the beginning of processing of the request.
I traced the issue I was having above to a problem in which our server resources were maxed out for a period. When resources (CPU; HTTP request worker threads) became available, the server started processing the request, but by this time the token had expired.
Related
Our team is developing a simple Angular website that sends a form data to our backend via API. This website will be published under a public IP, so the interaction will be protected with Google reCAPTCHA v3.
Recently we decided to run some stress tests in a pre-productive environment in order to see if everything is stable and works correctly. So we set up a simple JMeter tests group with 100 users and 100 loops. This way we had 10000 requests in total to our API. So, having all that configured, we ran the frontend in order to generate a reCAPTCHA token, executed the action which sends the data to the API and copied the generated token into the JMeter configuration.
The API, before passing the form data to the backend, checks if the token is valid by making a request to “https://www.google.com/recaptcha/api/siteverify”, specifying this token and the secret key generated in the reCAPTCHA admin console.
After executing the JMeter tests, we saw that a certain amount of requests bypass the validation of the token and end up in the backend, while the token has already been used.
What we tried?
Stress test of our API with 10k requests in order to try the validation of an already used reCAPTCHA token.
What we expected to happen?
All the requests to return an error code of 401, beacause the reCAPTCHA token has already been used before and those tokens are single use only (the 401 code is returned by our API if the request to "/siteverify" returns a "success:false" in the response body or a status code other than 200).
What actually resulted?
5% of the requests bypassed the validation and ended up in the backend.
JMeter results
(The 400 bad request errors are returned by the backend, after the validation of the token has already been done, meaning that the token was assumingly valid)
We chequed the logs of our API and we've been able to verify that, in fact, the "/siteverify" requests return a status code of 200 and a response body of "success:true" in those 5% of the tests.
To me, it seems like some kind of balancing problem, maybe some node didn’t have enough time to replicate the status of that token? Or maybe the problem comes from our implementation… Hopefully someone could give us a hint!
I have an app built with Spring Boot, it's using Apache Tomcat 8.5.53.
It all works fine, but sometimes my users get the following message:
HTTP Status 403 - ForbiddenType Status ReportMessage Invalid CSRF Token '1423gi43-3452-65t3-cg8d-21a75cd7gc3x' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'
Then they refresh the page, login and it all works fine.
This doesn't always happen, and it doesn't happen for the same request. My users perform normally other operations before they see this message. However, it happens most of the time on post or patch requests.
I have seen issues on stackoverflow where token is null, but in my case it randomly expires.
I don't want to remove the token.
Has anyone experienced (and hopefully solved) this issue before?
I have web application where I am uploading the large file more than 1 GB from browser to the server. Depending on network speed some time it will take more than 1 hour.
Server endpoint is secured with OAuth.
When upload request is sent from browser it has valid token with 1 hour expiry.
In case of large file upload, it gives Unauthorised error because of token expiry after 1 hour.
How can I solve this problem where token should validate only in the beginning of the request not after complete file upload?
Technology used
AngularJs - UI
SpringBoot version 2 - Backend
POST request
Content-Type: Multipart/form-data
I dont have option to increase the token expiry beyond 1 hour.
The reason is that the tomcat will receive the file firstly, then dispatch the servlet request to your controller. When the upload takes too long time and the token has already expired, the security check will return 401, and your request will never enter the controller (the security check is before your controller).
You can put a breakpoint in your controller with the MultiPartFile parameter, then try to upload a huge size file to verify what I said.
One possible solution is you resolve the servlet yourself, maybe something like:
uploadFile(HttpServletRequest rawRequest)
Then when a token already expired, you can refresh it rather than return 401 then discard the already uploaded file.
Hope this may help you, and if you have a better idea, please let us know. Thank you!
useful link: https://docs.spring.io/spring-framework/docs/5.3.x/reference/html/web.html#mvc-multipart
I have a http request that auto generates '_token' value with the request(this value generated under http request only, not in the response of this request) and this '_token' value needs to be passed to the next http request header as 'authorization'. I know we can use JSON/RegEx post processor if it is in Response of the first http request. However how it be be correlated if the dynamic value is in http request.
Please suggest how can we achieve this in jmeter.
Most likely you are trying to load test an application which uses OAuth and depending on OAuth version and your application setup there could be different options. If the token is permanent - you can just put it into HTTP Header Manager, however if the token expires more or less frequently - you will need to implement OAuth flow using JMeter (in some cases you will need some extras like scripting, kick off browser to open a redirect URL or use OAuth client libraries). Check out How to Run Performance Tests on OAuth Secured Apps with JMeter article for details.
I would suggest contacting your application developers to learn about OAuth version, settings, required client id/secret, etc.
My Restful service application developed with Spring 3 is deployed on Tomcat7. I use a chrome app called Postman to request REST services.
I have a custom-filter placed before all the services (except the non-secured service login) for checking Session and application specific cookies.
This filter returns HTTP status:403 if cookies are not present or invalid in the incoming HttpServletRequest. The filter (myCustomSecurityFilter) is Singleton scoped.
<security:intercept-url pattern="/services/v1/login" access="permitAll()" /> <security:custom-filter before="FILTER_SECURITY_INTERCEPTOR" ref="myCustomSecurityFilter" />
I observed that in a speicific case old HttpServletRequest is used. Please see the following scenario
Case #1: All requests are over HTTPS.
All cookies are removed and browser is restarted.
Call HTTPS serveice: ..\services\v1\account. As this service has to be called after ..\services\v1\login, 403 response is expected. Actual response :403.
A new session is created and a JSESSIONID is returned by Tomcat. Say, JSESSIONID_1.
Request ..\services\v1\login . Expected and Actual respose 200-OK.
A new session is created and a JSESSIONID is returned by Tomcat. Say, JSESSIONID_2.
Also application specific cookies are returned to client/browser. Say, App_cookie_1.
Call any other service other than ..\services\v1\account. All are successful(200).
Cookies JSESSIONID_2, App_cookie_1 are sent by request and the same can be observed after receiveing response.
Note: This step is not important. Step 5 can be reproduced with or without this step.
Request ..\services\v1\account. Expected: 200. Actual: 403.
When I debugged the HttpServletRequest received by the doFilter method in my SecurityFilter mentioned above, I see that the HttpServletRequest contains old cookies of the previous request to the same service ..\services\v1\account.
i.e JSESSIONID_1. No app cookie.
I checked cookies with the help of httpServletRequest.getCookies()
Browser shows Cookies JSESSIONID_2, App_cookie_1. I am sure that Tomcat receieves Cookies JSESSIONID_2, App_cookie_1 becasue I have access logging enabled.
So, it is Spring (my code or config on top of the the Spring framework) passing old HttpServletRequest to filter. But how? why?
Request ..\services\v1\account. Expected: 200. Actual: 200.
Cookies JSESSIONID_2, App_cookie_1 are sent by request and the same can be observed after receiveing response.
So, old cookies are used only once and that too only for the same service in this case (..\services\v1\account).
Webapp works as expected in the following cases (above steps are denoted by numbers):
Case2: 1,2,3,4,5,6. All are HTTPS requests except #2 (login request). #5 returns 200 if #2 is a HTTP request!! This is also a surprise.
Case3: 2,3,4,5,6.
Case4: 2,3,5,6.
Step 4 is not important. Step 5 can be reproduced with or without this step. I placed this to explain that previous request of the same service is loaded and no effect on other services.
Problem is definitely not with ..\services\v1\account. Because I just used this service for example. Case 1 can be repeated with any secured service in the application.
I tried managing my session with newSessio, migrateSession options.
<security:session-management session-fixation-protection="newSession">
<security:concurrency-control max-sessions="1" />
</security:session-management>
Thanks for reading my question. It would be great if you could give some pointers.
Please let me know if I am not clear.
(answering as I faced a similar problem recently. Even though the question is too old)
..\services\v1\login
A new session is created and a JSESSIONID is returned by Tomcat.
How is the session created here?
Assuming its typically created like below
HttpServletRequest.getSession(true);
there is a high chance server gets an old session here.
Can you try a
session.Invalidate()
or
request.logout()
So that any open session is invalidated.after that you try creating the session again
HttpServletRequest.getSession(true);