{"id":13787791,"url":"https://github.com/xenit-eu/thunx","last_synced_at":"2026-03-10T11:02:57.419Z","repository":{"id":40412998,"uuid":"375046549","full_name":"xenit-eu/thunx","owner":"xenit-eu","description":"Pluggable ABAC/PBAC middleware","archived":false,"fork":false,"pushed_at":"2025-03-21T07:44:53.000Z","size":1726,"stargazers_count":32,"open_issues_count":2,"forks_count":10,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-27T02:11:41.197Z","etag":null,"topics":["java","openpolicyagent","querydsl","spring","spring-cloud-gateway","spring-data-jpa","spring-security"],"latest_commit_sha":null,"homepage":"","language":"Java","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/xenit-eu.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-06-08T14:50:59.000Z","updated_at":"2025-03-21T07:44:56.000Z","dependencies_parsed_at":"2024-02-05T23:25:16.877Z","dependency_job_id":"2fbea67a-c680-4fa4-9e82-083cbc2ba791","html_url":"https://github.com/xenit-eu/thunx","commit_stats":{"total_commits":281,"total_committers":7,"mean_commits":"40.142857142857146","dds":0.5978647686832741,"last_synced_commit":"be5dce9e533d9beff9e89014fb9a2f8212ce1397"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xenit-eu%2Fthunx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xenit-eu%2Fthunx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xenit-eu%2Fthunx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xenit-eu%2Fthunx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xenit-eu","download_url":"https://codeload.github.com/xenit-eu/thunx/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248703196,"owners_count":21148117,"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":["java","openpolicyagent","querydsl","spring","spring-cloud-gateway","spring-data-jpa","spring-security"],"created_at":"2024-08-03T21:00:31.183Z","updated_at":"2026-03-10T11:02:57.352Z","avatar_url":"https://github.com/xenit-eu.png","language":"Java","funding_links":[],"categories":["Language and Platform Integrations"],"sub_categories":["Java"],"readme":"# Thunx  \n\n[![build](https://github.com/xenit-eu/thunx/workflows/build/badge.svg?branch=main)](https://github.com/xenit-eu/thunx/actions/workflows/ci.yml)\n[![maven central](https://img.shields.io/maven-central/v/com.contentgrid.thunx/thunx-spring?color=blue)](https://search.maven.org/search?q=g:com.contentgrid.thunx)\n[![Apache License 2](https://img.shields.io/github/license/xenit-eu/thunx?color=blue)](LICENSE)\n\nThunx is a pluggable [Attribute Based Access Control] system, with and end-to-end implementation\nusing:\n* [OpenPolicyAgent] as a policy engine\n* [Spring Cloud Gateway] as a policy enforcement point \n* [Spring Data REST] as an API service\n\nThis project uses a distributed authorization architecture, by applying:\n* early access decisions at the API Gateway \n* postponed access decisions in the Spring Data REST service\n\nWhen the API Gateway does not have sufficient contextual information to grant or deny access,\nit delegates the policy decision to the Spring Data REST service. This API Service receives an\nauthorization-predicate, a __thunk__ from the API Gateway and rewrites the database queries to\nensure the authorization-predicate is satisfied.\n\n### Advantages\n\nThis approach provides the following advantages:\n\n* **Decoupling**: The API service does not need to be concerned with authorization logic.\n* **Performance**: Using query-rewriting instead of post-filtering can be orders of magnitude faster.\n* **Performance**: By delegating decisions to the appropriate data-context, access policies can be much more\n  fine-grained, without paying a big runtime penalty for loading data in the policy engine on demand.\n\n[Attribute Based Access Control]: https://en.wikipedia.org/wiki/Attribute-based_access_control\n[OpenPolicyAgent]: https://www.openpolicyagent.org/\n[Spring Cloud Gateway]: https://spring.io/projects/spring-cloud-gateway\n[Spring Data REST]: https://spring.io/projects/spring-data-rest\n[QueryDSL]: http://www.querydsl.com/\n\n## Architecture overview\n\nThis section describes the Thunx architecture.\n\nPlease note all the diagrams use the [C4 model] style. A legend, included in every diagram, explains the meaning\nof each shape.\n\nA _Client-side webapp_ uses a REST API provided by the _API Service_. An API Gateway sits in between,\nwhich takes care of authentication and authorization concerns.\n\nThe _Client-side webapp_ gets an access token with an OIDC Identity Provider and makes some REST API requests with the\naccess token. The API Gateway first validates the access token (authentication step). The user-profile is (optionally) \nloaded from the OIDC User Endpoint. The Gateway asks the Policy Decision Point (PDP) to authorize the request.\n\nIn a simple ABAC system, the authorization requests has a binary response: the policy engine returns an\n_access granted_ or _access denied_ decision. The API Gateway adheres to this decision and either allows or denies\nthe request, acting as a classic Policy Enforcement Point (PEP).\n\nOur system also allows for a _conditional and partial grant_. When the policy engine determines it does not have\nsufficient information to make a decision, it returns a residual policy, a predicate. Access to the API resource \nis conditionally granted, if and only if, the predicated can be fulfilled when the missing information is available.\n\nThe residual policy, in this case an [OpenPolicyAgent] `QuerySet`, is translated into a technology-neutral boolean\nexpression, called a `thunk-expression`. The `thunk-expression` is stored as a `thunk-context` in the API Gateway\nrequest context. The API Gateway forwards requests to the API Service and propagates the `thunk-context` by\nserializing and encoding the `thunk-context` as HTTP request headers.\n\nThe API Service receives the REST API request. A filter reconstructs the `thunk-context` from the HTTP request headers.\nThe `thunk-expression` from the `thunk-context` can be converted into a [QueryDSL] predicate. When the API service\nuses a JPA Repository, the [Spring Data QueryDSL Extension] can be used to include the QueryDSL predicate, and with\nthat fulfill the conditional authorization predicate.\n\n![overview](./resources/diagrams/container-diagram-overview.png)\n\n[C4 model]: https://c4model.com/\n\n[Spring Data QueryDSL Extension]: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#core.extensions.querydsl]\n\n### Solution mechanics\n\n#### Gateway\n\n#### Spring Data REST\n\n### Subprojects\n\nThis repository has several modules:\n\n* `thunx-model` is a set of (vendor-neutral) data structures to model authorization policy expressions\n* `thunx-pdp` is a central abstraction for a Policy Decision Point (PDP)\n* `thunx-pdp-opa` is a PDP implementation using [OpenPolicyAgent](https://www.openpolicyagent.org/).\n* `thunx-encoding-json` is a JSON-serialization library for thunk-expressions\n* `thunx-predicates-querydsl` is a library to convert thunk-expressions into QueryDSL predicates\n* `thunx-spring-api` provides an integration with Spring Data REST\n* `thunx-spring-gateway` provides an integration with Spring Cloud Gateway\n* `thunx-spring-querydsl-predicate-resolver` is a library to inject additional [QueryDSL] predicates to be processed\n  together with the predicates from the [Spring Data QueryDSL Extension]\n* `thunx-spring-security` provides an integration with JWT Authentication Tokens from Spring Security\n\n## Getting Started\n\n### Installation\n\nRequirements:\n\n* Java 17+\n\n#### Spring Cloud Gateway\n\nUsing Gradle:\n\n```groovy\nimplementation \"com.contentgrid.thunx:thunx-gateway-spring-boot-starter:${thunxVersion}\"\n```\n\n#### Spring Data REST Service\n\nUsing Gradle:\n\n```groovy\nimplementation \"com.contentgrid.thunx:thunx-gateway-spring-boot-starter:${thunxVersion}\"\n\nimplementation \"com.querydsl:querydsl-jpa\" // Or another QueryDSL implementation, dependent on the spring data flavor you're using\n```\n\n\n## License\n\nApache License Version 2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxenit-eu%2Fthunx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxenit-eu%2Fthunx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxenit-eu%2Fthunx/lists"}