{"id":15044021,"url":"https://github.com/busykoala/fastapi-opa","last_synced_at":"2025-04-05T06:04:23.268Z","repository":{"id":39750153,"uuid":"354345741","full_name":"busykoala/fastapi-opa","owner":"busykoala","description":"Fastapi OPA middleware incl. auth flow.","archived":false,"fork":false,"pushed_at":"2025-01-01T20:27:18.000Z","size":597,"stargazers_count":60,"open_issues_count":2,"forks_count":14,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-29T05:05:55.974Z","etag":null,"topics":["authentication-flow","authorization","fastapi","fastapi-opa","open-policy-agent"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/busykoala.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","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}},"created_at":"2021-04-03T16:54:48.000Z","updated_at":"2025-02-14T17:25:19.000Z","dependencies_parsed_at":"2023-02-01T03:15:43.565Z","dependency_job_id":"9d376c2e-54fc-4985-830f-60b7ea6c90e0","html_url":"https://github.com/busykoala/fastapi-opa","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/busykoala%2Ffastapi-opa","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/busykoala%2Ffastapi-opa/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/busykoala%2Ffastapi-opa/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/busykoala%2Ffastapi-opa/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/busykoala","download_url":"https://codeload.github.com/busykoala/fastapi-opa/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247294516,"owners_count":20915340,"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":["authentication-flow","authorization","fastapi","fastapi-opa","open-policy-agent"],"created_at":"2024-09-24T20:49:57.818Z","updated_at":"2025-04-05T06:04:23.234Z","avatar_url":"https://github.com/busykoala.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Open Policy Agent middleware for FastAPI\n\n## Table of contents\n- [Contributors](#contributors)\n- [What does fastapi-opa do](#about)\n- [Installation](#installation)\n- [How to get started](#getting-started)\n- [Open Policy Agent](#opa)\n- [Authentication flow](#auth-flow)\n  - [API key authentication](#api-key-auth)\n  - [OIDC authentication](#oidc-auth)\n  - [SAML authentication](#saml-auth)\n- [Custom payload enrichment](#custom-payload-enrichment)\n  - [GraphQL enrichment](#gql-enrichment)\n\n\u003ca name=\"contributors\"/\u003e\n\n## Contributors\n\nThanks to all the contributors below. Furthermore thanks for raising issues.\n\n\u003ca href=\"https://github.com/morestanna\"\u003e\n  \u003cimg src=\"https://avatars.githubusercontent.com/morestanna\" width=\"60\" height=\"60\" /\u003e\n\u003c/a\u003e\n\u003ca href=\"https://github.com/busykoala\"\u003e\n  \u003cimg src=\"https://avatars.githubusercontent.com/busykoala\" width=\"60\" height=\"60\" /\u003e\n\u003c/a\u003e\n\u003ca href=\"https://github.com/TracyWR\"\u003e\n  \u003cimg src=\"https://avatars.githubusercontent.com/TracyWR\" width=\"60\" height=\"60\" /\u003e\n\u003c/a\u003e\n\u003ca href=\"https://github.com/loikki\"\u003e\n  \u003cimg src=\"https://avatars.githubusercontent.com/loikki\" width=\"60\" height=\"60\" /\u003e\n\u003c/a\u003e\n\u003ca href=\"https://github.com/ejsyx\"\u003e\n  \u003cimg src=\"https://avatars.githubusercontent.com/ejsyx\" width=\"60\" height=\"60\" /\u003e\n\u003c/a\u003e\n\u003ca href=\"https://github.com/JimFawkes\"\u003e\n  \u003cimg src=\"https://avatars.githubusercontent.com/JimFawkes\" width=\"60\" height=\"60\" /\u003e\n\u003c/a\u003e\n\u003ca href=\"https://github.com/DiamondJoseph\"\u003e\n  \u003cimg src=\"https://avatars.githubusercontent.com/DiamondJoseph\" width=\"60\" height=\"60\" /\u003e\n\u003c/a\u003e\n\u003ca href=\"https://github.com/miceg\"\u003e\n  \u003cimg src=\"https://avatars.githubusercontent.com/miceg\" width=\"60\" height=\"60\" /\u003e\n\u003c/a\u003e\n\u003ca href=\"https://github.com/JulianSprung\"\u003e\n  \u003cimg src=\"https://avatars.githubusercontent.com/JulianSprung\" width=\"60\" height=\"60\" /\u003e\n\u003c/a\u003e\n\n\u003ca name=\"about\"/\u003e\n\n## What does fastapi-opa do\n\nThe FastAPI extension `fastapi-opa` allows to add login flows and integrates\nOpen Policy Agent to your app.\n\n![Flow Diagram](https://raw.githubusercontent.com/busykoala/fastapi-opa/master/assets/diagram.png)\n\nThe middleware redirects the request to the identity provider. After the\nauthentication it validates the token. Using the token, Open Policy Agent\ndecides if the response has success or failure status.\n\n\u003ca name=\"installation\"/\u003e\n\n## Installation\n\n```bash\npoetry add [--extras \"graphql\"] [--extras \"saml\"] fastapi-opa \n```\n\n\u003ca name=\"getting-started\"/\u003e\n\n## How to get started\n\n:bulb: checkout the wiki for an environment setup with Keycloak and Open Policy Agent:  \n[Getting Started with FastAPI app with Authentication and Authorization](https://github.com/busykoala/fastapi-opa/wiki#dev-setup)\n\nThe package combines authentication and authorization with FastAPI. You can\ncustomize the `OPAMiddleware` depending on your authentication flow.\n\nCheck out these examples for the most common flows:\n- OIDC: `fastapi_opa.example_oidc.py`\n- SAML: `fastapi_opa.example_saml.py`\n\n## Open Policy Agent\n\nThe middleware sends the validated and authenticated user token to Open\nPolicy Agent. It adds the extra attributes `request_method` and\n`request_path`.\n\n```json\n{\n    \"input\": {\n        \"exp\": 1617466243,\n        \"iat\": 1617465943,\n        \"auth_time\": 1617465663,\n        \"jti\": \"9aacb638-70c6-4f0a-b0c8-dbc67f92e3d1\",\n        \"iss\": \"http://localhost:8080/auth/realms/example-realm\",\n        \"aud\": \"example-client\",\n        \"sub\": \"ccf78dc0-e1d6-4606-99d4-9009e74e3ab4\",\n        \"typ\": \"ID\",\n        \"azp\": \"david\",\n        \"session_state\": \"41640fe7-39d2-44bc-818c-a3360b36fb87\",\n        \"at_hash\": \"2IGw-B9f5910Sll1tnfQRg\",\n        \"acr\": \"0\",\n        \"email_verified\": false,\n        \"hr\": \"true\",\n        \"preferred_username\": \"david\",\n        \"user\": \"david\",\n        \"subordinates\": [],\n        \"request_method\": \"GET\",\n        \"request_path\": [\"finance\", \"salary\", \"david\"]\n    }\n}\n```\n\nIn Open Policy Agent you can create policies using user roles,\nroutes, request methods etc.\n\nAn example policy (from [the official Open Policy Agent\ndocs](https://www.openpolicyagent.org/docs/v0.11.0/http-api-authorization/))\nfor this setup could look like this:\n\n```rego\npackage httpapi.authz\n\n# bob is alice's manager, and betty is charlie's.\nsubordinates = {\"alice\": [], \"charlie\": [], \"bob\": [\"alice\"], \"betty\": [\"charlie\"]}\n\n# HTTP API request\nimport input\n\ndefault allow = false\n\n# Allow users to get their own salaries.\nallow {\n  some username\n  input.request_method == \"GET\"\n  input.request_path = [\"finance\", \"salary\", username]\n  input.user == username\n}\n\n# Allow managers to get their subordinates' salaries.\nallow {\n  some username\n  input.request_method == \"GET\"\n  input.request_path = [\"finance\", \"salary\", username]\n  subordinates[input.user][_] == username\n}\n```\n\n\u003ca name=\"auth-flow\"/\u003e\n\n## Authentication flow\n\nUse the provided interface to set up your desired authentication flow. Then\ninsert it into `OPAMiddleware` (`fastapi_opa.auth.auth_interface.AuthInterface`).\nConsider submitting a pull request with new flows.\n\nYou can also use these ready-to-go implementations:\n\n\u003ca name=\"api-key-auth\"/\u003e\n\n### API key authentication\n\nIn the API key authentication a request header needs to match a given value.\n\n```python\n# Configure API keys\napi_key_config = APIKeyConfig(\n    header_key=\"test\",\n    api_key=\"1234\"\n)\napi_key_auth = APIKeyAuthentication(api_key_config)\n```\n\nIn the example the header `header[\"test\"] = \"1234\"` authenticates the request.\nFor Open Policy Agent, set user to `APIKey` and the variable `client` to the\nclient address.\n\n\u003ca name=\"oidc-auth\"/\u003e\n\n### OIDC authentication\n\nThe example in [How to get started](#getting-started) provides an example for\nthe implementation of the OIDC Authentication.\n\n\u003ca name=\"saml-auth\"/\u003e\n\n### SAML authentication\n\nFor the saml implementation create your certs using\n`openssl req -new -x509 -days 3652 -nodes -out sp.crt -keyout sp.key` and\nadd the keys to the sp section of your `settings.json`. Checkout the test\nsettings to get an idea (`tests/test_data/saml/*.json`).\nProvide the path to your own `settings.json` and `advanced_settings.json`\nin the `SAMLAuthConfig` like in the example below (don't use the test data in\nproduction).\n\n```python\nfrom fastapi_opa import OPAConfig\nfrom fastapi_opa.auth.auth_saml import SAMLAuthentication\nfrom fastapi_opa.auth.auth_saml import SAMLConfig\n\nopa_host = \"http://localhost:8181\"\n\nsaml_config = SAMLConfig(settings_directory=\"./tests/test_data/saml\")\nsaml_auth = SAMLAuthentication(saml_config)\n\nopa_config = OPAConfig(authentication=saml_auth, opa_host=opa_host,\n                       accepted_methods=[\"id_token\", \"access_token\"])\n```\n\nUpload the certificate to your identity provider. Using Keycloak as an\nidentity provider you need to configure `encrypt assertion`,\n`client signature required`, `force POST bindings` on creating the client.\nAlso configure: `Client Scopes` -\u003e `role_list (saml)` -\u003e `Mappers tab` -\u003e\n`role list` -\u003e `Single Role Attribute`\n\n\u003ca name=\"custom-payload-enrichment\"/\u003e\n\n## Custom payload enrichment\n\nUse the interface `fastapi_opa.opa.opa_config.Injectable` to add\nmore information to the payload sent to Open Policy Agent.\n\nConfigure the injectables in the `OPAConfig`:\n\n```python\nclass FancyInjectable(Injectable):\n    async def extract(self, request: Request) -\u003e List:\n        return [\"some\", \"custom\", \"stuff\"]\n\nfancy_inj = FancyInjectable(\"fancy_key\", skip_endpoints=[\"/health\", \"/api/[^/]*/test])\n\nopa_config = OPAConfig(\n    authentication=oidc_auth, opa_host=opa_host, injectables=[fancy_inj]\n)\n```\n\nUse `skip_endpoints` to choose which endpoints the injectable shouldn't affect.\nTo define an endpoint, specify an exact string or a regular expression.\n\n\u003ca name=\"gql-enrichment\"/\u003e\n\n### GraphQL enrichment\n\nFor GraphQL you can use the ready to go injectable:\n\n```python\nfrom fastapi_opa.opa.enrichment.graphql_enrichment import GraphQLInjectable`\n\ngraphql = GraphQLInjectable(\"gql_injectable\")\nopa_config = OPAConfig(authentication=oidc_auth, opa_host=opa_host, injectables=[graphql])\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbusykoala%2Ffastapi-opa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbusykoala%2Ffastapi-opa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbusykoala%2Ffastapi-opa/lists"}