Using the WSO2IS 5.1.0 (and I believe any version will have this issue) we are havving issues with incoming concurrent authentication requests.
The consurrent authentication requests can happend in two cases (as we see that):
First: When the user is not yet authenticated with multiple posts of the logon form. This happens when the users are not patient enough and double click the logon button (or spamming the logon submit button, some users do that). Using the custom logon pages we have some control over the UI and we can prevent the user from multiple posts (by disabling the submit button on submit).
Second (this is where we see the real issue): When the user is already authenticated, receiving multiple authentication requests will send the user to the retry.do page with an error message.
FINEST|6940/0|Service WSO2IS510|16-10-18 11:05:39|[2016-10-18 11:05:39,295] ERROR {org.wso2.carbon.identity.application.authentication.framework.handler.request.impl.DefaultRequestCoordinator} - Exception in Authentication Framework
FINEST|6940/0|Service WSO2IS510|16-10-18 11:05:39|java.lang.NullPointerException
FINEST|6940/0|Service WSO2IS510|16-10-18 11:05:39| at org.wso2.carbon.identity.application.authentication.framework.handler.sequence.impl.DefaultStepBasedSequenceHandler.handle(DefaultStepBasedSequenceHandler.java:105)
FINEST|6940/0|Service WSO2IS510|16-10-18 11:05:39| at org.wso2.carbon.identity.application.authentication.framework.handler.request.impl.DefaultAuthenticationRequestHandler.handle(DefaultAuthenticationRequestHandler.java:115)
FINEST|6940/0|Service WSO2IS510|16-10-18 11:05:39| at org.wso2.carbon.identity.application.authentication.framework.handler.request.impl.DefaultRequestCoordinator.handle(DefaultRequestCoordinator.java:135)
FINEST|6940/0|Service WSO2IS510|16-10-18 11:05:39| at org.wso2.carbon.identity.application.authentication.framework.servlet.CommonAuthenticationServlet.doPost(CommonAuthenticationServlet.java:53)
FINEST|6940/0|Service WSO2IS510|16-10-18 11:05:39| at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
FINEST|6940/0|Service WSO2IS510|16-10-18 11:05:39| at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
This is related to my older post.
Concurrent auth requests are becomming more common using the HTML5 applications (accessing their services with 401 result will redirect the user with an authentication request). In this case the processing of the same cached authentication context within multiple threads will bring the authentication context into an invalid state. Unfortunatelly - the service providers are outside out our control and we're unable to force sending only a single request at the time.
Are there any ways to synchronize / lock the authentication context until processed?
Concurrent user login restriction is not yet supported in WSO2 products. This has been raised as an improvement [1] and may get included in the future.
[1] https://wso2.org/jira/browse/IDENTITY-4191
Related
We're using django-notifications-hq to provide users with persistent notifications in our app. Until recently, they lived only in the web app, however now we want to show the notifications in the mobile app as well.
Also, our server is set up with CSRF.
All the endpoints provided by django-notifications-hq use #login_required annotation to verify that user is authenticated.
However, when we're trying to call any of those endpoints from our mobile app, we get 403 response. To be specific, the first OPTIONS request returnd 200, but then the following request for those APIs always results in 403.
This is not a problem when we're using i.e. django-rest-framework's permissions.IsAuthenticated.
The 403 returns this in the response:
<h1>Forbidden <span>(403)</span></h1>
<p>CSRF verification failed. Request aborted.</p>
<p>You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is required for security reasons, to ensure that your browser is not being hijacked by third parties.</p>
<p>If you have configured your browser to disable cookies, please re-enable them, at least for this site, or for 'same-origin' requests.</p>
Suggesting it's a CSRF problem, even though mobile app obviously doesn't provide cookies in their requests (it's token-based authorization).
Is this a general issue with #login_required (perhaps it can't be used at all with token-based authorization) or is this some misconfiguration on our part? I couldn't find a clear answer when looking for solutions.
Is there a significant implementation difference between django's #login_required vs django-rest-framework
#permission_classes((permissions.IsAuthenticated,))?
I have multiple django servers (API backend for mobile clients) running behind a load balancer. But when accessing django admin some times I'm getting 403 forbidden error. Is it related to csrf cookie ?
My load balancer setting is,
Session Stickiness - None
Algorithm - Roundrobin
I can't imaging any situation when it's possible until you do all job in one browser tab. When you request form (with GET-request) you generate csrf cookie (if it doesn't exist yet) and generate csrfmiddlewaretoken for this cookie, in response you get both csrf token and cookie value in consistent state. On POST-request your browser send them both and compare on server side. So, this behavior shouldn't depends on backend. But you always can test your assumption with logger. From the documentation:
CSRF failures are logged as warnings to the django.security.csrf
logger.
Changed in Django 1.11:
In older versions, CSRF failures are logged to the django.request logger.
I'm reading through openid connect document ATM and it says:
Put into a browser cookie the ID token can be used to implement lightweight stateless sessions.
IIUC we want to avoid using cookies in order to ensure avoid CSRF attacks, since the browser will send the cookie with all requests, and if the user loads an image (While logged in to notsosecurebank.com) with the URL:
href="http://notsosecurebank.com/transfer.do?acct=AttackerA&amount;=$100">Read more!
The browser will send the access token (Since it's a cookie) and this allows the attack to happen.
If the token is storage in session or local storage and only sent via REST / XHR requests, then there's no way for CSRF to happen? Did I understand this correctly?
We make react SPA with django-rest-framework on backend and use django-rest-auth for user authentication.
When user has logged in, we show him form for change profile data. When user submit this form, we take csrf token from cookie in login response, and put them in request X-CSRFToken header. Server responses that token is missing or incorrect.
If user refreshed the page, and repeated the same actions, csrf token is correct and profile data is updated.
How to solve this problem and why it occurs?
It looks like this is happening:
The login is successful
The cookie+token is created by the CSRF API and returned to the endpoint
The ready state executes some code not executed after the API response
The certificate is validated and the cookie+token is set in the database/app config/server-side cache during a GET request and/or by the ready state callback
Since there is no GET request until the refresh, the cookie+token is not centrally stored until then. Add a request to mimic what happens during the GET, then store it where it is currently being accessed for subsequent requests.
References
Issues with CSRF token and how to solve them | SAP Blogs
Why refresh CSRF token per form request? - Information Security Stack Exchange
CSRF Protection — Flask-WTF 0.14
CSRFGuard 3 Configuration - OWASP
Spring Security: Cross Site Request Forgery (CSRF)
Cross Site Request Forgery protection | Django documentation | Django
XSRF/CSRF Prevention in ASP.NET MVC and Web Pages | Microsoft Docs
Cross-Site Request Forgery is dead!
Still think you don't need HTTPS?
I am building a rails paypal integration, I am ussing the sandbox
and after the purchace I am redirecting the user on a "Your transaction has been completed"
page.
I want to prevent though users to directly access the page.
So I am trying to trace HTTP_REFERER but is not been set
request.env.has_key?('HTTP_REFERER')
<http://stackoverflow.com/questions/3104711/ruby-on-rails-request-envhttp-referer-returns-nil/3104799#3104799>
I suggest doing it another way. Trusting the referrer is not a very secure way to prevent users from accessing pages as it can be easily manipulated by the user and it is unreliable.
Typically, if you're re-directing from HTTPS to HTTP, it will be empty as I suspect this is the case.
I would use either sessions or the PayPal token to prevent users from accessing the page. If an order session number is set, and payment is completed through PayPal (PayPal will send you details back that the payment is a success, token etc.), then display the payment completion page.