FlaskSimpleAuth

Flask Extension and Wrapper

This extension helps manage:

  • authentication

  • authorization

  • parameters

  • and more…

This code is public domain.

Exceptions

ErrorResponse

Exception class to carry fields for an error Response.

ConfigError

FSA User Configuration Error.

Classes

Hooks

This class holds all hook types used by FlaskSimpleAuth.

path

Type to distinguish str path parameters.

string

Type to distinguish str string parameters.

JsonData

Magic JSON parameter type.

Session

Session parameter type.

Globals

Globals parameter type.

Environ

Environ parameter type.

CurrentUser

CurrentUser parameter type.

CurrentApp

CurrentApp parameter type.

Cookie

Application Cookie parameter type.

Header

Request Header parameter type.

Reference

Convenient object wrapper class.

Flask

Flask class wrapper.

Directives

Documentation for configuration directives.

FlaskSimpleAuth

Flask extension for authentication, authorization and parameters.

Functions

err(*args, **kwargs)

Shorcut function to trigger an error response.

jsonify(→ flask.Response)

Jsonify something, including generators, dataclasses and pydantic stuff.

Module Contents

class FlaskSimpleAuth.Hooks

This class holds all hook types used by FlaskSimpleAuth.

ErrorResponseFun

Generate an error response for message and status.

Parameters:
  • description – description string of the error.

  • status – HTTP status code.

  • headers – dict of additional headers.

  • content_type – HTTP content type.

Must return a Response.

The function mimics flask.Response(“message”, status, headers, content_type).

GetUserPassFun

Get password from user login, None if unknown.

Parameters:

login – user name to retrieve password for.

Returns the string, of None if no password or user.

GroupCheckFun

Tell whether a user belongs to some group.

Parameters:

login – user name.

Returns whether the user belongs to some group by calling the appropriate callback.

UserInGroupFun

Is user login in group (str or int): yes, no, unknown.

Parameters:
  • login – user name to check for group membership.

  • group – group name or number to check for membership.

Returns whether the user belongs to the group. This is a fallback for the previous per-group method.

ObjectPermsFun

Check object access in domain, for parameter, in mode.

Parameters:
  • login – user name.

  • oid – object identifier, must a key.

  • mode – optional operation the user wants to perform on the object.

Returns whether permission is granted.

PasswordCheckFun

Low level check login/password validity.

Parameters:
  • login – user name.

  • password – the password as provided.

Returns whether password is valid for user.

PasswordQualityFun

Is this password quality suitable?

Parameters:

password – the submitted password.

Returns whether the password is acceptable.

CastFun

Cast parameter value to some object.

Parameters:

data – initial data, usually a string.

Returns the converted object.

SpecialParameterFun

Generate a “special” parameter, with the parameter name.

Parameters:

name – parameter name (usually not needed).

Returns an object which will be the parameter value.

HeaderFun

Add a header to the current response.

Parameters:
  • response – response to consider.

  • header – name of header.

Returns the header value, or None.

BeforeRequestFun

Before request hook, with request provided.

Parameters:

request – current request.

Returns a response (to shortcut), or None to continue.

BeforeExecFun

After authentication and right before execution.

Parameters:
  • request – current request.

  • login – user name of authenticated user.

  • auth – authentication scheme used.

AfterRequestFun

After request hook.

AuthenticationFun

Authentication hook.

Parameters:
  • app – current application.

  • request – current request.

Returns the authenticated user name, or None.

exception FlaskSimpleAuth.ErrorResponse

Bases: BaseException

Exception class to carry fields for an error Response.

Use this exception from hooks to trigger an error response.

FlaskSimpleAuth.err(*args, **kwargs)

Shorcut function to trigger an error response.

It can be used inside an expression, eg: _ = res or err("no data", 404)

exception FlaskSimpleAuth.ConfigError

Bases: BaseException

FSA User Configuration Error.

This error is raised on errors detected while initializing the application.

class FlaskSimpleAuth.path

Bases: str

Type to distinguish str path parameters.

Use this type as hint for a route parameter to trigger a Flask route path parameter. A path may contain / characters.

class FlaskSimpleAuth.string

Bases: str

Type to distinguish str string parameters.

Use this type as hint for a route parameter to trigger a Flask route string parameter. A string may not contain / characters.

class FlaskSimpleAuth.JsonData

Magic JSON parameter type.

This triggers interpretting a parameter as JSON when used as a parameter type on a route.

class FlaskSimpleAuth.Session

Session parameter type.

This provides the session object when used as a parameter type on a route.

class FlaskSimpleAuth.Globals

