DRF + SimpleJWT 401 on Timeout - django

We use DRF + SimpleJWT and we're finding that when our servers get overloaded or timed out, we're passing a 401 on the token refresh endpoint and causing users to be thrown back to the login screen (because a 401 indicates that the user is no longer authorized to view anything).
Does anyone know why this might be? It only happens under really bad network conditions – we've ruled out the client and do believe it's the server returning a 401 somewhere now. When the user kills the app after being thrown back home, they are authenticated on next launch again, so it seems like we're issuing a 401 on timeout or something like that.

Related

How does Djoser JWT login flow works

So I've been trying to use Djoser JWT and I don't know how to login in it. As far as I know you create a request with your login credentials to this url /jwt/create/ and get the access and refresh token and maybe get the user object from /users/me/. This is where I got stuck, where do I go from here?
You correctly understood the first step of the process. Basically, you can now:
Add the access token in the header of your next requests.
This will transparently authenticate the user thanks to the Simple JWT plugin and you will be able to access him with the usual request.user in the views.
Refresh the access token each time you get a 401 response.
The access token is supposed to be short-living for security concerns and a 401 response from the server indicates that the one your are using is expired. So you have to get a new one by sending the refresh token to the token/refresh/ API and, then, make your request again.
You can read this article if you need more detailed explanations about this process or JWT.

IdentityServer4 external logout doesn't remove Google sign-on cookie

I am having trouble logging out of my identityServer under Google login. I can login through Google (external) with no issues but the logout never worked. After clicking on "Logout" I always get a message says "you are now logged out". But when I try to log back in again, I always get right in after clicking on the Googol button. My Chrome's Dev Tool shows that a cookie associated with my Google login left in there regardless if I click on logout.
And if I clear the cookie via Chrome, I will be able to get to the Google login page.
In trying to delete the cookie in my program when logging out, I tried the following code from the AccountController's Logout function. I watched the code got executed in debug mode, but it doesn't make any difference - the cookie is still there after the code gets executed and I am still get right in.
Could anyone tell me what I am missing here? Or is it just impossible to delete cookie from code?
To do an upstream signout the IDP (Google) would have to support the RP-initiated logout spec:
https://openid.net/specs/openid-connect-rpinitiated-1_0.html#RPLogout
However Google's discovery endpoint (https://accounts.google.com/.well-known/openid-configuration) does not advertise an end_session_endpoint so from that we'd have to conclude that it is not supported by Google.
However you may be able to use prompt=login or max_age={number of seconds} in your authorization_endpoint endpoint request to force interactive authentication again. When you receive the id_token in the callback you can validate that the auth_time claim falls within whatever condition you decide. The end result is that you can insist that users interactively authenticate each time you do a round trip to Google. If auth_time is too far in the past you'd prevent the local session from being established.

How to return 401 authentication from flask API?

I have developed an API in flask which is using HttpBasicAuth to authenticate users. API is working absolutely fine in fiddler and returning 401 when we pass wrong credential but when I am using the same on login page I am getting extra pop up from browser. I really don't want to see this extra pop-up which is asking for credential (default behaviour of browser when returning
401
with
WWW-Authenticate: Basic realm="Authentication Required"
).
It is working fine when deployed locally but not working when hosted on remote server.
How can we implement 401 which will not let browser to display popup asking for credentials.
So, flask return statements are actually processed again before sending the data off to the client. You can actually send a tuple of two elements as a return statement. The second element is the status (https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) If you are using the auth library, you can change this:
#auth.error_handler
def unauthorized():
response = jsonify({'message':'Failed'})
return response
To this:
#auth.error_handler
def unauthorized():
response = jsonify({'message':'A winner is you'})
return response, 404
If you don't want the popup message, change 401 to anything else.
This is a common problem when working with REST APIs and browser clients. Unfortunately there is no clean way to prevent the browser from displaying the popup. But there are tricks that you can do:
You can return a non-401 status code. For example, return 403. Technically it is wrong, but if you have control of the client-side API, you can make it work. The browser will only display the login dialog when it gets a 401.
Another maybe a bit cleaner trick is to leave the 401 in the response, but not include the WWW-Authenticate header in your response. This will also stop the login dialog from appearing.
And yet another (that I haven't tried myself, but have seen mentioned elsewhere) is to leave the 401 and the WWW-Authenticate, but change the auth method from Basic to something else that is unknown to the browser (i.e. not Basic and not Digest). For example, make it CustomBasic.
The following works. See docs.
from flask import Flask, abort
app = Flask(__name__)
#app.route('/api/endpoint/', methods=['GET'])
abort(401, description="Error message you want the reader to receive.")

What Response Should Be Sent Back a When Cross-Site Request Forgery (CSRF) is Detected

What response should I send back when a Cross-Site Request Forgery (CSRF) is detected?
There is a scanning tool which I cannot get a hold of that is saying one of my pages is not protected against CSRF. But it is. The response I send back is a normal 202 with the sentence "REQUEST CANNOT BE PROCESSED". That's it, nothing informative is sent back to the attacker, and I log the attempt. But this software says it is still susceptible to CSRF. I could easily run tests myself and figure it out but it's a long time in between scans and tests and I can't get the same software, that's why I'm asking stackoverflow, so I can hopefully knock it out on the next scheduled scan. I'm thinking of sending back a statusCode of 404 or 410 instead of a 202. http://www.cfgears.com/index.cfm/2009/8/11/cfheader-404-status-codes-and-why-you-shouldnt-use-them
What do you recommend sending back when a CSRF is detected?
403 Forbidden as the user is technically authorized to access the site, it is just the specific action that is forbidden (HTTP POST without correct CSRF token).
A web server may return a 403 Forbidden HTTP status code in response to a request from a client for a web page or resource to indicate that the server can be reached and understood the request, but refuses to take any further action. Status code 403 responses are the result of the web server being configured to deny access, for some reason, to the requested resource by the client.
Bear in mind that the attacker will not be able to read this response, and for the most part the user will not see the message or HTTP response because a CSRF attack is not designed to be obvious to the victim that it is happening. If you have an effective CSRF mechanism, your site is not likely to be attacked in this manner anyway - the defense is also the deterrent.
How about:
401 Unauthorized
or
403 Forbidden

What status code should I use when session token is invalid?

When creating a web service (RESTful), what status code should I use when session token is invalid?
Currently the one in my company sends me a 404, not found, but I think this is not correct, because the resource exists.
Maybe I should use 401 Unauthorized.
What do you think? What status code do you recommend me to use in this scenario? Thanks.
401 Unauthorized.
Your existing session token doesn't authorize you any more, so you are unauthorized.
Don't forget that a session token is just a short-cut to avoid having to provide credentials for every request.
Sending 404 is incorrect because, as you observe, the resource does exist. You just don't currently have authorization to see it.
NB Don't use 403 Forbidden; the HTTP specification defines it as follows: "The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated." That doesn't apply in this case as authorization WILL help.
Looking through the HttpStatusCode enum, I think Unauthorized is probably the closest to what you're looking for.
Take a look at the list there, and read the descriptions for each one.