How to correctly authenticate Python Flask-WTF web app users against Python Flask API using JWT - python-3.x

I'm new to Python, but have previous experience writing .Net web apps.
I'm working on a website written in Python using Flask-WTF (html pages with forms and individual routes for GET and POST requests). The app makes calls against a Python Flask API that talks to a MySQL db for user authentication (user table with names and hashed passwords). Everything the user sees is handled by the web app UI, and all the logic is handled by the API.
I followed Miguel's Mega-Tutorial (https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world) to learn the basics of the Python language and how to solve a number of problems along the way.
I need my users to log in once a day (set tokens to expire every 12-24 hours or so), but then have access to the app to perform whatever actions they need. I have a Login form that grabs username/password and submits that to an API endpoint. The API verifies the user data against the db, generates JWTs (access and refresh tokens), and writes them to cookies in the response. I am able to see that the cookies are set in the web app after the initial login and verified the contents using https://jwt.io. The only thing I need from the user login after verification is the username for when a user makes a change to database entries.
The Problem: How do I actually use the info in the cookies to call subsequent #jwt_protected methods in the API? When I add the #jwt_required to a post(self) function and try to access it I'm getting back a 401 with { "msg": "Missing cookie "access_token_cookie"" } that appears to be coming from the jwt_flask_extended library. I used "access_token_cookie" as the name of the cookie for the JWT token. Are the tokens magically handled by FlaskWTF/flask_jwt_extended and I'm just using it wrong? Do I need take the info out of the cookie and add it as a header on subsequent requests? If I send the info in a header, how does the API know where to look? I have a feeling it's something minor where I'm just not connecting the obvious dots.
I'll create a standalone app to test out just the authentication features between UIs and APIs that can be shared as opposed to trying to rip out existing code minimize the existing app and api to the bare minimums in case anybody else comes across a similar problem. This might also show me what my problem really is.
The final version of the app and api will both be hosted in a Cloudfoundry environment in case that has any bearing on suggestions.

Related

Can anyone outside use my api to make requests?

I am currently learning full stack dev, and have made a simple application with React on the front end, and set up a very simple REST api on my express web server that handles certain routes.
For example api/users returns a list of users from my database and returns responses as JSON data. api/blogs can return a list of blogs in JSON with a get request, or post a blog with a post request.
I have learned and been able to implement very basic user tokenization with JWT, and so only logged in users with a valid token can make a post of a blog for example. This is done by adding their token with bearer as a Authentication header in the request, which the server verifies. This makes sense to me, however I am very confused on how the backend works or if I am doing something critically wrong.
If I go to my main page for my application, and type api/blogs it opens up a page displaying JSON data. Anyone can basically view this from my application by going to api/endpoint
I am also assuming anyone from outside can use something like Postman to send a post request to my database assuming they have the token which they got since my token is saved in storage.
This is incredibly weird to me Is this just how these things work? Or am I failing to understand something crucial?
if I wanted to progress forward and learn more about this, where or what do I do?
You have described how users authenticate to your application (with a bearer token), but what steps does your application take before issuing such a token?
Does your application keep a database of users and their passwords?
If yes, can anyone sign up by inventing a user name and password?
Do you verify an email address before admitting a new user?
Or does your application rely on an external OpenID Connect service (for example, login with your Google or Facebook account)?
If yes, can anyone with a Google or Facebook account sign up for your application?
Or must an application admin (that is, you) put the user on an "allow-list"?
To summarize: Unless you take special precautions, anyone from outside can sign up to your application and subsequently use it.

How do you handle navigation in a token-secured web application?

I have a rather conceptual question, I'm sure it's fairly stupid, but I can't figure it out.
So I am building a simple node.js app to learn, I want to make a web app which is has a set of REST web APIs for everything (including authentication), and then the presentation.
For authentication I am using token-based auth with PassportJS.
So when a user wants to access the site, he'll obtain a token from the authentication API, in turn he'll need to pass this token in a HTTP Header on each request to the app.
My question is, how is this handled in the code? When the app gets the token (for example from a login page which hits the auth API), should it attempt to store it in the local machine (for example LocalStorage, or Cookie) and then on each new page fetch it and use it in a Header? Should each page's javascript attempt to load the token from the local storage automatically? I tried looking for an example, but haven't found a complete one that deals with how you handle navigation when you're depending on sending a header on every single request (that you want authenticated).
Thanks!
Once the user is authenticated return a secure session cookie which will be stored by the user's browser. Now on every request, this cookie will be sent by the browser to your application automatically, which you can check in your backend code (typically controller) to verify the existence of user session.

PHP REST API Key and User Token Authentication