Globals parameter type.

This provides the g (globals) object when used as a parameter type on a route.

class FlaskSimpleAuth.Environ

Environ parameter type.

This provides the WSGI environ object when used as a parameter type on a route.

class FlaskSimpleAuth.CurrentUser

Bases: str

CurrentUser parameter type.

This provides the authenticated user (str) when used as a parameter type on a route.

class FlaskSimpleAuth.CurrentApp

CurrentApp parameter type.

This provides the current application object when used as a parameter type on a route.

class FlaskSimpleAuth.Cookie

Bases: str

Application Cookie parameter type.

This provides the cookie value (str) when used as a parameter type on a route. The name of the parameter is the cookie name.

class FlaskSimpleAuth.Header

Bases: str

Request Header parameter type.

This provides the header value (str) when used as a parameter type on a route. The name of the parameter is the header name (case insensitive, underscore for dash).

FlaskSimpleAuth.jsonify(a: Any) flask.Response

Jsonify something, including generators, dataclasses and pydantic stuff.

This is somehow an extension of Flask own jsonify.

NOTE on generators, the generator output is json-streamed instead of being treated as a string or bytes generator.

class FlaskSimpleAuth.Reference(*args, **kwargs)

Bases: ProxyPatternPool.Proxy

Convenient object wrapper class.

This is a very thin wrapper around ProxyPatternPool Proxy class.

class FlaskSimpleAuth.Flask(*args, debug: bool = False, **kwargs)

Bases: flask.Flask

Flask class wrapper.

The class behaves mostly as a Flask class, but supports extensions:

  • the route decorator manages authentication, authorization and parameters transparently.

  • per-methods shortcut decorators allow to handle root for a given method: get, post, put, patch, delete.

  • make_response slightly extends its parent to allow changing the default content type and handle None body.

  • several additional methods are provided: get_user_pass, user_in_group, group_check, check_password, hash_password, create_token, get_user, current_user, clear_caches, cast, object_perms, user_scope, password_quality, password_check, add_group, add_scope, add_headers, error_response, authentication

See FlaskSimpleAuth class documentation about these methods.

make_response(rv) flask.Response

Create a Response.

This method handles overriding the default Content-Type and accepts a None body.

class FlaskSimpleAuth.Directives

Documentation for configuration directives.

This class presents all configuration directives, their expected type and default value.

FSA_MODE: str = 'prod'

Execution mode.

  • prod: default terse mode.

  • dev: adds headers with the route, authentication and run time.

  • debug1 to debug4: increasing debug.

FSA_LOGGING_LEVEL: int

Module internal logging level.

Upgrade to logging.DEBUG for maximal verbosity.

FSA_SECURE: bool = True

Require TLS on non local connexions.

This should be True, unless an external appliance handles TLS decryption.

FSA_SERVER_ERROR: int = 500

Status code on FSA internal server errors.

This is for debugging help. Changing this allows to separate FSA errors from Flask errors or others.

FSA_NOT_FOUND_ERROR: int = 404

Status code on not found errors.

This is for debugging help. Changing this allows to separate FSA generated 404 from others.

FSA_LOCAL: str = 'thread'

Isolation requirement for internal per-request objects.

  • process: one process only

  • thread: threaded request handler

  • werkzeug: use werkzeug local

  • gevent: gevent request handler

  • eventlet: eventlet request handler

Depending on the WSGI server, requests may be managed by process, thread, greenlet… this setting must match the WGI context so that FSA can isolate requests properly.

FSA_HANDLE_ALL_ERRORS: bool = True

Whether to handle all 4xx and 5xx Flask-generated errors.

  • on True: override Flask error processing to use FlaskSimpleAuth response generation with FSA internal error handler (FSA_ERROR_RESPONSE).

  • on False: some errors may generate their own response in any format based on Flask default error response generator.

FSA_KEEP_USER_ERRORS: bool = False

Whether to hide user errors.

They may occur from any user-provided functions such as various hooks and route functions.

  • on False: intercept user errors and turned them into 5xx.

  • on True: refrain from handling user errors and let them pass to the outer WSGI infrastructure instead. User errors are intercepted anyway, traced and raised again.

FSA_ERROR_RESPONSE: str | Hooks = 'plain'

Common hook for generating a response on errors.

Same as error_response decorator.

  • plain: generate a simple text/plain response.

  • json: generate a simple application/json string.

  • json:msg: generate a JSON object with property msg.

  • callback: give full control to a callback which is passed the message, the status, headers and content type.

FSA_GET_USER_PASS: Hooks | None = None

Password hook for getting a user’s salted hashed password.

