Skip to main content

Imia

Imia (belarussian for "a name") is an authentication library for Starlette and FastAPI (python 3.8+).

PyPI GitHub Workflow Status GitHub Libraries.io dependency status for latest release PyPI - Downloads GitHub Release Date Lines of code

Production status

The library is considered in "beta" state thus may contain bugs or security issues, but I actively use it in production.

Installation

Install imia using PIP or poetry:

pip install imia
# or
poetry add imia

Features

  • Login/logout flows
  • Pluggable authenticators:
    • WWW-Basic
    • session
    • token
    • bearer token
    • any token (customizable)
    • API key
  • Database agnostic user storage
  • Authentication middleware
    • with fallback strategies:
      • redirect to an URL
      • raise an exception
      • do nothing
    • with optional URL protection
    • with option URL exclusion from protection
  • User Impersonation (stateless and stateful)
  • SQLAlchemy 1.4 (async mode) integration

TODO

  • remember me

A very quick start

If you are too lazy to read this doc, take a look into examples/ directory. There you will find several files demoing various parts of this library.

How it works?

Here are all moving parts:

  1. UserLike object, aka "user model" - is an arbitrary class that implements imia.UserLike protocol.
  2. a user provider - an adapter that loads user model (UserLike object) from the storage (a database).
  3. an authenticator - a class that loads user using the user provider from the request (eg. session)
  4. an authentication middleware that accepts an HTTP request and calls authenticators for a user model. The middleware always populates request.auth with UserToken.
  5. user token is a class that holds authentication state

When a HTTP request reaches your application, an imia.AuthenticationMiddleware will start handling it. The middleware iterates over configured authenticators and stops on the first one that returns non-None value. At this point the request is considered authenticated. If no authenticators return user model then the middleware will create anonymous user token. The user token available in request.auth property. Use user_token.is_authenticated token property to make sure that user is authenticated.

User authentication quick start

  1. Create a user model and implement methods defined by imia.UserLike protocol.
  2. Create an instance of imia.UserProvider that corresponds to your user storage. Feel free to create your own.
  3. Setup one or more authenticators and pass them to the middleware
  4. Add imia.AuthenticationMiddleware to your Starlette application

At this point you are done.

Here is a brief example that uses in-memory provider for demo purpose. For production environment you should use database backed providers like SQLAlchemyORMUserProvider or SQLAlchemyCoreUserProvider. Also, for simplicity reason we will not implement login/logout flow and will authenticate requests using API keys.

from dataclasses import dataclass, field

from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.requests import Request
from starlette.responses import JSONResponse
from starlette.routing import Route

from imia import APIKeyAuthenticator, AuthenticationMiddleware, InMemoryProvider


@dataclass
class User:
    """This is our user model. It may be an ORM model, or any python class, the library does not care of it,
    it only expects that the class has methods defined by the UserLike protocol."""

    id: str
    password: str = 'password'
    scopes: list[str] = field(default_factory=list)

    def get_display_name(self) -> str:
        return self.id.split('@')[0].title()

    def get_id(self) -> str:
        return self.id

    def get_hashed_password(self) -> str:
        return self.password

    def get_scopes(self) -> list:
        return self.scopes


async def whoami_view(request: Request) -> JSONResponse:
    return JSONResponse({
        'id': request.auth.user_id,
        'name': request.auth.display_name,
    })


user_provider = InMemoryProvider({
    'user1@example.com': User(id='user1@example.com'),
    'user2@example.com': User(id='user2@example.com'),
})

authenticators = [
    APIKeyAuthenticator(user_provider=user_provider),
]

routes = [
    Route('/', whoami_view),
]

middleware = [
    Middleware(AuthenticationMiddleware, authenticators=authenticators)
]

app = Starlette(routes=routes, middleware=middleware)

Now save the file to myapp.py and run it with uvicorn application server:

uvicorn myapp:app

Open http://127.0.0.1:8000/ and see that your request is not authenticated and user is anonymous. Let's pass API key via query parameters to make the configured APIKeyAuthenticator to load user. This time open http://127.0.0.1:8000/?apikey=user1@example.com in your browser. Now the request is fully authenticated as User1 user.

For more details refer to the doc sections below.

Docs

  1. UserLike protocol (a user model)
  2. Load user from databases using User Providers
  3. Request authentication
  4. Built-in authenticators
  5. User token
  6. Passwords
  7. Login/Logout flow
  8. User impersontation

Usage

See examples/ directory.

Metadata

Release files for imia 0.5.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 imia 0.5.3
File Size Uploaded Provenance Actions
imia-0.5.3.tar.gz 14.3 kB Without provenance Details for imia-0.5.3.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for imia 0.5.3
File Interpreter ABI Platform Actions
imia-0.5.3-py3-none-any.whl Python 3 none any Details for imia-0.5.3-py3-none-any.whl

Total release size: 28.0 kB

Release files / imia-0.5.3.tar.gz

Download URL imia-0.5.3.tar.gz
Size 14.3 kB
Tags Source
SHA-256 checksum
How to use checksums
e02cdebceef1828f076f52477bf78612dabf282ac9334855ffb491576c26bb1f
BLAKE2b-256 checksum
How to use checksums
7c675d7cc27a1c8b5d66f09736ad1ca513ccbf3dd9fa2f9a6d8b96124715fe00
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.1.14 CPython/3.10.5 Linux/5.13.0-1031-azure

Release files / imia-0.5.3-py3-none-any.whl

Download URL imia-0.5.3-py3-none-any.whl
Size 13.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f8edce6c04c4eb4542aee0fe90126899858c3466636134dbfb414edb0a475273
BLAKE2b-256 checksum
How to use checksums
71657bb38c17d10016fe28a07921c5561a0e0045d72771fe8a9ab9bbcd267119
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.1.14 CPython/3.10.5 Linux/5.13.0-1031-azure

Security for imia 0.5.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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