I wanted to check with you guys if my API Key and user Authentication scheme makes sense or not. My server side code is in PHP and the Database is MySQL. This is the scheme I have in mind:
I am implementing a REST API in a backend server that will be called by a Mobile App (for now). At this point, I only want known Mobile Apps to connect to this API. So I am using a one-time API Key that has been given to the Mobile App during installation. Every request from the App passes the API Key that my API checks before going further. This Key is stored in a Database table. This completes my API Key checking and seems to allow only known Apps from calling my APIs.
Next, I also have certain services after calling the API which only authenticated users are supposed to get access to. For this, the Mobile App logs in with a Username and password which is authenticated in the User table of my Database. If it passes, the server generates a User Token and passes it to the Mobile App. The User Token is also saved in the User table against that User. All subsequent requests from the App (which requires user authentication) passes this User Token which is checked in the User table in the Database for User Authentication. If the Mobile App logs out, this User Token is deleted from the User table. I also have provision to add "TimeToExpire" for this User Token which I will implement later.
I would be really grateful if you guys could tell me the following:
Does the above structure makes sense for App Authentication and User Authentication?
I am a little lost as to what will happen if I ever need to change the API Key (for whatever reason). Not sure how that will be sent to all the Apps. Google Messaging seems like one possible way to handle that.
For the App Authentication, does it make sense to keep the API Key in a Memcached object? Since all requests from the Apps are authenticated, I don't want to go to the DB everytime. And pros/cons?
Along the same lines, does it also make sense to have the User Token in a Memcached object as well? Pros/cons?

The "right" way to do oAuth from a mobile client

