{"id":13501371,"url":"https://github.com/alex-oleshkevich/imia","last_synced_at":"2025-04-10T05:05:46.001Z","repository":{"id":37950291,"uuid":"392798880","full_name":"alex-oleshkevich/imia","owner":"alex-oleshkevich","description":"An authentication library for Starlette and FastAPI.","archived":false,"fork":false,"pushed_at":"2023-04-03T09:12:07.000Z","size":160,"stargazers_count":98,"open_issues_count":3,"forks_count":3,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-24T09:47:23.557Z","etag":null,"topics":["api-token","asyncio","authentication","fastapi","impersonation","python","starlette"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alex-oleshkevich.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.rst","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2021-08-04T19:02:55.000Z","updated_at":"2025-03-09T08:22:40.000Z","dependencies_parsed_at":"2023-10-20T16:32:38.755Z","dependency_job_id":null,"html_url":"https://github.com/alex-oleshkevich/imia","commit_stats":{"total_commits":67,"total_committers":1,"mean_commits":67.0,"dds":0.0,"last_synced_commit":"bd7c6a5384018f7285abf493d26df5c16dc609ea"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alex-oleshkevich%2Fimia","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alex-oleshkevich%2Fimia/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alex-oleshkevich%2Fimia/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alex-oleshkevich%2Fimia/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alex-oleshkevich","download_url":"https://codeload.github.com/alex-oleshkevich/imia/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246922248,"owners_count":20855345,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-token","asyncio","authentication","fastapi","impersonation","python","starlette"],"created_at":"2024-07-31T22:01:34.923Z","updated_at":"2025-04-03T02:11:54.431Z","avatar_url":"https://github.com/alex-oleshkevich.png","language":"Python","funding_links":[],"categories":["Python","Extensions"],"sub_categories":["Auth","Authentication \u0026 Authorization"],"readme":"# Imia\n\nImia (belarussian for \"a name\") is an authentication library for Starlette and FastAPI (python 3.8+).\n\n![PyPI](https://img.shields.io/pypi/v/imia)\n![GitHub Workflow Status](https://img.shields.io/github/workflow/status/alex-oleshkevich/imia/Lint)\n![GitHub](https://img.shields.io/github/license/alex-oleshkevich/imia)\n![Libraries.io dependency status for latest release](https://img.shields.io/librariesio/release/pypi/imia)\n![PyPI - Downloads](https://img.shields.io/pypi/dm/imia)\n![GitHub Release Date](https://img.shields.io/github/release-date/alex-oleshkevich/imia)\n![Lines of code](https://img.shields.io/tokei/lines/github/alex-oleshkevich/imia)\n\n## Production status\n\nThe library is considered in \"beta\" state thus may contain bugs or security issues, but I actively use it in production.\n\n## Installation\n\nInstall `imia` using PIP or poetry:\n\n```bash\npip install imia\n# or\npoetry add imia\n```\n\n## Features\n\n- Login/logout flows\n- Pluggable authenticators:\n    - WWW-Basic\n    - session\n    - token\n    - bearer token\n    - any token (customizable)\n    - API key\n- Database agnostic user storage\n- Authentication middleware\n    - with fallback strategies:\n        - redirect to an URL\n        - raise an exception\n        - do nothing\n    - with optional URL protection\n    - with option URL exclusion from protection\n- User Impersonation (stateless and stateful)\n- SQLAlchemy 1.4 (async mode) integration\n\n## TODO\n\n* remember me\n\n## A very quick start\n\nIf you are too lazy to read this doc, take a look into `examples/` directory. There you will find several files demoing\nvarious parts of this library.\n\n## How it works?\n\nHere are all moving parts:\n\n1. **UserLike** object, aka \"user model\" - is an arbitrary class that implements `imia.UserLike` protocol.\n2. **a user provider** - an adapter that loads user model (UserLike object) from the storage (a database).\n3. **an authenticator** - a class that loads user using the user provider from the request (eg. session)\n4. **an authentication middleware** that accepts an HTTP request and calls authenticators for a user model. The\n   middleware always populates `request.auth` with `UserToken`.\n6. **user token** is a class that holds authentication state\n\nWhen a HTTP request reaches your application, an `imia.AuthenticationMiddleware` will start handling it. The middleware\niterates over configured authenticators and stops on the first one that returns non-None value. At this point the\nrequest is considered authenticated. If no authenticators return user model then the middleware will create  _anonymous\nuser token_. The user token available in `request.auth` property. Use `user_token.is_authenticated` token property to\nmake sure that user is authenticated.\n\n## User authentication quick start\n\n1. Create a user model and implement methods defined by `imia.UserLike` protocol.\n2. Create an instance of `imia.UserProvider` that corresponds to your user storage. Feel free to create your own.\n3. Setup one or more authenticators and pass them to the middleware\n4. Add `imia.AuthenticationMiddleware` to your Starlette application\n\nAt this point you are done.\n\nHere is a brief example that uses in-memory provider for demo purpose. For production environment you should use\ndatabase backed providers like `SQLAlchemyORMUserProvider` or  `SQLAlchemyCoreUserProvider`. Also, for simplicity reason\nwe will not implement [login/logout flow](docs/login_logout.md) and will authenticate requests using API keys.\n\n```python\nfrom dataclasses import dataclass, field\n\nfrom starlette.applications import Starlette\nfrom starlette.middleware import Middleware\nfrom starlette.requests import Request\nfrom starlette.responses import JSONResponse\nfrom starlette.routing import Route\n\nfrom imia import APIKeyAuthenticator, AuthenticationMiddleware, InMemoryProvider\n\n\n@dataclass\nclass User:\n    \"\"\"This is our user model. It may be an ORM model, or any python class, the library does not care of it,\n    it only expects that the class has methods defined by the UserLike protocol.\"\"\"\n\n    id: str\n    password: str = 'password'\n    scopes: list[str] = field(default_factory=list)\n\n    def get_display_name(self) -\u003e str:\n        return self.id.split('@')[0].title()\n\n    def get_id(self) -\u003e str:\n        return self.id\n\n    def get_hashed_password(self) -\u003e str:\n        return self.password\n\n    def get_scopes(self) -\u003e list:\n        return self.scopes\n\n\nasync def whoami_view(request: Request) -\u003e JSONResponse:\n    return JSONResponse({\n        'id': request.auth.user_id,\n        'name': request.auth.display_name,\n    })\n\n\nuser_provider = InMemoryProvider({\n    'user1@example.com': User(id='user1@example.com'),\n    'user2@example.com': User(id='user2@example.com'),\n})\n\nauthenticators = [\n    APIKeyAuthenticator(user_provider=user_provider),\n]\n\nroutes = [\n    Route('/', whoami_view),\n]\n\nmiddleware = [\n    Middleware(AuthenticationMiddleware, authenticators=authenticators)\n]\n\napp = Starlette(routes=routes, middleware=middleware)\n```\n\nNow save the file to `myapp.py` and run it with [uvicorn](https://uvicorn.org) application server:\n\n```bash\nuvicorn myapp:app\n```\n\nOpen `http://127.0.0.1:8000/` and see that your request is not authenticated and user is anonymous. Let's pass API key\nvia query parameters to make the configured APIKeyAuthenticator to load user. This time\nopen `http://127.0.0.1:8000/?apikey=user1@example.com` in your browser. Now the request is fully authenticated as User1\nuser.\n\nFor more details refer to the doc sections below.\n\n## Docs\n\n1. [UserLike protocol (a user model)](docs/userlike_protocol.md)\n2. [Load user from databases using User Providers](docs/user_providers.md)\n6. [Request authentication](docs/authentication.md)\n7. [Built-in authenticators](docs/authenticators.md)\n5. [User token](docs/user_token.md)\n5. [Passwords](docs/password_verification.md)\n4. [Login/Logout flow](docs/login_logout.md)\n8. [User impersontation](docs/impersonation.md)\n\n## Usage\n\nSee [examples/](examples) directory.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falex-oleshkevich%2Fimia","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falex-oleshkevich%2Fimia","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falex-oleshkevich%2Fimia/lists"}