I'm building an app that has a frontend for both iOS and Android, and a Backend composed of a Flask API and a MySQL database.
Right now, our authentication uses JWT. Except that I'm not sure I totally understand how it is supposed to work.
I don't know where to find the specifications for JWT, so when I say JWT I simply mean a JSON payload encrypted using the PyJWT library.
Currently, the expiration of the tokens happens 6 months from their creation.
I feel like this is a rather insecure setup.
From all the examples I've seen, JWTs have a very short lifetime, and then there's some sort of "refresh token" that renews it.
But that's all I know. I don't understand it well enough to code it in Python.
Could someone please help explain what this refresh token is, what exactly it does, how it is created, etc.?
UPDATE:
As for the specifications for JWT, I read this: https://www.rfc-editor.org/rfc/rfc7519
It doesn't mention any refresh tokens.
So now my question is, is what I'm doing secure enough?
Is it worth it to have a logout API endpoint that sends the token and adds it to a blacklist, so no one can steal it?
Six months for a JWT is way too high and unsecure. You might want to keep it a few hours or a day max. Along with that, have a long lived refresh token (RT), which you can use to keep getting new JWT. The function of the refresh token is to maintain a long lived session (so that the user can be logged in for a long period of time), to detect token theft (if you keep changing the RT on each use) - since you mentioned stealing, and to enable you to use short lived access tokens (since those are exposed over the wire most frequently). And yes, blacklisting JWTs can be a good idea, but if you are keeping them short lived, then why do that?
This topic is quite vast and complex. You can refer to my blog post about this - it provides information about all session flows, their security and also has an end-to-end implemented library.
Related
I only need oauth2 for login so far, but I feel that to be reasonably complete, my app should still handle refresh tokens.
I'm fairly new to oauth, so here is my understanding:
By keeping access token lifetime short, but refresh token lifetime long, you force the client to "check in" regularly to renew the access token, and thereby maintain more control.
But how to actually do that using authlib and the flask integration?
There seems to be no refresh_token() on the FlaskRemoteApp, and I have not been able to find any example code showing this.
This seems to work to get a new token
res = oauth.myOauth2.fetch_access_token(refresh_token=session['tok_res']['refresh_token'])
session['tok_res'].update(res)
But fails when subsequently using the new access_token for an api call.
Could be a server error I suppose, or maybe I need to wait for the old token to expire before using the new one? The expires_at time, keeps updating and that makes no sense to me in that case.
It would be great if somebody could explain how refresh_token is intended to be used with authlib and flask.
Well, unless #lepture drops by with the answer, I have at least an answer.
I was simply missing grant_type='refresh_token' from my call.
So this now works as expected for me.
if session['oatoken']['expires_at'] - 2 < now: # refresh 2 seconds early
oatoken = oauth.myOauth2.fetch_access_token(
refresh_token=session['oatoken']['refresh_token'],
grant_type='refresh_token')
session['oatoken'].update(oatoken)
I played around a little with setting the update_token function in the registry, but was not able to make it work. In any case I believe this is only triggered if an api call using the token receives an "expired token" reply. In my case I'm only using Oauth for login, so I can just watch the expires_at time, and only hit the auth server when necessary.
I am learning Django and have an idea for an app that would access data on the Microsoft Graph API for users of their outlook service.
It seems the cleanest way of doing this is by using a package like django-all-auth to handle obtaining and storing the authorisation token in the backend. There’s also an example on the Graph API website using python-social-auth.
However, I’ve been informed here that I can use a library like jQuery to make the API call directly, meaning the JSON data returned from the 3rd party API could bypass my server and go directly to the user’s browser.
With a 3rd party API requiring authorisation I’d need to get the auth token from my django back end to the front end so that it could be used in the Ajax request.
I appreciate that it would be an option to use the implicit or PKCE flows in the browser.
However, as an alternative I’d had the idea that I could use the server side OAuth flow to store the access token and refresh token in the back end and then send the auth access token from django back end to the user’s browser to be securely stored and used from there.
The benefit of this, as I see it, is that if the user’s access token expired you could make a call to the back end to use the refresh token in order to provide a new auth token, thus requiring the user to log in fewer times.
I also don’t see how this can be any less safe than the implicit flow, although me not seeing it doesn’t mean it doesn’t exist!
I know I’d have to use SSL to avoid any malicious actor snooping on the token. I’d also need to account for CSRF and XSS vulnerabilities, but thankfully django comes with solutions to both.
Would this method be a bad idea and considered bad practice?
My rationale for considering this is that it would reduce greatly the overhead of my server if I could cut out the intermediate step of rendering the JSON response in the page template before it’s sent to the user’s browser.
I think what I’m describing is addressed here, albeit with different frameworks.
If anyone else reads this and thinks of a problem with what I’m proposing please let me know.
What is the best way to do user management in a single page JS (Mithril) app? I want users to login to load preferences and take on a role so they gain certain permissions. I have a REST API backend written in Python (Falcon web framework). Having read a bit into it, it seems to boil down to sending credentials to the backend and get a token back. But the question is how that should be done. It seems that tokens are a better method than cookies, but that has effects on the exchange of secrets/tokens. the 'xhr.withCredentials' method seems to be cookie based for instance. JWT (json web tokens) seems like a modern, interesting option, but it's hard to find a clear explanation how it could be used with a SPA.. And once the Mithril app has a token, where should I store it and how should I use it with subsequent requests?
This isn't so much about Mithril, actually the only Mithril-related area is the server communication. That is done with the m.request method (docs here), but you need to create an object for all server communication that requires authentication.
That object should have knowledge about the auth system and detect if a token expired, then request a new one, take proper action if things fail, etc. It's a bit of work, but the process is different for most auth systems, so there's not much to do about it, except using something that already exists.
Being a small and lean MVC framework, Mithril doesn't have any security-related features built-in, but the m.request method is very powerful and you should use that inside the auth communication object.
The client-side storage will be in cookies or HTML5 storage. Here's an StackExchange answer that goes into more depth: https://security.stackexchange.com/a/80767 but the point is that this isn't Mithril-related either.
Thanks for linking to the tokens vs. cookies article, it was very nice!
I am aware that these questions has been asked before several times separately, and most of the answers I've found are "Python is not easy to obfuscate, because that's the nature of the language. If you really need obfuscation, use another tool" and "At some point you need a tradeoff" (see How do I protect Python code and How to keep the OAuth consumer secret safe, and how to react when it's compromised?).
However, I have just made a small Python app which makes use of Twitter's API (and therefore needs OAuth). OAuth requires a Consumer Secret, which is to be kept away from users. The app needs that information, but the user should not be able to access it easily. If that information cannot be protected (and I am using obfuscation and protection as synonyms, because I do not know of any other way), what is the point of having a OAuth API for Python in the first place?
The question(s) then are:
Would it be possible to hardcode the secret in the app and then
obfuscate it in an effective manner?
If not, what would be the best way to use OAuth in Python? I have thought of "shipping" the encrypted consumer secret along with the app and using a hardcoded key to recover it, but the problem remains the same (how to protect the key); having the consumer secret in a server, and have the application retrieve it at start up (if information is sent unencrypted, it would be even easier for a malicious attacker to just use Wireshark and get the consumer secret from the network traffic than decompiling the bytecode, plus how could I make sure that I am sending that secret to my app and not to a malicious attacker? Any form of authentication I know would require having secret information in the app side, the problem remains the same); a mixture of both (have the server send the encryption key, same problems as before). The basic problem is the same: how can you have something secret if critical information cannot be hidden?
I have also seen comments saying that one should use a C/C++ extension for those critical parts, but I do not know anything about that, so if that were the answer, I'd appreciate some extra information.
If you want to deploy on servers (or laptop) you own, you can store secrets in env var or files. If you want to deploy to user, suggestion is that you, or your user should register an API key, generate ssl key, or similar.
You can code your own simple symetric crypt fucntion with a lot of data manipulation to make it harder to reverse.
It is unclear why you'd need to ship your OAuth key with the script. That would mean giving anyone access to your Twitter account, whether or not the key itself is obfuscated inside the app.
The more typical scenario is that you develop some Twitter client, and anyone who wants to run it locally will have to input their own OAuth token before being able to run it. You simply do not hardcode the token and require any user to supply the token.
I am a newbie and I want to do the following
I have service endpoints like
#login_required
#app.route('/')
def home():
pass
#login_required
#app.route('/add')
def add():
pass
#login_required
#app.route('/save')
def save():
pass
#login_required
#app.route('/delete')
def delete():
pass
I would like user to user to be authenticated while making these calls.
Question
How can I authenticate REST calls using python?
How do I make sure that if call lands to execute any of the endpoints, they are authenticated?
How do I basically do all authentication at the HTTP header level without saving any state so that it can scale better in future (Like Amazon S3), meaning any call might go to a different server and still be able to authenticate it self.
I am entirely new to REST world and don't really know how to achieve this.
Thank you
First, a question, are you authenticating a user, a client, or both?
For authenticating a client I like HTTP MAC Authentication for REST service authentication. Take a look at the Mozilla Services macauthlib and how it's used in their pyramid_macauth project. You should be able to learn from pyramid_macauth as an example in applying macauthlib to secure your services. A search to see if anyone else has tried this with Flask is a good idea, too.
For authenticating users and clients, perhaps take a look at OAuth 2.0 proper (HTTP MAC Auth is a related specification).
I had hoped to post more links, however, this is my first post and it seems I have to earn my way to more links in a response. :)
Security is not for noobs. Use a framework and rely on its implementation. Study the source code, read blogs and papers, and at some point you'll be able to architect your own system.
There are many things that may go wrong, and once you deploy a protocol you may not be able to come back without breaking existing clients.
That said, the usual way fot authenticating a request is by using a couple of tokens, usually called a public key and a private (secret) key. A variant is using the private key to generate a short lived session token. Another variant is using an API key specific per client. Anyway, this token is usually sent in a HTTP header (either a standard cookie or a custom one), but it's also possible to use the request body. Usually they are not appended to the URL because the secret may end in a log file. Also, you should pay attention to how and where store the secret key.
Depending on the channel (plain HTTP) you may want to use a HMAC to sign requests instead of sending secrets in the wild. You have to watch against replay attacks. Timing attacks are possible. Cryptographic collisions may be used to defeat your scheme. You may need tokens to avoid CSRF (this is not really needed if web browsers don't come into play, but you don't specify this)
Again, choose a framework and don't code anything by yourself. Broken software is usually ok to fix, but security holes can do real damages.
Looking at your API, it does not look like restful endpoints. The URI should represent a certain entity and not actions. For an instance if you are dealing with an entity such as user you could have yourdomain.com/user and perform various operations such as create, delete, update and fetch using HTTP verbs like POST, DELETE, PATCH and GET (Given that you use flask this can be achieved very easily).
In terms of security, I assume there are multiple schemes but the one which I have used is generating a session token given a key and secret via an initial authenticate call. I suggest you look for specialized online resources on generating key and secret pair as well as the session token.
In terms of scaling I guess your concern is that the sessions should not be specific to a given machine. The authentication data can be stored in a store separately from the HTTP front-ends. This way you can add additional webservers and scale your front-end or add additional data stores and scale either on a need basis.