Notes

Refreshing Tokens

One of the keys to proper security with auth tokens is to make sure that they only last a finite amont of time. This makes sure that if the token is stolen, it cannot be used in perpetuity to gain complete access to the user. However, calls to the database to validate a user on every http request would dramatically slow down an application.

To mitigate both situations, the concept of token refreshing has been introduced. The idea is that the user is re-checked periodically, but not on every request. After some fixed amount of time, the database is re-checked to make sure that a user is still allowed access.

At that point in time, a new token is issued with the same claims as the first except its refresh lifespan is not extened. This is so that a token cannot be refreshed in perpetuity.

Once a token’s access lifespan and refresh lifespan are both expired, the user must log in again.

Rate Limiting

There is not any sort of rate-limiting protection offered by flask-praetorian. Thus, if your app does not implment such a thing, it could be vulnerable to brute force attacks. It’s advisable that you implement some sort of system for limiting incorrect username/password attempts.

Error Handling

By default, flask-praetorian will add an error handler to Flask for PraetorianErrors. This error handler produces nicely formatted json responses with status codes that reflect the failures. The flask-praetorian package’s custom exception type PraetorianError derives from the FlaskBuzz base exception type from the flask-buzz exceptions package. The flask-buzz package provides convenience methods for error handlers.

The error handling may be disabled by adding a configuration setting for DISABLE_PRAETORIAN_ERROR_HANDLER. You may wish to do this if you want to customize your error handling even further.

For example, you may wish to have the error handler log messages about failures prior to returning an error response. In this case, you can still take advantage of flask-buzz’s features to do so:

app.register_error_handler(
    PraetorianError,
    PraetorianError.build_error_handler(lambda e: logger.error(e.message)),
)

Flask-Restplus compatibility

Flask-Restplus’s error handler is not compatible with the normal Flask error handler. What’s more, prior to Flask-Restplus 0.11.0, Flask-Restplus’s error handler did not automatically handle derived exception classes, so you would need to handle each and every PraetorianError type in your handler.

The flask-buzz exceptions package provides a helper method for registering error handlers with flask-restplus:

PraetorianError.register_error_handler_with_flask_restplus(api)

Like the normal Flask error handler, additional tasks may be passed to this method to be executed on the error prior to returning the response

Configuration Settings

Requirements for the user_class

The user_class argument supplied during initialization represents the class that should be used to check for authorization for decorated routes. The class itself may be implemented in any way that you see fit. It must, however, satisfy the following requirements:

  • Provide a lookup class method that:
    • should take a single argument of the name of the user
    • should return an instance of the user_class or None
  • Provide an identify class method
    • should take a single argument of the unique id of the user
    • should return an instance of the user_class or None
  • Provide a rolenames instance attribute
    • only applies if roles are not disabled. See PRAETORIAN_ROLES_DISABLED setting
    • should return a list of string roles assigned to the user
  • Provide a password instance attribute
    • should return the hashed password assigned to the user
  • Provide an identity instance attribute
    • should return the unique id of the user

Although the example given in the documentation uses a SQLAlchemy model for the userclass, this is not a requirement.