Same as get_user_pass decorator.

Provide a callback to retrieved the hashed password from the user login. Returning None will skip internal password checking.

FSA_AUTHENTICATION: dict[str, Hooks]

Authentication hook for adding authentication schemes.

Same as authentication decorator.

For each scheme name, associate a callback which will be given the app and request, and should return the authenticated user login (str). Returning None suggests a 401 for this scheme. The implementation may also raise an ErrorResponse.

FSA_GROUP_CHECK: dict[str, Hooks]

Authorization hook for checking whether a user is some groups.

Same as group_check decorator.

For each group name, associate a callback which given a login returns whether the user belongs to this group. The group name is also registered in passing.

FSA_USER_IN_GROUP: Hooks | None = None

Authorization hook for checking a user group.

Same as user_in_group decorator.

Provide a hook to check whether a user, identified by their login, belogs to a group.

FSA_OBJECT_PERMS: dict[str, Hooks]

Authorization hook for object permissions.

Same as authorization decorator.

For each kind of object (domain), associate a callback which is given the object id, the user login and the expected role, and returns whether the user has this role for this object id. Return None for 404.

FSA_CAST: dict[Any, Hooks]

Parameter hook for type conversion.

Cast function to call on the raw parameter (usually) string value, if it does not have the expected type. This does not apply to special and pydantic parameters.

See also cast function/decorator.

FSA_SPECIAL_PARAMETER: dict[Any, Hooks]

Parameter hook for special parameters.

The hook is called with the parameter name as an argument. It may access request or whatever to return some value.

See also special_parameter function/decorator.

FSA_BEFORE_REQUEST: list[Hooks] = []

Request hook executed before request.

These hooks are managed internally by FlaskSimpleAuth so that they are executed after its own (FSA) before request hooks, so as to minimize interactions between user hooks registered to Flask directly and its own hooks.

FSA_BEFORE_EXEC: list[Hooks] = []

Request hook executed after authentication.

FlaskSimpleAuth-specific hooks executed after authentication, so that for instance the current user is available.

The hook is executed after authentication and before the user function.

It may be used to commit and return a database connection used by the authentication phase.

See also before_exec function/decorator.

FSA_AFTER_REQUEST: list[Hooks] = []

Request hook executed after request.

These hooks are managed internally by FlaskSimpleAuth so that they are executed after its own before request hooks, so as to minimize interactions between user hooks registered to Flask directly and its own hooks.

FSA_ADD_HEADERS: dict[str, str | Callable[[], str]]

Response hook to add headers.

Key is the header name, value is the header value or a function generating the header value.

See also add_headers function.

FSA_AUTH: str | list[str] = []

List of enabled authentication schemes.

This directive is mandatory.

Note: the result of authentication is the user identification (eg login, name or email…) as a string, which is accessible from the application and using the CurrentUser special parameter type in route functions.

  • none: no authentication, implicit if FSA_AUTH is a scalar, required for OPEN routes.

  • httpd: inherit web-server authentication.

  • basic: HTTP Basic password authentication.

  • http-basic: same with Flask-HTTPAuth implementation.

  • digest: HTTP Digest password authentication with Flask-HTTPAuth.

  • http-digest: same as previous.

  • param: parameter password authentication.

  • password: try basic then param.

  • fake: fake authentication using a parameter, for local tests only.

  • token: token authentication (implicit if FSA_AUTH is a scalar).

  • http-token: same with Flask-HTTPAuth.

  • oauth: token authentication variant, where the token holds the list of permissions.

FSA_AUTH_DEFAULT: str | list[str] | None = None

Default authentications to use on a route.

These authentications must be enabled. Default is None, which means relying on schemes allowed by FSA_AUTH.

FSA_REALM: str = '<to be set as application name>'

Authentication realm, default is application name.

This realm is used for basic, digest and token authentications.

FSA_FAKE_LOGIN: str = 'LOGIN'

Parameter name for fake authentication.

This parameter string value is taken as the authenticated user name when fake auth is enabled. Only for local tests, please!

FSA_PARAM_USER: str = 'USER'

Parameter name for user for param authentication.

This parameter string value is the login name for param authentication.

FSA_PARAM_PASS: str = 'PASS'

Parameter name for password for param authentication.

This parameter string value is the password for param authentication.

FSA_TOKEN_TYPE: str | None = 'fsa'

Type of authentication token.

  • fsa: simple custom token

  • jwt: JSON web token standard

  • None: disable token authentication

FSA_TOKEN_ALGO: str = 'blake2s'

Token signature algorithm.

