Authentication

The Authentication class provides a means of authenticating users of the site. It is designed to work out-of-the-box with a simple User model, but can be heavily customized.

The auth system is also designed to work closely with the Admin Interface.

Getting started

In order to provide a method for users to authenticate with your site, instantiate an Auth backend for your project:

from flask import Flask

from flaskext.auth import Auth
from flaskext.db import Database

app = Flask(__name__)
db = Database(app)

# needed for authentication
auth = Auth(app, db)

Marking areas of the site as login required

If you want to mark specific areas of your site as requiring auth, you can decorate views using the Auth.login_required() decorator:

@app.route('/private/')
@auth.login_required
def private_timeline():
    user = auth.get_logged_in_user()

    # ... display the private timeline for the logged-in user

If the request comes from someone who has not logged-in with the site, they are redirected to the Auth.login() view, which allows the user to authenticate.

Retrieving the current user

Whenever in a request context, the currently logged-in user is available by calling Auth.get_logged_in_user(), which will return None if the requesting user is not logged in.

The auth system also registers a pre-request hook that stores the currently logged-in user in the special flask variable g.

Accessing the user in the templates

The auth system registers a template context processor which makes the logged-in user available in any template:

{% if user %}
  <p>Hello {{ user.username }}</p>
{% else %}
  <p>Please <a href="{{ url_for('auth.login') }}?next={{ request.path }}">log in</a></p>
{% endif %}

Using a custom “User” model

It is easy to use your own model for the User, though depending on the amount of changes it may be necessary to override methods in both the Auth and Admin classes.

Here’s a simple example of extending the auth system to use a custom user model:

app = Flask(__name__)
db = Database(app)

# create our custom user model
class User(db.Model):
    username = CharField()
    password = CharField()
    email = CharField()

    # ... our custom fields ...
    is_superuser = BooleanField()


# create a modeladmin for it
class UserAdmin(ModelAdmin):
    columns = ('username', 'email', 'is_superuser',)


# subclass Auth so we can return our custom classes
class CustomAuth(Auth):
    def get_user_model(self):
        return User

    def get_model_admin(self):
        return UserAdmin

# instantiate the auth
auth = CustomAuth(app, db)

Here’s how you might integrate the custom auth with the admin area of your site:

# subclass Admin to check for whether the user is a superuser
class CustomAdmin(Admin):
    def check_user_permission(self, user):
        return user.is_superuser

# instantiate the admin
admin = CustomAdmin(app, auth)

admin.register(User, UserAdmin)
admin.setup()

Components of the auth system

The Auth system is comprised of a single class which is responsible for coordinating incoming requests to your project with known users. It provides the following:

  • views for login and logout
  • model to store user data (or you can provide your own)
  • mechanism for identifying users across requests (uses session storage)

All of these pieces can be customized, but the default out-of-box implementation aims to provide a good starting place.

So, without further ado here’s a look at the auth class:

class Auth
__init__(app, db[, user_model=None[, prefix='/accounts']])
Parameters:
  • app – flask application to bind admin to
  • dbDatabase database wrapper for flask app
  • user_modelUser model to use
  • prefix – url to bind authentication views to, defaults to /accounts/
get_logged_in_user()
Return type:returns the currently logged-in User, or None if session is anonymous

Note

this method must be called while within a RequestContext

login_required(func)
Parameters:func – a view function to be marked as login-required
Return type:if the user is logged in, return the view as normal, otherwise returns a redirect to the login page

Note

this decorator should be applied closest to the original view function

@app.route('/private/')
@auth.login_required
def private():
    # this view is only accessible by logged-in users
    return render_template('private.html')
get_user_model()
Return type:Peewee model to use for persisting user data and authentication
get_model_admin([model_admin=None])
Parameters:model_admin – subclass of ModelAdmin to use as the base class
Return type:a subclass of ModelAdmin suitable for use with the User model

Note

the default implementation includes an override of the ModelAdmin.save_model() method to intelligently hash passwords:

class UserAdmin(model_admin):
    columns = ['username', 'email', 'active', 'admin']

    def save_model(self, instance, form, adding=False):
        orig_password = instance.password

        user = super(UserAdmin, self).save_model(instance, form, adding)

        if orig_password != form.password.data:
            user.set_password(form.password.data)
            user.save()

        return user
get_urls()
Return type:a tuple of 2-tuples mapping url to view function.

Note

the default implementation provides views for login and logout only

def get_urls(self):
    return (
        ('/logout/', self.logout),
        ('/login/', self.login),
    )
get_login_form()
Return type:a wtforms.Form subclass to use for retrieving any user info required for login
authenticate(username, password)

Given the username and password, retrieve the user with the matching credentials if they exist. No exceptions should be raised by this method.

Return type:User model if successful, otherwise False
login_user(user)

Mark the given user as “logged-in”. In the default implementation, this entails storing data in the Session to indicate the successful login.

Parameters:userUser instance
logout_user()

Mark the requesting user as logged-out