{"id":13624620,"url":"https://github.com/embesozzi/keycloak-openfga-workshop","last_synced_at":"2025-08-16T01:14:12.676Z","repository":{"id":61842959,"uuid":"555695112","full_name":"embesozzi/keycloak-openfga-workshop","owner":"embesozzi","description":"Keycloak integration with OpenFGA (based on Zanzibar) for Fine-Grained Authorization at Scale (ReBAC)","archived":false,"fork":false,"pushed_at":"2024-07-12T14:48:06.000Z","size":22850,"stargazers_count":104,"open_issues_count":1,"forks_count":28,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-04-04T08:04:16.679Z","etag":null,"topics":["access-management","api","api-gateway","apisix","auth0","authorization","fine-grained-authorization","keycloak","oauth2","okta","openfga","rebac","roles","user-identity","workshop","zanzibar"],"latest_commit_sha":null,"homepage":"https://medium.com/@embesozzi/keycloak-integration-with-openfga-based-on-zanzibar-for-fine-grained-authorization-at-scale-d3376de00f9a","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/embesozzi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"custom":"https://www.paypal.me/embesozzi"}},"created_at":"2022-10-22T05:18:02.000Z","updated_at":"2025-04-03T18:41:48.000Z","dependencies_parsed_at":"2023-10-12T09:52:24.585Z","dependency_job_id":"f4b9ffbb-d3f1-474d-bc88-f2e9604cd82b","html_url":"https://github.com/embesozzi/keycloak-openfga-workshop","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/embesozzi/keycloak-openfga-workshop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/embesozzi%2Fkeycloak-openfga-workshop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/embesozzi%2Fkeycloak-openfga-workshop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/embesozzi%2Fkeycloak-openfga-workshop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/embesozzi%2Fkeycloak-openfga-workshop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/embesozzi","download_url":"https://codeload.github.com/embesozzi/keycloak-openfga-workshop/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/embesozzi%2Fkeycloak-openfga-workshop/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270653580,"owners_count":24622790,"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","status":"online","status_checked_at":"2025-08-15T02:00:12.559Z","response_time":110,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["access-management","api","api-gateway","apisix","auth0","authorization","fine-grained-authorization","keycloak","oauth2","okta","openfga","rebac","roles","user-identity","workshop","zanzibar"],"created_at":"2024-08-01T21:01:44.338Z","updated_at":"2025-08-16T01:14:12.656Z","avatar_url":"https://github.com/embesozzi.png","language":"JavaScript","funding_links":["https://www.paypal.me/embesozzi"],"categories":["JavaScript"],"sub_categories":[],"readme":"# Keycloak integration with OpenFGA (based on Zanzibar) for Fine-Grained Authorization at Scale (ReBAC)\nThis repository contains a PoC implemented with [Keycloak](https://www.keycloak.org/) integrated with [OpenFGA](https://openfga.dev/) on demostrating how to apply fine-grained access (FGA) control in a high performance and flexible authorization.\n\nIn this version of the PoC we have a direct integration between the Access Manager platform and the OpenFGA solution thanks to the use of the [OpenFGA Java SDK](https://github.com/openfga/java-sdk) to publish the events.\n\nThis workshop is based the following article [Keycloak integration with OpenFGA (based on Zanzibar) for Fine-Grained Authorization at Scale (ReBAC)](https://embesozzi.medium.com/keycloak-integration-with-openfga-based-on-zanzibar-for-fine-grained-authorization-at-scale-d3376de00f9a). You will find there full details about the authorization architecture guidelines and involved components.\n\nIn the new version 🔥, I aimed to continue improving the authorization architecture and provide an agnostic approach for exposing and protecting APIs following best practices such as Policy as Code (PaC), decoupling authorization, and low-code authorization. Therefore, I added an identity-aware API gateway, Apache APISIX, as an API sidecar to the authorization architecture to enforce authorization and decouple it from the backend. The gateway uses a plugin I developed called [authz-openfga](https://github.com/embesozzi/apisix-authz-openfga) that supports Relationship-Based Access Control (ReBAC) policies because it's integrated with OpenFGA platform. The details are explained in the following article [Mastering Access Control: Implementing Low-Code Authorization Based on ReBAC and Decoupling Pattern](https://medium.com/@embesozzi/mastering-access-control-implementing-low-code-authorization-based-on-rebac-and-decoupling-pattern-f6f54f70115e).\n\n## Authorization Framework (New)\n\nThe following diagram illustrates the solution architecture of this workshop:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"90%\" height=\"90%\" src=\"doc/images/workshop-docker-environment.png\"\u003e\n\u003c/p\u003e\n\n* Core:\n    * Keycloak is responsible for handling the authentication with the standard OpenID Connect and manages user access with its Role Model.\n    * Keycloak is configured with a new custom extension ❤️: [keycloak-openfga-event-publisher](https://github.com/embesozzi/keycloak-openfga-event-publisher)\n      * Listens to the Keycloak events (User Role Assignment, Role to Role Assignment, etc).\n      * Parses this event into an OpenFGA tuple key based on the [Keycloak Authorization Schema](model.dsl).\n      * Publishes them to OpenFGA over HTTP using the [OpenFGA Java SDK](https://github.com/openfga/java-sdk).\n    * OpenFGA is responsible for applying fine-grained access control. The OpenFGA service answers authorization checks by determining whether a relationship exists between an object and a user.\n* Other components\n    * Store Web Application is integrated with Keycloak by OpenID Connect\n    * Store Authorization Gateway exposes and protects the Store API with ReBAC policies integrated with the OpenFGA Platform (Protection at API Gateway)🔥.\n\nYou can also have Store OpenFGA API is protected by OAuth 2.0 and it utilizes the OpenFGA SDK for FGA as example (Protection at API Level).\n\n\nAnother cool feature of custom extension is its capability to discover the OpenFGA authorization model and determine which events are handled. This gives you the flexibility to choose your authorization model, whether it’s RBAC, GBAC, or both 🙌.\n\n# How to install?\n## Prerequisites\n\n * Install Git, [Docker](https://www.docker.com/get-docker) and [Docker Compose](https://docs.docker.com/compose/install/#install-compose) in order to run the steps provided in the next section\u003cbr\u003e\n\n## Deploy the PoC\n\n1. Clone this repository\n    ````bash\n    git clone https://github.com/embesozzi/keycloak-openfga-workshop\n    cd keycloak-openfga-workshop\n    ````\n\n2. Execute following Docker Compose command to start the deployment\n\n   ```sh\n   docker-compose -f docker-compose.yml -f docker-compose-apps.yml -f docker-compose-openfga.yml -f docker-compose-import.yml up\n   ```\n\n3. To be able to use this environment, you need to add this line to your local HOSTS file:\n\n   ```sh\n   127.0.0.1  keycloak openfga store store-openfga-api store-authz-gateway\n   ```\n\n4. Access the following web UIs using URLs bellow via a web browser.\n\n    | Component                 |  URI                          |  Credential               | Image                                    |\n    | ------------------------- |:-----------------------------:|:-------------------------:|:-----------------------------------------:\n    | Keycloak Console          |   http://keycloak:8081        |  admin / password         | quay.io/keycloak/keycloak:25.0.1         |\n    | OpenFGA Playground        |   http://localhost:3000/playground  |                     | openfga/openfga:v1.5.5                   | \n    | Store Portal              |   http://store:9090           |                           | Custom image                             |\n    | Store Authorization Gateway    |   http://store-authz-gateway:9080 |                  | Custom image based Apache APISIX Gateway |\n    | Store OpenFGA API              |   http://store-openfga:9091       |                  | Custom image                             |\n\n\u003e\n\u003e In the latest version, the store portal calls the API exposed by the Store Authorization Gateway (`store-authz-gateway:9080`). If you want to call the Store OpenFGA API (`store-openfga:9091`), just adjust the store portal configuration\n\u003e\n    \n## Review configuration (optional)\n\n\u003e\n\u003e In this new version of the workshop, we automatically import all the required configurations into the Keycloak and OpenFGA platforms 😄 🪄\n\u003e\n       \n### Keycloak Platform\n- You will find that the OpenFGA Event Listener 'openfga-events-publisher' extension in Keycloak is enabled.\n\n    * [Administration console](http://keycloak:8081) \u003e Realm settings \u003e `openfga-events-publisher`   \n\n    \u003cimg src=\"doc/images/kc-admin-events.png\" width=\"80%\" height=\"80%\"\u003e\n\n- The following roles and demo users have already been created in Keycloak.\n\n    ![users](doc/images/users.png)\n\n    The password for all the users is `demo1234!`\n\n### OpenFGA Platform\n- You will see the following OpenFGA Authorization Model in the [OpenFGA Playground Console](http://localhost:3000/playground) and the Tuples tab:\n\n  \u003cimg src=\"doc/images/openfga-tuples.png\" width=\"80%\" height=\"80%\"\u003e\n\n- Once the workshop is deployed, the Keycloak OpenFGA Event Publisher extension proceeds to send these events over HTTP to the OpenFGA solution. Here, all tuples are stored.\n\n    | User                      |  Relation                     |  Object               | \n    | ------------------------- |:-----------------------------:|:---------------------:|\n    | role:admin-catalog        |   parent                      |  role:view-product    |\n    | role:analyst-catalog      |   parent                      |  role:view-product    |\n    | role:admin-catalog        |   parent                      |  role:edit-product    |\n    | user:paula                |   assignee                    |  role:analyst-catalog |\n    | user:richard              |   assignee                    |  role:admin-catalog   |\n\n\n    The users are identified by the value of the claim sub.\n\n## Test cases\nAs an example, we will implement an Product Catalog web application that has the following requirements:\n* Only authenticated user can access to the application\n* Product can be viewed by their Analyst\n* Product can be edited by their Admin\n* Global Admin users can view or edit any Product\n\nYou can follow the test cases described in the [Keycloak integration with OpenFGA (based on Zanzibar) for Fine-Grained Authorization at Scale (ReBAC)](https://embesozzi.medium.com/keycloak-integration-with-openfga-based-on-zanzibar-for-fine-grained-authorization-at-scale-d3376de00f9a).\n\nAnd the article [Mastering Access Control: Implementing Low-Code Authorization Based on ReBAC and Decoupling Pattern](https://medium.com/@embesozzi/mastering-access-control-implementing-low-code-authorization-based-on-rebac-and-decoupling-pattern-f6f54f70115e).\n\nNevertheless, the use cases are detailed below:\n\n### Use case 1: Access to the Store for managing products as an Analyst (Paula)\n\n1. Access to the [store web application](http://store:9090) store web application and proceed to login with Paula (paula / demo1234!) in Keycloak.\n    \n    \u003cimg src=\"doc/images/tc-store-login.png\" width=\"80%\" height=\"80%\"\u003e\n\n2. Keycloak will return the id_token and the access token to the application\n\n3. The Store web application will show the product catalog\n\n    3.1. The app will call the product API sending the access token in the Authorization header\n\n    3.2. The API will apply the following steps:\n\n    3.3. It will validate the token following the OAuth 2.0 standard and it will extract the claim sub to identify the user\n\n    3.4. Then it will call the OpenFGA API to check if the user has the view-product role with the relationship assignee\n\n    3.5. OpenFGA will return the response “allowed”\n\n    3.6. The API will return the product information and the Store web app will show the product catalog to the user\n    \n    \u003cimg src=\"doc/images/tc1-view-products-success.png\" width=\"80%\" height=\"80%\"\u003e\n\n4. Try to publish a product by clicking the button \"Publish\" but you will see that Paula is not allowed\n\n    4.1. The app will call the product API sending the access token in the Authorization header\n\n    4.2. The API will apply the following steps:\n\n    4.3. It will validate the token following the OAuth 2.0 standard and it will extract the claim sub to identify the user\n\n    4.4. Then it will call the OpenFGA API to check if the user has the edit-product role with the relationship assignee\n\n    4.5. OpenFGA will return the response “denied”\n\n    \u003cimg src=\"doc/images/tc1-publish-product-denied.png\" width=\"80%\" height=\"80%\"\u003e    \n\n### Use case 2: Access to the Store for managing products as an Admin (Richard)\n\n1. Access to the [store web application](http://store:9090) store web application and proceed to login with Richard (richard / demo1234!) in Keycloak.\n    \n    \u003cimg src=\"doc/images/tc-store-login.png\" width=\"80%\" height=\"80%\"\u003e\n\n2. Keycloak will return the id_token and the access token to the application\n\n3. The store web application will show the product catalog\n\n    \u003cimg src=\"doc/images/tc-2-view-products-success.png\" width=\"80%\" height=\"80%\"\u003e\n\n4. Try to publish a product by clicking the button \"Publish\" but you will see that Richard is allowed\n\n    \u003cimg src=\"doc/images/tc-2-publish-product-success.png\" width=\"80%\" height=\"80%\"\u003e\n\n\n### Use case 3:  Access to the Store for managing products as an Regular User (Peter)\n\n1. Access to the [store web application](http://store:9090) store web application and proceed to login with Peter (peter / demo1234!) in Keycloak.\n    \n    \u003cimg src=\"doc/images/tc-store-login.png\" width=\"80%\" height=\"80%\"\u003e\n\n2. Keycloak will return the id_token and the access token to the application\n\n3. The store web application will try to the products show but the user is not allowed\n\n    \u003cimg src=\"doc/images/tc-3-view-products-denied.png\" width=\"80%\" height=\"80%\"\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fembesozzi%2Fkeycloak-openfga-workshop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fembesozzi%2Fkeycloak-openfga-workshop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fembesozzi%2Fkeycloak-openfga-workshop/lists"}