Default depends on token type.

  • blake2s: for fsa tokens. Other values can be taken from hashlib, see hashlib.algorithms_available.

  • HS256: for jwt tokens. Other values defined in the JWT standard.

FSA_TOKEN_CARRIER: str = 'bearer'

Token carrier, i.e. where to find the token.

  • bearer: in the Authorization header (default)

  • cookie: in a request cookie

  • header: in a custom header

  • param: in a request parameter

The FSA_TOKEN_NAME directives provides the additional name.

FSA_TOKEN_NAME: str = 'Bearer'

Token carrier name.

Authentication scheme, or cookie/header/parameter name. See defaults in full documentation.

FSA_TOKEN_DELAY: float = 60.0

Token validity delay in minutes.

FSA_TOKEN_GRACE: float = 0.0

Token grace time after expiration, in minutes.

FSA_TOKEN_LENGTH: int = 16

FSA token signature length.

Number of hash characters kept for signing an fsa token. Default is 16, meaning a 64-bit signature.

FSA_TOKEN_SECRET: str = '<to be overriden>'

Token verification secret.

Default is a randomly generated 256-bits string which only works for one process.

FSA_TOKEN_SIGN: str | None = None

Token signature secret.

Only for public-key JWT schemes. Default is FSA_TOKEN_SECRET.

FSA_TOKEN_RENEWAL: float = 0.0

Token cookie automatic renewal as a fraction of remaining life time.

FSA_TOKEN_ISSUER: str | None = None

Token issuer.

FSA_PASSWORD_SCHEME: str | list[str] | None = 'bcrypt'

Password hash provider and algorithm name, or list of passlib schemes, or password disactivation.

If the provider is not set, uses fsa for bcrypt, argon2, scrypt, plaintext, a85 and b64, otherwise passlib.

FSA_PASSWORD_OPTS: dict[str, Any] | None = None

Password hash algorithm options.

None triggers the defaults, which depend on the provider and scheme:

  • for fsa:bcrypt: {"rounds": 4, "prefix"=b"2b"}

  • for fsa:argon2: {"memory_cost": 1000, "time_cost": 1, "parallelism": 1}

  • for fsa:scrypt: {"saltlength": 16, "maxtime": 0.05}

  • for fsa:*: {}

  • for passlib:bcrypt: {"bcrypt__default_rounds": 4, "bcrypt__default_ident": "2y"}

With passlib, default for bcrypt is ident 2y (132-bit salt) with 4 rounds (2⁴ hash iterations). It is compatible with Apache. All _2*_ variants are really equivalent.

The recommend password rounds is _12_, which results in _x00 ms_ server cpu time. This is okay only if you do not use password authentication on many routes, but only to retrieve some token which would be much easier to check.

FSA_PASSWORD_LENGTH: int = 0

Password quality minimal length.

Default is 0, meaning no minimal length is required.

FSA_PASSWORD_RE: list[str] = []

Password quality regular expressions.

Passwords submitted to hash_password are checked against this list. Default is empty list, meaning no character constraints on passwords.

FSA_PASSWORD_QUALITY: Hooks | None = None

Password quality hook.

Arbitrary password quality check. Given the password string, returns whether the password is valid.

FSA_PASSWORD_CHECK: Hooks | None = None

Password check hook.

Alternate password check function. Given the login and clear password, returns whether the authentication is valid. This allows to take full control of password checking, eg for LDAP/AD authentication.

Consider adding a new authentication scheme, see FSA_AUTHENTICATION.

FSA_HTTP_AUTH_OPTS: dict[str, Any]

Flask-HTTPAuth initialization options.

FSA_AUTHZ_GROUPS: list[str] = []

Authorized groups declaration.

Declaring groups allows to detect group name typos at configuration time.

FSA_AUTHZ_SCOPES: list[str] = []

Authorized scopes declaration.

Declaring scopes allows to detect scope name typos at configuration time.

FSA_DEFAULT_CONTENT_TYPE: str | None = None

Set default content type for str or bytes responses.

Default (None) is to use Flask’s defaults.

FSA_JSON_STREAMING: bool = True

Whether to stream JSON output on generators.

Default (True) is to stream, which may interact badly with driver transactions depending on how the WSGI server works. Setting this to False ensures that JSON is returned as a string by FlaskSimpleAuth’s jsonify.

FSA_REJECT_UNEXPECTED_PARAM: bool = True

Whether to reject unexpected parameters.

FSA_CACHE: str | MutableMapping = 'ttl'

Cache type.

  • none: disactivate caching

  • dict: simple dictionary

  • ttl, lru, tlru, lfu, …: from CacheTools

  • memcached and redis: external shared caches

