Developing Authhelpers 🛠️

Environment setup

Clone the repository, install dependencies. This repo prefers uv for dependency management.

git clone git@gitlab.com:ska-telescope/ska-aaa-authhelpers.git
cd ska-aaa-auth-helpers
uv sync --group dev --group docs --extra scripts

Install/update the .make submodule:

git submodule update --recursive --remote
git submodule update --init --recursive

Autoformat:

uv run make python-format

Lint/type check

Linting is Ruff, type checking with pyright

uv run make python-lint

Tip

This repository uses Ruff for linting and formatting, in place of the default tools pylint/black.

When running make commands you will see warnings like Makefile:18: warning: overriding recipe for target 'python-do-format'

These are expected and don’t indicate any problem in your code.

Test:

We use nox for testing with different FastAPI / Python versions, to run the full test suite as it will run on GitlabCI:

make python-test

If you just want to run the tests in your current environment, you can use Pytest directly.

uv run pytest

You can also run a specific Python and FastAPI combination when debugging a version-specific issue:

uv run nox -s "test-3.10(fastapi='0.135.3')"

Docs

Documentation (except for the README) is located in docs/src/ and can be built with…

uv run make docs-build html

…this will put output in docs/build/html

Where do I start?

See also

You may want to check out Components for more details on the public API of this library.

To understand and work on Authhelpers, start with security.Requires() This is a utility function that automatically creates a FastAPI Security() subclass that wraps a TokenScheme()instance as its callable. TokenScheme itself has a child-dependency on an HTTP Authorization header, which it uses to obtain the JWT access token, decode and verify it, and finally create and return an AuthContext object for the application to work with. This is the core functionality offered by this library.

We’re using joserfc to deal with all the JWT-decoding mechanics, which in turn uses cryptography for the nitty-gritty details of signature verification.

Other slightly magical or weird bits worth noting:

  • We’re relying on Starlette Context to set a per-request global context so we can access the auth context inside AuditLogFilter without explicitly passing it all the way into the logger.

  • watchdog() is a Starlette lifespan – a kind of context manager used to run events before the application starts.

  • test_helpers.monkeypatch_pubkeys() goes fishing through the garbage collector to find live objects carrying references to DEFAULT_PUBLIC_KEYS and replace them with TEST_PUBLIC_KEYS. This is kind of ugly, but it means the application code doesn’t have to change to accommodate tests.