{"id":22009701,"url":"https://github.com/zitadel/example-api-python3-flask","last_synced_at":"2025-05-06T18:15:42.270Z","repository":{"id":103222465,"uuid":"590434228","full_name":"zitadel/example-api-python3-flask","owner":"zitadel","description":"Example Python3 + Flask API for authentication and authorization with ZITADEL ","archived":false,"fork":false,"pushed_at":"2024-07-09T18:05:15.000Z","size":33,"stargazers_count":13,"open_issues_count":7,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-31T01:41:17.616Z","etag":null,"topics":["api","examples","flask","oidc","python3","zitadel"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zitadel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2023-01-18T12:09:56.000Z","updated_at":"2025-03-18T21:49:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"caf87fe1-b490-4ba2-b12b-7c37eb8d7bfe","html_url":"https://github.com/zitadel/example-api-python3-flask","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/zitadel%2Fexample-api-python3-flask","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zitadel%2Fexample-api-python3-flask/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zitadel%2Fexample-api-python3-flask/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zitadel%2Fexample-api-python3-flask/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zitadel","download_url":"https://codeload.github.com/zitadel/example-api-python3-flask/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252741475,"owners_count":21797027,"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","examples","flask","oidc","python3","zitadel"],"created_at":"2024-11-30T02:10:29.508Z","updated_at":"2025-05-06T18:15:42.245Z","avatar_url":"https://github.com/zitadel.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Example: Python3 Flask API Authentication and Authorization\n\nThis example shows you how to create a Python3 API using Flask.\n\n## Overview\n\nThe API will have a public, private, and private-scoped route and check if a user is authenticated and authorized to access the routes.\nOur private routes expect an authorization header with an valid access_token in the request.\nThe API will validate the access_token on the [introspect endpoint](https://zitadel.com/docs/apis/openidoauth/endpoints#introspection_endpoint) and receives the user's roles.\n\nThe API application uses [Client Secret Basic](https://zitadel.com/docs/apis/openidoauth/authn-methods#client-secret-basic) to authenticate against ZITADEL and access the introspection endpoint.\nYou can use any valid access_token from a user or service account to send requests to the example API.\nIn this example we will use a service account with a [personal access token](https://zitadel.com/docs/guides/integrate/pat) which can be used directly to access the example API.\n\n```mermaid\n  graph LR;\n      User-- request auth:access_token --\u003eAPI;\n      API\u003c-- get claims auth:clientSecret --\u003eintrospect_endpoint\n      API-- response --\u003eUser\n      subgraph backend\n        API-- validate --\u003eAPI\n      end\n      subgraph zitadel\n        introspect_endpoint\n      end\n```\n\n## Running the example\n\nIn order to run the example you need to have `python3` and `pip` installed.\n\n### ZITADEL configuration\n\nYou need to setup a couple of things in ZITADEL. If you don't have an instance yet, please go ahead and create an instance following our [Get Started Guide](https://zitadel.com/docs/guides/start/quickstart).\n\n#### 1. Create an application\n\nFollow [our guide](https://zitadel.com/docs/guides/manage/console/applications) to create a new application with type \"API\" and authentication method \"Basic\".\n\nSave both the ClientID and ClientSecret.\n\n#### 2. Create a service user and PAT\n\nFollow [our guide](https://zitadel.com/docs/guides/manage/console/users#create-user) to create a service user.\n\nCreate a personal access token, following [this guide](https://zitadel.com/docs/guides/integrate/pat#create-a-service-user-with-a-pat). No need to add the the user as manager.\n\n#### 3. Authorization\n\nFollow [this guide](https://zitadel.com/docs/guides/manage/console/roles) to create a role `read:messages` on your project.\n\nAuthorize the service user, by adding the role `read:messages` to the user.\n\n### Client configuration\n\nYou just need to create a file named `.env` in the directory.\nThere is in example configuration in the `.env.example` file. \n\nSet the values with the Instance Domain, Client ID, and Client Secret from the previous steps, and the client should work.\n\n### Start the service\n\n1. Install required dependencies with `pip install -r requirements.txt`\n2. Start the server with `python3 server.py`\n3. Open another terminal and follow the next step to test the API\n\nYou can optionally create a virtual environment before installing the dependencies by running `python3 -m venv venv`\n\n## Testing the API\n\n### Public route\n\nTry calling the public route\n\n```\ncurl --request GET \\\n    --url http://127.0.0.1:5000/api/public\n```\n\nYou should get a response with Status Code 200 and the following message.\n\n`{\"message\":\"Public route - You don't need to be authenticated to see this.\"}`\n\n### Private route\n\nTry calling the private route without authorization headers\n\n```\ncurl --request GET \\\n    --url http://127.0.0.1:5000/api/private\n```\n\nYou should get a response with Status Code 401 and an error message.\n\nSo let's add an authorization header to your request. Save the personal access token for your service user to a variable. \n\n`PAT=nr9vnUTkQkn4rxWk...`\n\nThen call the private route with the PAT in the authorization header.\n\n```\ncurl --request GET \\\n    --url http://127.0.0.1:5000/api/private \\\n    --header \"authorization: Bearer $PAT\"\n```\n\nNow you should get a response with Status Code 200 and the following message.\n\n`{\"message\":\"Private route - You need to be authenticated to see this.\"}`\n\n### Private route, protected\n\nTry calling the private route that requires the user to have a certain role\n\n```\ncurl --request GET \\\n    --url http://127.0.0.1:5000/api/private-scoped \\\n    --header \"authorization: Bearer $PAT\"\n```\n\nYou should get a response with Status Code 200 and the following message. \n\n`{\"message\":\"Private, scoped route - You need to be authenticated and have the role read:messages to see this.\"}`\n\nYou can remove the role from the service user in ZITADEL and try again. You should then get Status Code 401, unauthorized.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzitadel%2Fexample-api-python3-flask","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzitadel%2Fexample-api-python3-flask","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzitadel%2Fexample-api-python3-flask/lists"}