40 comments

[ 2.4 ms ] story [ 20.4 ms ] thread
Heya, author here. If you have any questions, I'm happy to answer them.
I didn't know there was a "problem" with Flask authentication, but otherwise I'm looking forward to your work at Stormpath!
Flask's "problem" with authentication is that it refuses to deal with the broader Identity problem that plagues all networked systems. Matt did some great work integrating some of the pre-existing pieces (including one by another Matt) into a one size fits many solution: https://pythonhosted.org/Flask-Social/

But regardless of language / platform / framework, you still have to contend with the fact that OAuth and OpenID exist, and SAML is somewhere in there too, all sitting on top of legacy systems speaking LDAP and Kerberos negotiated with SASL along with some other oddball one-offs thrown in for good measure. BrowserID looks cool too. And what about two-factor?

So enter StormPath as yet another vendor to help solve this problem. It isn't a problem with Flask but if you're entering this market to solve the problem once and for all, it's very nice to see you paying attention to Flask.

Great work! Mind doing a compare / contrast with flask-security? (First comes to mind is that flask-security is a mix-match of a bunch of libraries)

https://pythonhosted.org/Flask-Security/

Sure -- Flask-Security is really excellent. I should have included it in the first part of this series.

Essentially, Flask-Security is doing the same thing as Flask-Stormpath, but is a lot more flexible -- it allows you to store users however you want with Postgres, Mongo, or whatever backend database you like. It also comes with some good examples (of how to create a users table for Postgres, etc.).

The benefit to Flask-Stormpath is a few things:

- You have a pre-defined user model that is really flexible (you can do email or username login / auth).

- You get greater security for authentication stuff (we use a really secure digest authentication method which prevents various attacks: MITM stuff, replay attacks, timing attacks, etc.).

- We also provide a flexible (and scalable) key-value store for all your user data (up to 10mb of data, per user account, completely free), so you can do cool stuff like this:

>>> my_user.custom_data['blah'] = { 'something': { 'more_stuff': 999.999, 'woot': 'hiya!', }, } >>> my_user.save()

All your user information (and user data), is hosted, backed up, encrypted, and provided via a fast, REST API.

This means that you can do cool stuff like:

- Access your user data from many parts of your stack (without sharing databases, or doing other hacks). This is really great if you're building a service-oriented application.

- Scale your userbase up from a few users to millions, no issues whatsoever.

And lastly, Stormpath also provides a really complete permissions model:

- You can encapsulate users in unique containers (directories), then map those directories to applications to make them 'active'.

- You get out of the box email verification and password reset stuff.

- You can require passwords to have various levels of complexity (length, types of characters, etc.).

- You can put users into groups (many-to-many), which scales particularly well on our backend -- a great way to build complicated authorization hierarchies.

Hopefully that helps answer your questions.

SUMMARY: Flask-Security is probably the very best possible, purely open source, and flexible, application that exists. Flask-Stormpath is built on top of the Stormpath API, so as a benefit, can do a lot of stuff that isn't possible for Flask-Security to do.