Default is ttl… because it is a good idea.

FSA_CACHE_SIZE: int = 262144

Cache maximum number of entries.

FSA_CACHE_OPTS: dict[str, Any]

Cache initialization options.

These options as passed when creating the cache instance.

FSA_CACHE_PREFIX: str | None = None

Cache common prefix.

This prefix is shared by all FSA internal cache entries, so that they may not collide with other cache entries when an external cache is shared by different part of an application.

FSA_401_REDIRECT: str | None = None

URL redirection target on 401.

URL of the web application login page.

FSA_URL_NAME: str = 'URL'

URL redirection parameter name.

The source URL is passed as this parameter to the 401 redirection target so that it can be redirected back after authentication.

FSA_CORS: bool = False

Whether to activate Flask-CORS.

This is needed to work around web browser security checks. This implementation is delegated to the Flask-CORS extension.

FSA_CORS_OPTS: dict[str, Any]

Flask-CORS initialization options.

See Flask-CORS documentation for details.

class FlaskSimpleAuth.FlaskSimpleAuth(app: flask.Flask, debug: bool = False, **config)

Flask extension for authentication, authorization and parameters.

Although this class can be used as a Flask extension, the prefered approach is to use the Flask class provided in this module, which overrides directly Flask internals so as to provide our declarative security layer, so that you may not shortcut the extension.

get_user_pass(gup: Hooks) Hooks

Set get_user_pass helper, can be used as a decorator.

user_in_group(uig: Hooks) Hooks

Set user_in_group helper, can be used as a decorator.

password_quality(pqc: Hooks) Hooks

Set password_quality hook.

password_check(pwc: Hooks) Hooks

Set password_check hook.

error_response(erh: Hooks) Hooks

Set error_response hook.

cast(t, cast: Hooks | None = None)

Add a cast function associated to a type.

This function is called for type conversion on parameters.

special_parameter(t, sp: Hooks | None = None)

Add a special parameter type.

These special parameters are managed by calling the hook with a the parameter name as an argument.

group_check(group: str | int, checker: Hooks | None = None)

Add a group helper for a given group.

object_perms(domain: str, checker: Hooks | None = None)

Add an object permission helper for a given domain.

authentication(auth: str, hook: Hooks | None = None)

Add new authentication hook.

add_group(*groups) None

Add some groups.

add_scope(*scopes) None

Add some scopes.

add_headers(**kwargs) None

Add some headers.

before_exec(hook: Hooks) None

Register an after auth/just before exec hook.

check_user_password(user, pwd) bool

Verify whether a user password is correct according to internals.

This allows to check the prior password for a change password route.

check_password(pwd, ref)

Verify whether a password is correct compared to a reference (eg salted hash).

This allows to check the prior password for a change password route.

hash_password(pwd, check=True)

Hash password according to the current password scheme.

Setting check to False disables automatic password quality checks.

get_user(required=True) str | None

Authenticate user or throw exception.

Tries all possible authentication schemes allowed on the route, and returns the authenticated user or throws an exception. The result is memoized.

current_user() str | None

Return current authenticated user, if any.

Returns None if no user has been authenticated.

user_scope(scope) bool

Is scope in the current user scopes.

clear_caches() None

Clear internal shared cache.

Probably a bad idea because:

  • of the performance impact

  • for a local cache in a multi-process setup, other processes are out

The best option is to wait for cache entries to expire with a TTL, or to use one of the specific _uncache methods.

password_uncache(user: str) bool

Remove user password entry from cache.

token_uncache(token: str, realm: str) bool

Remove token entry from cache.

user_token_uncache(user: str, realm: str) bool

Remove token associated to user/realm from cache.

group_uncache(user: str, group: str | int) bool

Remove group membership entry from cache.

object_perms_uncache(domain: str, user: str, oid, mode: str | None) bool

Remove permission entry from cache.

auth_uncache(user: str) int

Attempt at removing all user authn and authz cache entries.

add_url_rule(rule, endpoint=None, view_func=None, authorize='CLOSE', auth=None, realm=None, **options)

Route decorator helper method.

  • authz or authorize: authorization constraints.

  • authn or auth: authentication constraints.

  • realm: realm for this route, supercedes global settings.

get(rule, **options)

Shortcut for route with GET method.

post(rule, **options)

Shortcut for route with POST method.

put(rule, **options)

Shortcut for route with PUT method.

delete(rule, **options)

Shortcut for route with DELETE method.

patch(rule, **options)

Shortcut for route with PATCH method.

register_blueprint(blueprint, **options)

Register a blueprint.