Skip to main content

Flask-SSPI

Flask-SSPI is an extension to Flask that allows you to trivially add NTLM based authentication to your website. It depends on both Flask and sspi. You can install the requirements from PyPI with pip or conda, or download them by hand.

The official copy of this documentation is available at Read the Docs.

Installation

Install the extension with one of the following commands:

pip install Flask-SSPI

or using conda:

conda install -c conda-forge flask-sspi

Limitations

  • Based on win32 so only works on Windows servers.
  • Tested with Chrome and Edge browsers.
  • Only NTLM authentication has been implemented, 'Negotiate' (Kerberos) has not been implemented.

How to Use

First Form (preferred)

You can decorate any view functions you wish to require authentication with the @authenticate decorator. To get the current user you can use g.current_user:

from flask_sspi import authenticate
from flask import g

@app.route("/protected/<path:path>")
@authenticate
def protected_view(path):
    print(g.current_user)
    ...

Second Form

You can decorate any view functions you wish to require authentication with @requires_authentication. With this keyword, you need to change them to accept the authenticated user principal as their first argument:

from flask_sspi import requires_authentication

@app.route("/protected/<path:path>")
@requires_authentication
def protected_view(user, path):
    ...

Flask-SSPI assumes that the service will be running using the hostname of the host on which the application is run. If this is not the case, you can override it by initializing the module:

from flask_sspi import init_sspi

init_sspi(app, hostname='example.com', package='NTLM')

NOTE: init_sspi is optional. If used, current_user will be defined within the context of Jinja templates. You can then use:

<h1>Hello {{ current_user }}</h1>

How it works

When a protected view is accessed by a client, it will check to see if the request includes authentication credentials in an Authorization header. If there are no such credentials, the application will respond immediately with a 401 Unauthorized response which includes a WWW-Authenticate header field with a value of NTLM indicating to the client that they are currently unauthorized, but that they can authenticate using Negotiate authentication.

If credentials are presented in the Authorization header, the credentials will be validated, the principal of the authenticating user will be extracted, and the protected view will be called with the extracted principal passed in as the first argument.

Once the protected view returns, a WWW-Authenticate header will be added to the response which can then be used by the client to authenticate the server. This is known as mutual authentication.

SSPI also has the ability to serve the value Negotiate from the WWW-Authenticate header. This has not been implemented but could be in the future with the help of the community.

Full Example

To see a simple example, you can download the code from github. It is in the example directory.

Decorators that can be used

Decorator Description
@authenticate The user must have been identified.
Impersonate Context class to impersonate the connecting user: The user's credentials will be used to execute the route function. Use this to access a database under the user's name per example. Important: I could not get this to work with an external database as it requires a trusted connection between the web server and the SQL database (which I don't have). It should work with a database located on the same computer.
@requires_authentication Same as login_required but the user parameter needs to be specified in the arguments of the route function. user will contain the name of the logged user. Kept for backward compatibility.

For all flask_sspi decorators, a g.current_user entry is created and accessible within the route function. Within HTML templates the variable current_user is also defined if init_sspi is used.

Using before_request function for Blueprints

If you want to restrict access to a whole Blueprint, better to do it with the before_request function. Here is an example:

@blueprint.before_request
@authenticate
def before_request():
    pass

Offsite debugging

You may want to test your flask application offsite in a non-domain environment. To allow testing without error from flask_sspi you can issue import flask_sspi_fake before any reference to flask_sspi. flask_sspi_fake will use stubs instead of the real functions and allow the site to be tested under the credentials of the currently logged user.

Changes

0.1

  • Initial implementation

0.2

  • Added the authenticate decorator and the Impersonate context.

API References

The full API reference:

See the API documentation.


Release files for Flask-SSPI 0.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for Flask-SSPI 0.3
File Size Uploaded
flask_sspi-0.3.tar.gz 9.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for Flask-SSPI 0.3
File Interpreter ABI Platform
flask_sspi-0.3-py3-none-any.whl Python 3 none any Details

Total release size:20.8 kB

Release files / flask_sspi-0.3.tar.gz

Download URL flask_sspi-0.3.tar.gz
Size 9.2 kB
Tags Source
SHA-256 checksum
How to use checksums
6d43c6ec2384846fbd994755237f420ab499ed912e2272fecbd5f875c7789965
BLAKE2b-256 checksum
How to use checksums
610a69c4ba79a4abd0dd3d9b1822d66f3fb921c2d37ac9efbcd54fb861a8a649
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.5

Release files / flask_sspi-0.3-py3-none-any.whl

Download URL flask_sspi-0.3-py3-none-any.whl
Size 11.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
94a96fd6237ae52d9c87b49d5be1fd762f823b9fd53db657c92c9b8808153953
BLAKE2b-256 checksum
How to use checksums
d94ca874212528089965a1cef96d115449e573e419142a3edbf8cca6eafd7b54
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.5

Release history Release notifications | RSS feed

This release

0.3 This release

2 release files

0.2

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

0.0.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page