Would you mind comparing Stormpath with Firebase? Just the authentication and permission aspects, obviously.
I'm actually not terribly familiar with Firebase's user account stuff, sorry :( I'll look into it and write a follow up post at some point in the near future, though.
That'd be great. Thanks - I'll keep an eye out.
How do people have "scaling" problems with authentication? I have never heard of the source of a scaling problem be related to user accounts.
healthcare.gov is the only example that comes to mind.
Maybe he meant authorization and entitlements, which can easily run into scaling problems. The articles seem to conflate 'authorization' with 'authentication' for sake of simplicity.
No one in the industry can really agree on what AAA means once humans get involved. Ping added a fourth A for Account Management in an Attempt to Address the Ambiguity: https://www.pingidentity.com/resource-center/authentication-...

But trust and authority are deeper concepts than just usernames and passwords for the latest web app. Managing a sprawling system with multiple levels of access and demonstrating proof of security? The computers running the services and protocol translations aren't the parts that have trouble scaling anymore. (Hint: The L in LDAP. Compared to what?)

I have a friend that is emphatic about the benefits of what he terms 'realm-role' security[1], which I do prefer over some of the more byzantine approaches I've dealt with.

The levels of complexity stack up on the user side too, especially if you try to accommodate wandering contexts in multitenancy scenarios. His model doesn't try to address those requirements, which may be for the best.

[1] http://www.bivio.biz/bp/Realm_Role_Task/Diagram

Good question! There are a lot of issues (that I've experienced personally):

- Hashing passwords is CPU intensive if you're doing computationally expensive stuff (bcrypt, scrypt).

- If your site has user accounts, it's likely that every single page on your site requires some sort of user data: maybe files, videos, links, custom information, whatever. This means that for most people, every site request generates cache hits / database queries which can end up slowing things down substantially if you have a non-trivial amount of users.

There are also other issues out there as well, e.g: you're building a service oriented application, so you have a lot of internal services (myapp-www, myapp-billing, myapp-logs), and you need to share your user data between them securely -- how do you do that? Share your user database with all applications? Build your own internal user API service?

Hope that helps!

Look, I'm not trying to be intentionally confrontational - I actually find your product interesting. However, I'm just not understanding the angle you're going for here.

> Hashing passwords is CPU intensive if you're doing computationally expensive stuff (bcrypt, scrypt).

If you are continually logging-in so many accounts that hashing the supplied password is becoming a performance problem, you are either doing something terribly wrong, or you are so big that no SaaS could possibly support you anyway (FB?, Google?).

> If your site has user accounts, it's likely that every single page on your site requires some sort of user data

This, in fact, IS a scaling problem, but I don't see how it's related to authentication. It's a content/caching problem. And even if the problem here was related to auth - are you suggesting that whichever DB/IO operation is causing it can be made faster by a HTTP request going out of the datacenter? Not really sure that's how I'd fix it...

Ah, this is also a great question.

So, regarding the hashing stuff: password hashing is supposed to be slow, which is why bcrypt / scrypt are so popular.

A lot of people (probably not most HN readers) sometimes don't realize that this can actually cause performance implications on busy servers. Even if you're running a small business on a reasonably sized EC2 instance, handling the password hashing on an already busy server can definitely cause problems if you're serving several requests per second (or more). It's not a big issue, but certainly a real one that many people don't realize they have. (Interestingly, if you use NewRelic and do Bcrypt stuff -- check it out!).

In regards to user data -- you're completely correct. It's not an authentication problem.

I wrote about that quite a bit as I think it's important as user data is also sensitive information. Just like you wouldn't want to leak user password hashes, you also wouldn't want to leak user data.

At stormpath, we provide the data service because we think it's critically important to have your user data secured in the same fashion as your user authentication information -- and as a side effect -- it helps users scale this.

If you're on EC2, you'll likely get the same latency you'd have writing to a Cassandra database locally (with very small overhead) from the Stormpath service. Furthermore, our clients implement really smart caching rules, and can do interesting stuff like transparently handle object caching to a memcached or redis cluster, smartly handle data synchronization, etc.).

Hope that helps!

Also: I really do appreciate these comments, it's an incredibly interesting topic, and it's really useful to hear what other people think! Thank you :D

You've hit the nail on the head here, comparing "slow" DB/IO operations to a "faster?!" HTTP request. I don't even..

"You'll likely get the same latency you'd have writing to a Cassandra database locally". Nope, no I won't. Not even close.

I understand that the OP is working on their own solution called "Flask-Stormpath" but some of the arguments against Flask Authentication does not make sense to me at least and I have been dabbling in Flask for a while.

First, flask was designed with a purpose. The creator makes it very clear "The “micro” in microframework means Flask aims to keep the core simple but extensible. Flask won’t make many decisions for you". So now that we have that out of the way, I will point some specific things from this post that do not make sense to me. May be I didn't get the point.

"Set up a SQLite3 / MySQL / PostgreSQL database server."

What do you mean here ? Should we not setup a database server ? Flask does not force you to use any specific database. In fact, personally I prefer that I can use sqlalchemy etc. without worrying about being tied to a specific ORM. That's the point of flask for me.

"Write a User model (and define a users table)."

Sure. Flask wants you create your own user table. But why is that a big deal ? I mean yes most user models have username/email,pwd_hash etc. I would rather create my own model depending on my application need vs taking a pre-defined model. This is not at all difficult and again, the whole idea is that you want that flexibility and hence using flask.

"Build your own login view code to create new user accounts, and store them in the database."

Again, I can create custom apps based on the specific requirements if I have this flexibility. But ok, I see your point. Stuff like this can get overwhelming. But then again, flask gives me so many tools that I am not worried. Want to do notifications/subscriptions ? boom, plug in Signals. stuff like that.

"Implement your own crypto, usually by importing from the werkzeug library and hashing user passwords yourself."

Wait,what ? Who says that flask wants you to implement your own crypto ? You can directly use py-bcrypt or others. It is as easy as below. There is no implementation here.

    bcrypt.hashpw(password,bcrypt.gensalt())
"Hashing user passwords when they attempt to login, then comparing these hashes to the database."

What's wrong with this again ?

"Storing custom user data either in the same database table as your accounts, or relating it via a foreign key."

Now it seems like you are justifying Flask-Stormpath more than the fact that we should not be doing these ?

"Storing user data in cookies and sessions directly to handle logged-in state."

Ok, I agree here. Flask does make it a little harder dealing with sessions since the default is cookies for everything. But again, because flask does not want to enforce any particular datastore, it gets tricky.

Then, you came up with these conclusions:

"Almost nobody hashes passwords correctly."

Is this a little far fetched conclusion ? I would think so. And even if people don't hash password correctly, it is not flask authentication's fault. It is the developer's fault.

"Almost nobody structures their user database to allow for scaling."

What do you mean by "scaling" ? Do you mean updating user models, adding millions of users ? What does scaling have to do with authentication ?

Overall, I realize that you are presenting arguments for Flask-Stormpath and as a flask dev, I will definitely take a look at it. But most of your arguments for Stormpath are not the reasons why flask has a bad authentication if there is such thing.

> First, flask was designed with a purpose. The creator makes it very clear "The “micro” in microframework means Flask aims to keep the core simple but extensible. Flask won’t make many decisions for you".

Yeah, well, it turns out that a lot of Flask users aren't looking for a "microframework" at all. They want something pluggable where they can build their own "full stack" out of different parts. Why else is there a huge ecosystem of Flask extensions for everything but the kitchen sink?

That's a wrong conclusion to draw from the term "microframework." Unlike Django which defines in no uncertain terms what you get from it and what you can do with it, in Flask it's all up to you.

Yes, for some projects I want admin panels built for me; sometimes I don't. Sometimes my front end is SPA and all I need is a REST middleware talking to a database. If the database is supported through SQLAlchemy, even better -- there's a framework for that.

Some people will like Flask's approach and others won't; my only suggestion is to pick the right tool for the job and run with that. For my projects it's Flask because it's easy to reason about and most people can pick Flask up in a matter of days rather than weeks or months with monolithic frameworks.

Author here. This is a really insightful comment, and I think there are a few things I should have mentioned in the two articles to help explain why I feel this is needed a bit more.

I've been working with Flask for a long time now, and like you, I really appreciate how flexible and free it is, compared to heavier frameworks that force a lot of stuff on you.

I'm of the opinion, however, that user data, particularly, should be handled for me automatically. My reasoning is this:

- It's really scary to be responsible for user data and security -- it's very hard to do properly. For a lot of HN readers, bcrypting stuff is an afterthought, but for many developers, this is challenging and confusing.

- The way you setup your user database / relationships matters, a lot. It has a huge performance affect on every other page of your site / app, and many people don't realize this when they're developing stuff.

I've always felt like authentication is one of those things that should be completely black-boxed, to give developers the following:

- Faith in their security, without understanding the underlying representations of data.

- Transparent user scaling. This one is critical, in my opinion, because many people don't realize how quickly user data becomes a problem since it relates to almost everything else.

So, to summarize, while I do love Flask's flexibility, etc., I've always felt like having that flexibility applied to user stuff, in particular, is a bad choice, as it's incredibly easy to mess up, and the stakes are very high.

> I've always felt like authentication is one of those things that should be completely black-boxed, to give developers the following: > - Faith in their security, without understanding the underlying representations of data.

Isn't this contradictory - how can a developer have faith in a black-box if they can't see for themselves what it's doing? For security, in particular, this approach seems troublesome.

I'll be honest, I didn't read to the end of the second of the 2 articles, as the first persuaded me it is a bad solution: you are passing ownership of your user accounts to another firm. This means you are relying on them for your most trusted data, not to mention you have to leave the data centre to log somebody in.

Although I don't work in Flask daily, guess I'm stuck with Flask-Login for weekend projects.

Yeah, user accounts and authentication doesn't strike me as something that makes sense in the cloud.
That's completely reasonable.

I would, however, like to point you to the Terms of Service stormpath has: http://www.stormpath.com/terms_of_service

You own all your data, completely. Us (as employees) can't even access it! Furthermore, we use strong encryption and all security best practices to keep things locked away.

I'd argue that if you're safe enough with pushing your user data into an RDS instance, you're already giving out this part of your application.

You're comparing a tiny startup to AWS. For me, the bigger issue isn't security, it's not knowing if you guys will still be around in a couple months (no offense).

Between the chances of getting acquired or running out of funding and shutting down, startups aren't the best place to put the most essential part of your application. Stormpath is gone = my app is gone.

This is a great point I wasn't even considering.

You're completely right -- there's definitely inherent risk in relying on a third party (particularly a new one).

Just some background on Stormpath: we've been around since 2012, have funding, a big team, and are growing pretty fast. Also: we make it as painless as possible to migrate out of our platform (I can answer specific questions if anyone is interested).

When I write an app, I never worry that one day I'll wake up to an email from my database saying "I'm done storing your data, you'll have to export it to another database. Look, I made it really easy to migrate."

It's a nice product, but it would work better as an open source service I could host on my own servers and databases.

I love flask, I built http://www.gauthify.com 's API and http://Uphound.com using it. I think its great for small and large apps. With that said, I do think that at this point you might consider using something like Django instead.
The GAuthify home page looks awesome, and it's a great concept.

I'm curious about your comment that Flask is 'great for small and large apps' and your advice 'at this point you might consider... Django'.

From my limited experience of trying to build things with both, my impression is that Django has a steeper learning curve because of the project/app distinction, and urls.py but that, after some time, the additional structure this imposes makes it less likely that my code becomes a mess.

With Flask, it was super-fast to get started, and to add functionality incrementally, but at some point I realised my code was all in one file, which didn't seem right.

If, as you say, Flask is suitable for large projects like GAuthify, how do you structure your code so as to avoid the problem I faced?

Under what circumstances would you use Django for a project instead of Flask?

Thanks.

Yeah exactly, Django is really intended for the full range developer. They make a lot of the design (software) decisions for you, which in turn causes you to often end up in a much more manageable project (sometimes this backfires). Getting into a Django frame of mind is a bit more difficult since you have constraints but once you get it down, its generally straight forward. The other thing about Django is the packaging ecosystem. Things like advanced user perm/management, etc are baked in and very likely available in their myriad of packages (djangopackages.com). I would definitely recommend the beginner to start with django, mess it up a couple times and learn what ideal structures are like.

Flask on the other hand is extremely easy for the couple view project but requires someone quite competent in python to manage larger projects in it. You'll eventually have to create internal rules for your structure and code to keep things clean (MVC, etc) but the flexibility you'll have with it is amazing. The creator of Flask, Armin Ronacher, and it's devs are amazing at python and the languages idioms. You'll learn a lot going through the code and using its phenomenal design to create your own solutions. For example you won't be using flask packages with their own models/migrations, you'll be using pypi packages and design your models around your needs. Unless your project is really small, if you have everything in one file you're doing it wrong.

I guess the shorthand rules on flask vs django is: - Very simple: use flask - Novice on large api: use django - Good at python large api: use flask - Med/Large web project: use django - Medium web project, good at python: use flask - Good at python, large api: use flask

Check out https://github.com/imwilsonxu/fbone and https://github.com/mitsuhiko/flask/wiki/Large-app-how-to for some advise. Let me know if you have any specific questions.

Thanks for the advice and those links.

The example's use of Blueprints for the users module is really clear. Previously I was confused by the documentation on Blueprints, and I simultaneously didn't 'get' what they were for, whilst wondering why there wasn't an obvious way to break down a project into smaller pieces of functionality.

I think I'll follow your advice and use Django for now, just because it will be easier for me to find and use existing packages (e.g. django-allauth was a little easier to get working than flask-social).

you won't be using flask packages with their own models/migrations, you'll be using pypi packages and design your models around your needs

Are you talking about the distinction between, e.g. flask-social (a flask package) and python-social-auth (a python package, which requires me to define my own models)?

I don't even.. everything about this. Just no. Nope.
I use Django heavily but I like Flask's lightweight approach. So when the opportunity came to use Flask for a small project I did. At some point during the project it became a requirement to login. Sadly at that point I ended up writing more code manage user registration and authentication than the rest of the app. I think an opinionated Flask Authentication app (uses SqlAlchemy, WTForms, Jinja) would really help when bootstrapping small sites.
Great work, but you shouldn't say your solving the Flask auth problem when there isn't one. Flask-Login already solved the Flask auth problem and sticks to Flask's micro philosophy making it super simple and readable in one sitting.

You're providing a library with more features, but implying Flask has an auth problem is misleading.

Alternate title: "how to make flask handle users like django for people who cant decide what size framework they want"
> If you want to securely create a new user account, you POST to Stormpath’s API.

And I must trust you handle it properly. If I understood correctly, Stormpath saves the password for me for my users? If so, no. If I were to do that, I would have enable oauth and openid (which is a pain in the ass to find a library that actually passes security audit today!) or I'd just switch to Persona myself.

To solve real authentication issue, we need a layer that works nice. Pyramid has a nice authentication layer, though I find that layer poorly documented or just confusing to work with (I have conquered that hurtle but to be honest, it was hard!).

There is a real reason why I prefer the Django style. It built a basic authentication layer for me (username password default). The downside is ORM and user are tightly coupled with Django. There is a tradeoff, obviously.

But if there were a single API call which I could use to map to any openID, oauth, that'd be really great. Does stormpath do it? That's what I need as a library. Why can't we make oauth, openid like network protocol having layered protocol design? It's still quite a mess to me that we don't have a standard reference implementation for major languages well enough to be trusted (both consumer and provider). Last year for a project I almost had to implement my own oauth provider implementation because other existing projects are either incomplete or dead.

am I understanding this correctly that Flask-stormpath (and stormpath in this use case) is meant to provide Flask-Security like interface but hosted?