{"id":22048538,"url":"https://github.com/samhammerag/sag_py_auth","last_synced_at":"2025-05-08T23:05:05.577Z","repository":{"id":148442905,"uuid":"620489967","full_name":"SamhammerAG/sag_py_auth","owner":"SamhammerAG","description":"Keycloak authentication for python projects","archived":false,"fork":false,"pushed_at":"2025-04-25T10:46:19.000Z","size":84,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-05-08T23:04:56.880Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/SamhammerAG.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-03-28T19:34:13.000Z","updated_at":"2025-04-25T10:45:50.000Z","dependencies_parsed_at":"2024-05-21T11:36:30.410Z","dependency_job_id":"c390c9e6-7a69-4de5-b0a6-8d9d643728cc","html_url":"https://github.com/SamhammerAG/sag_py_auth","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamhammerAG%2Fsag_py_auth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamhammerAG%2Fsag_py_auth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamhammerAG%2Fsag_py_auth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamhammerAG%2Fsag_py_auth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SamhammerAG","download_url":"https://codeload.github.com/SamhammerAG/sag_py_auth/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253160770,"owners_count":21863627,"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":[],"created_at":"2024-11-30T14:12:42.916Z","updated_at":"2025-05-08T23:05:05.556Z","avatar_url":"https://github.com/SamhammerAG.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# sag_py_auth\n\n[![Maintainability][codeclimate-image]][codeclimate-url]\n[![Coverage Status][coveralls-image]][coveralls-url]\n[![Known Vulnerabilities](https://snyk.io/test/github/SamhammerAG/sag_py_auth/badge.svg)](https://snyk.io/test/github/SamhammerAG/sag_py_auth)\n\n[coveralls-image]:https://coveralls.io/repos/github/SamhammerAG/sag_py_auth/badge.svg?branch=master\n[coveralls-url]:https://coveralls.io/github/SamhammerAG/sag_py_auth?branch=master\n[codeclimate-image]:https://api.codeclimate.com/v1/badges/2da48e3952f9640f702f/maintainability\n[codeclimate-url]:https://codeclimate.com/github/SamhammerAG/sag_py_auth/maintainability\n\nThis provides a way to secure your fastapi with keycloak jwt bearer authentication.\n\n## What it does\n* Secure your api endpoints\n* Verifies auth tokens: signature, expiration, issuer, audience\n* Allows to set permissions by specifying roles and realm roles\n\n## How to use\n\n### Installation\n\npip install sag-py-auth\n\n### Secure your apis\n\nFirst create the fast api dependency with the auth config:\n```python\nfrom sag_py_auth.models import AuthConfig, TokenRole\nfrom sag_py_auth.jwt_auth import JwtAuth\nfrom fastapi import Depends\n\nauth_config = AuthConfig(\"https://authserver.com/auth/realms/projectName\", \"myaudience\")\nrequired_roles = [TokenRole(\"clientname\", \"adminrole\")]\nrequired_realm_roles = [\"additionalrealmrole\"]\nrequires_admin = Depends(JwtAuth(auth_config, required_roles, required_realm_roles))\n```\n\nAfterwards you can use it in your route like that:\n\n```python\n@app.post(\"/posts\", dependencies=[requires_admin], tags=[\"posts\"])\nasync def add_post(post: PostSchema) -\u003e dict:\n```\n\nOr if you use sub routes, auth can also be enforced for the entire route like that:\n\n```python\nrouter = APIRouter()\nrouter.include_router(sub_router, tags=[\"my_api_tag\"], prefix=\"/subroute\",dependencies=[requires_admin])\n```\n\n### Get user information\n\nThe Jwt call directly returns a token object that can be used to get additional information.\n\nFurthermore you can access the context directly:\n```python\nfrom sag_py_auth.auth_context import get_token as get_token_from_context\ntoken = get_token_from_context()\n```\n\nThis works in async calls but not in sub threads (without additional changes).\n\nSee:\n* https://docs.python.org/3/library/contextvars.html\n* https://kobybass.medium.com/python-contextvars-and-multithreading-faa33dbe953d\n\n#### Methods available on the token object\n\n* get_field_value: to get the value of a claim field (or an empty string if not present)\n* get_roles: Gets the roles of a specific client\n* has_role: Verify if a spcific client has a role\n* get_realm_roles: Get the realm roles\n* has_realm_role: Check if the user has a specific realm role\n\n\n### Log user data\n\nIt is possible to log the preferred_username and the azp value (party that created the token) of the token by adding a filter.\n\n```python\nimport logging\nfrom sag_py_auth import UserNameLoggingFilter\n\nconsole_handler = logging.StreamHandler(sys.stdout)\nconsole_handler.addFilter(UserNameLoggingFilter())\n\n```\n\nThe filter provides the following two fields as soon as the user is authenticated: user_name, authorized_party\n\n### How a token has to look like\n\n```json\n{\n\n    \"iss\": \"https://authserver.com/auth/realms/projectName\",\n    \"aud\": [\"audienceOne\", \"audienceTwo\"],\n    \"typ\": \"Bearer\",\n    \"azp\": \"public-project-swagger\",\n    \"preferred_username\": \"preferredUsernameValue\",\n    .....\n    \"realm_access\": {\n        \"roles\": [\"myRealmRoleOne\"]\n    },\n    \"resource_access\": {\n        \"my-client-one\": {\n            \"roles\": [\"a-permission-role\", \"user\"]\n        },\n        \"my-client-two\": {\n            \"roles\": [\"a-permission-role\", \"admin\"]\n        }\n    }\n}\n```\n\n* realm_access contains the realm roles\n* resource_access contains the token roles for one or multiple clients\n\n## How to start developing\n\n### With vscode\n\nJust install vscode with dev containers extension. All required extensions and configurations are prepared automatically.\n\n### With pycharm\n\n* Install latest pycharm\n* Install pycharm plugin BlackConnect\n* Install pycharm plugin Mypy\n* Configure the python interpreter/venv\n* pip install requirements-dev.txt\n* pip install black[d]\n* Ctl+Alt+S =\u003e Check Tools =\u003e BlackConnect =\u003e Trigger when saving changed files\n* Ctl+Alt+S =\u003e Check Tools =\u003e BlackConnect =\u003e Trigger on code reformat\n* Ctl+Alt+S =\u003e Click Tools =\u003e BlackConnect =\u003e \"Load from pyproject.yaml\" (ensure line length is 120)\n* Ctl+Alt+S =\u003e Click Tools =\u003e BlackConnect =\u003e Configure path to the blackd.exe at the \"local instance\" config (e.g. C:\\Python310\\Scripts\\blackd.exe)\n* Ctl+Alt+S =\u003e Click Tools =\u003e Actions on save =\u003e Reformat code\n* Restart pycharm\n\n## How to publish\n* Update the version in setup.py and commit your change\n* Create a tag with the same version number\n* Let github do the rest\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamhammerag%2Fsag_py_auth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsamhammerag%2Fsag_py_auth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamhammerag%2Fsag_py_auth/lists"}