I am building a cross platform mobile application (using the Xamarian tools, MonoTouch / MonoDroid). I am trying to work through the authentication workflow and am running into a stumbling block. I have searched all over for a clear answer and have yet to find it.
Here is an overview of my current setup.
I have a web site built in nodejs.
I use passport.js to do oAuth login on the web site. This works great, users can login to my site using Twitter or Facebook.
Now I want to extend this same login functionality to my mobile clients.
I see 2 options
Embed the app id and app secret's in the mobile clients and make direct oAuth calls to FB or Twitter from the mobile app
Proxy the oAuth calls through my existing nodejs web server (keeping the secret keys on the server)
Option 2 appears to be the preferred way (as it avoids having to "ship" the secret in the mobile apps).
I have the proxy approach mostly working.
I open a WebView in my mobile client and point it at http://mysever/auth/twitter
This runs through my existing passport.js code and redirects the mobile WebView over to the Twitter login page.
The user then enters their creds on the twitter webpage on the device.
Twitter then calls my oAuth callback URL (which is my nodejs web server).
My server and Twitter handle the back a fourth handshake of obtaining the user profile information (As I understand it, this is the key to this approach, my server and twitter handle the handshake, the mobile client doesn't have to do anything or pass any tokens during this process)
Here is my problem:
It is this last step that stumps me. Once the handshake is complete on my server I have the user information I need on the server and need to send it back to the mobile client application
I can't figure out any way in the WebView control to grab the response object and grab a cookie, or header value (for instance) (this seems true for Android and iOS). I don't think it is platform specific. I think I am trying to do something that a WebView widget in mobile platforms just don't suport. It makes me think I am missing something obvious.
The only thing I have figured out is to have my web server "redirect" the mobile client browser to a fake URL that has the user info in the querystring. Something like myapp://info?userid=1234
Then in the mobile app I can hijack the URL loading and grab this url and get the data I need. I can then stash this userinfo, close the WebView control and move on to a native screen in my mobile application and user the userinfo in any subsequent REST calls to my nodejs server as a means of identifying the user.
This is massively kludgy for multiple reasons. The biggest of which is that the url is sent over the wire unencrypted and has all the data in plain text.
There has to be a better way to get the data from the web server back to the mobile client?
Or am I doing it all wrong?
The most straightforward way to implement oauth for Xamarin, both for iOS and Android, is using Xamarin.Auth. The starter documentation for the client is here. I think it should maintain everything securely and you will not have to worry about having to use your node server as a proxy.
You will need to provide your Application ID as part of the calls, but I don't there are too many or any security issues to worry about there.
I know this is going against what you already have implemented, but maybe this could help simplify things a bit.
This is the same dilemma that I have been dealing with.
This is how I currently deal with it.
In my app the client can come directly or via another service such as facebook which is my main one and hence the one which I have concentrated on.
Facebook can either redirect via a POST (desk apps) or a GET (mobile).
I check the initial request so see if has a service identifier - here is the facebook GET for example.
app.get('/', function(req, res) {
var paraUrl = URL.parse(req.url,true).query;
//The fb_source is shown -
//i need to go striaght to the facebook authorization since
//its coming from
//from a mobile device.
if (paraUrl.fb_source){
res.redirect('/auth/facebook'); //this is the passport part
return;
}
res.sendfile('index.html');
}
The facebook POST is slightly different in that you get an access token encode in base64url. The GET gives you a code which you can exchange for an access token but I had problems with it and just opted for tying into the passport system.
If a client comes direct I check for the session or a encrypted cookie which ties into the local strategy. This then checks the db for an access token which can used to access the facebook api for example.
If a client is unrecognised they are given the option to authenticate via facebook, google etc.
The main thing is that only 2 pieces of information are stored with the client, the passport session id and my app user id
connect.sid - encypted cookie
userId - encypted cookie
I would be interested to find out how other people are dealing with issue

How do I secure REST API calls?

I'm developing the restful web app that using some popular web framework on the backend, say (rails, sinatra, flask, express.js). Ideally, I want to develop client side with Backbone.js. How do I let only my javascript client side interact with those API calls? I don't want those API calls to be public and be called by curl or simply by entering the link on browser.
As a first principle, if your API is consumed by your JS client, you have to assume, that it is public: A simple JS debugger puts an attacker into a position, where he can send a byte-for-byte identical request from a tool of his choice.
That said, if I read your question correctly, this is not, what you want to avoid: What you really don't want to happen is, that your API is consumed (on a regular basis) without your JS client being involved. Here are some ideas on how to if not enforce, then at least encourage using your client:
I am sure, your API has some sort of authentication field (e.g. Hash computed on the client). If not, take a look at This SO question. Make sure you use a salt (or even API key) that is given to your JS client on a session basis (a.o.t. hardcoded). This way, an unauthorized consumer of your API is forced into much more work.
On loading the JS client, remember some HTTP headers (user agent comes to mind) and the IP address and ask for reauthentication if they change, employing blacklists for the usual suspects. This forces an attacker to do his homework more thoroughly again.
On the server side, remember the last few API calls, and before allowing another one, check if business logic allows for the new one right now: This denies an attacker the ability to concentrate many of his sessions into one session with your server: In combination with the other measures, this will make an abuser easy detectable.
I might not have said that with the necessary clarity: I consider it impossible to make it completely impossible for an abuser to consume your service, but you can make it so hard, it might not be worth the hassle.
You should implement some sort of authentication system. One good way to handle this is to define some expected header variables. For example, you can have an auth/login API call that returns a session token. Subsequent calls to your API will expect a session token to be set in an HTTP header variable with a specific name like 'your-api-token'.
Alternatively many systems create access tokens or keys that are expected (like youtube, facebook or twitter) using some sort of api account system. In those cases, your client would have to store these in some manner in the client.
Then it's simply a matter of adding a check for the session into your REST framework and throwing an exception. If at all possible the status code (to be restful) would be a 401 error.
There's an open standard now called "JSON Web Token",
see https://jwt.io/ & https://en.wikipedia.org/wiki/JSON_Web_Token
JSON Web Token (JWT) is a JSON-based open standard (RFC 7519) for
creating tokens that assert some number of claims. For example, a
server could generate a token that has the claim "logged in as admin"
and provide that to a client. The client could then use that token to
prove that they are logged in as admin. The tokens are signed by the
server's key, so the server is able to verify that the token is
legitimate. The tokens are designed to be compact, URL-safe and usable
especially in web browser single sign-on (SSO) context. JWT claims can
be typically used to pass identity of authenticated users between an
identity provider and a service provider, or any other type of claims
as required by business processes.[1][2] The tokens can also be
authenticated and encrypted.[3][4]
Set a SESSION var on the server when the client first loads your index.html (or backbone.js etc.)
Check this var on the server-side on every API call.
P.S. this is not a "security" solution!!! This is just to ease the load on your server so people don't abuse it or "hotlink" your API from other websites and apps.
Excuse me #MarkAmery and Eugene, but that is incorrect.
Your js+html (client) app running in the browser CAN be set up to exclude unauthorized direct calls to the API as follows:
First step: Set up the API to require authentication. The client must first authenticate itself via the server (or some other security server) for example asking the human user to provide the correct password.
Before authentication the calls to the API are not accepted.
During authentication a "token" is returned.
After authentication only API calls with the authentication "token" will be accepted.
Of course at this stage only authorized users who have the password can access the API, although if they are programmers debugging the app, they can access it directly for testing purposes.
Second step: Now set up an extra security API, that is to be called within a short limit of time after the client js+html app was initially requested from the server. This "callback" will tell the server that the client was downloaded successfully. Restrict your REST API calls to work only if the client was requested recently and successfully.
Now in order to use your API they must first download the client and actually run it in a browser. Only after successfully receiving the callback, and then user entry within a short frame of time, will the API accept calls.
So you do not have to worry that this may be an unauthorized user without credentials.
(The title of the question, 'How do I secure REST API calls', and from most of what you say, that is your major concern, and not the literal question of HOW your API is called, but rather BY WHOM, correct?)
Here's what I do:
Secure the API with an HTTP Header with calls such as X-APITOKEN:
Use session variables in PHP. Have a login system in place and save the user token in session variables.
Call JS code with Ajax to PHP and use the session variable with curl to call the API. That way, if the session variable is not set, it won't call and the PHP code contains the Access Token to the API.

Resources