{"id":23773865,"url":"https://github.com/open-policy-agent/opa-springboot","last_synced_at":"2025-09-05T18:31:32.459Z","repository":{"id":249722322,"uuid":"827895234","full_name":"StyraInc/opa-springboot","owner":"StyraInc","description":"The Styra-supported driver to connect Spring Boot applications to Open Policy Agent (OPA) and Enterprise OPA deployments.","archived":false,"fork":false,"pushed_at":"2024-11-28T12:55:51.000Z","size":439,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-11-28T13:29:01.875Z","etag":null,"topics":["java","java-sdk","open-policy-agent","policy-as-code","spring-boot","springboot","styra"],"latest_commit_sha":null,"homepage":"https://docs.styra.com/sdk","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/StyraInc.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":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-12T16:00:35.000Z","updated_at":"2024-11-28T12:55:56.000Z","dependencies_parsed_at":"2024-11-18T19:34:13.409Z","dependency_job_id":"472390cc-f269-4a4d-81d2-a422a6bc1e02","html_url":"https://github.com/StyraInc/opa-springboot","commit_stats":null,"previous_names":["styrainc/opa-springboot"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StyraInc%2Fopa-springboot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StyraInc%2Fopa-springboot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StyraInc%2Fopa-springboot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StyraInc%2Fopa-springboot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/StyraInc","download_url":"https://codeload.github.com/StyraInc/opa-springboot/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":232052252,"owners_count":18465724,"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","java-sdk","open-policy-agent","policy-as-code","spring-boot","springboot","styra"],"created_at":"2025-01-01T05:46:07.116Z","updated_at":"2025-09-05T18:31:32.447Z","avatar_url":"https://github.com/StyraInc.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OPA Spring Boot SDK\n\n\u003e [!IMPORTANT]\n\u003e The documentation for this SDK lives at [https://docs.styra.com/sdk](https://docs.styra.com/sdk), with reference documentation available at [https://styrainc.github.io/opa-springboot/javadoc](https://styrainc.github.io/opa-springboot/javadoc)\n\nYou can use the Styra OPA Spring Boot SDK to connect [Open Policy Agent](https://www.openpolicyagent.org/) and [Enterprise OPA](https://www.styra.com/enterprise-opa/) deployments to your [Spring Boot](https://spring.io/projects/spring-boot) applications using the included [AuthorizationManager](https://docs.spring.io/spring-security/reference/servlet/authorization/architecture.html#_the_authorizationmanager) implementation.\n\n\u003e [!IMPORTANT]\n\u003e Would you prefer a plain Java API instead of Spring Boot? Check out the [OPA Java SDK](https://github.com/StyraInc/opa-java).\n\n## SDK Installation\n\nThis package is published on Maven Central as [`com.styra.opa:springboot`](https://central.sonatype.com/artifact/com.styra.opa/springboot). The Maven Central page includes up-to-date instructions to add it as a dependency to your Java project, tailored to a variety of build systems including Maven and Gradle.\n\nIf you wish to build from source and publish the SDK artifact to your local Maven repository (on your filesystem) then use the following command (after cloning the git repo locally):\n\nOn Linux/MacOS:\n\n```shell\n./gradlew publishToMavenLocal -Pskip.signing\n```\n\nOn Windows:\n\n```shell\ngradlew.bat publishToMavenLocal -\"Pskip.signing\"\n```\n\n## SDK Example Usage\n### OPAAuthorizationManager\nUsing `OPAAuthorizationManager`, HTTP requests could be authorized:\n\n```java\nimport com.styra.opa.springboot.OPAAuthorizationManager;\n\n@Configuration\n@EnableWebSecurity\npublic class SecurityConfig {\n\n    @Autowired\n    OPAAuthorizationManager opaAuthorizationManager;\n\n    @Bean\n    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {\n        http.authorizeHttpRequests(authorize -\u003e authorize.anyRequest().access(opaAuthorizationManager));\n        // Other security configs\n        return http.build();\n    }\n}\n```\nAuto-configuration will be done using `OPAAutoConfiguration`. If any customization be needed, custom `OPAClient`\nor `OPAAuthorizationManager` beans could be defined by clients.\n\n### OPAClient\nA custom `OPAClient` bean could be defined to send custom headers to the OPA server, or using custom\n`com.styra.opa.openapi.utils.HTTPClient`, such as:\n\n```java\nimport com.styra.opa.OPAClient;\n\n@Configuration\npublic class OPAConfig {\n\n    @Bean\n    public OPAClient opaClient(OPAProperties opaProperties) {\n        var headers = Map.ofEntries(entry(\"Authorization\", \"Bearer secret\"));\n        return new OPAClient(opaProperties.getUrl(), headers);\n    }\n}\n```\n\n### OPAProperties\nConfiguration properties are defined in `OPAProperties` and can be set\n[externally](https://docs.spring.io/spring-boot/reference/features/external-config.html), e.g. via\n`application.properties`, `application.yaml`, system properties, or environment variables.\n\nExample `application.yaml` to modify properties:\n```yaml\nopa:\n    url: http://localhost:8182 # OPA server URL. Default is \"http://localhost:8181\".\n    path: foo/bar # Policy path in OPA. Default is null.\n    request:\n        resource:\n            type: stomp_endpoint # Type of the request's resource. Default is \"endpoint\".\n        context:\n            type: websocket # Type of the request's context. Default is \"http\".\n        subject:\n            type: oauth2_resource_owner # Type of the request's subject. Default is \"java_authentication\".\n    response:\n        context:\n            reason-key: de # Key to search for decision reasons in the response. Default is \"en\".\n    authorization-event:\n        denied:\n            enabled: false # Whether to publish an AuthorizationDeniedEvent when a request is denied. Default is true.\n        granted:\n            enabled: true # Whether to publish an AuthorizationGrantedEvent when a request is granted. Default is false.\n```\n\n### OPAPathSelector\nBy default, OPAAuthorizationManager does not use any path when calling OPA (evaluating policies). Clients could define\nan `OPAPathSelector` bean, which could select paths based on the `Authentication`, `RequestAuthorizationContext`, or\nopaInput `Map`.\n\nExample `OPAPathSelector` bean:\n```java\n@Configuration\npublic class OPAConfig {\n    @Bean\n    public OPAPathSelector opaPathSelector() {\n        return (authentication, requestAuthorizationContext, opaInput) -\u003e {\n            String httpRequestPath = requestAuthorizationContext.getRequest().getServletPath();\n            if (httpRequestPath.startsWith(\"/foo\")) {\n                return \"foo/main\";\n            } else if (httpRequestPath.startsWith(\"/bar\")) {\n                return \"bar/main\";\n            } else {\n                return \"default/main\";\n            }\n        };\n    }\n}\n```\n\n### OPAInput*Customizers\nOPA `input` is a `Map\u003cString, Object\u003e` which will be sent to the\n[Get a Document (with Input) endpoint](https://www.openpolicyagent.org/docs/latest/rest-api/#get-a-document-with-input)\nas the `input` field in the request body and is accessible in OPA policies as the\n[input variable](https://www.openpolicyagent.org/docs/latest/philosophy/#the-opa-document-model). To enable clients to\ncustomize different parts of `input` (`subject`, `resource`, `action`, and `context`), `OPAInput*Customizer` beans\ncould be defined. After applying `input` customization, `input` will be validated to ensure it at least contains these\nkeys with not-null values:\n- `resource.[type, id]`\n- `action.name`\n- `subject.[type, id]`\n- `context.type`, if `context` exists\n\n#### 1. OPAInputSubjectCustomizer\nClients could define an `OPAInputSubjectCustomizer` bean to customize the `subject` part of the `input`. `subject` map\nmust at least contain `type` and `id` keys with not-null values, though their values could be modified.\n\nExample `OPAInputSubjectCustomizer` bean:\n```java\nimport static com.styra.opa.springboot.input.InputConstants.SUBJECT;\nimport static com.styra.opa.springboot.input.InputConstants.SUBJECT_AUTHORITIES;\nimport static com.styra.opa.springboot.input.InputConstants.SUBJECT_TYPE;\n\n@Configuration\npublic class OPAConfig {\n    @Bean\n    public OPAInputSubjectCustomizer opaInputSubjectCustomizer() {\n        return (authentication, requestAuthorizationContext, subject) -\u003e {\n            var customSubject = new HashMap\u003c\u003e(subject);\n            customSubject.remove(SUBJECT_AUTHORITIES); // Remove an existing attribute.\n            customSubject.put(SUBJECT_TYPE, \"oauth2_resource_owner\"); // Change an existing attribute.\n            customSubject.put(\"subject_key\", \"subject_value\"); // Add a new attribute.\n            return customSubject;\n        };\n    }\n}\n```\n\n#### 2. OPAInputResourceCustomizer\nClients could define an `OPAInputResourceCustomizer` bean to customize the `resource` part of the `input`. `resource`\nmap must at least contain `type` and `id` keys with not-null values, though their values could be modified.\n\nExample `OPAInputResourceCustomizer` bean:\n```java\nimport static com.styra.opa.springboot.input.InputConstants.RESOURCE;\nimport static com.styra.opa.springboot.input.InputConstants.RESOURCE_TYPE;\n\n@Configuration\npublic class OPAConfig {\n    @Bean\n    public OPAInputResourceCustomizer opaInputResourceCustomizer() {\n        return (authentication, requestAuthorizationContext, resource) -\u003e {\n            var customResource = new HashMap\u003c\u003e(resource);\n            customResource.put(RESOURCE_TYPE, \"stomp_endpoint\"); // Change an existing attribute.\n            customResource.put(\"resource_key\", \"resource_value\"); // Add a new attribute.\n            return customResource;\n        };\n    }\n}\n```\n\n#### 3. OPAInputActionCustomizer\nClients could define an `OPAInputActionCustomizer` bean to customize the `action` part of the `input`. `action` map\nmust at least contain `name` key with a not-null value, though its value could be modified.\n\nExample `OPAInputActionCustomizer` bean:\n```java\nimport static com.styra.opa.springboot.input.InputConstants.ACTION;\nimport static com.styra.opa.springboot.input.InputConstants.ACTION_HEADERS;\nimport static com.styra.opa.springboot.input.InputConstants.ACTION_NAME;\n\n@Configuration\npublic class OPAConfig {\n    @Bean\n    public OPAInputActionCustomizer opaInputActionCustomizer() {\n        return (authentication, requestAuthorizationContext, action) -\u003e {\n            var customAction = new HashMap\u003c\u003e(action);\n            customAction.remove(ACTION_HEADERS); // Remove an existing attribute.\n            customAction.put(ACTION_NAME, \"read\"); // Change an existing attribute.\n            customAction.put(\"action_key\", \"action_value\"); // Add a new attribute.\n            return customAction;\n        };\n    }\n}\n```\n\n#### 4. OPAInputContextCustomizer\nClients could define an `OPAInputContextCustomizer` bean to customize the `context` part of the `input`. `context` map\ncould be null; however if it is not-null, it must at least contain `type` key with a not-null value, though its value\ncould be modified.\n\nExample `OPAInputContextCustomizer` bean which makes `context` null (removes it from `input` map):\n```java\nimport static com.styra.opa.springboot.input.InputConstants.CONTEXT;\nimport static com.styra.opa.springboot.input.InputConstants.CONTEXT_TYPE;\n\n@Configuration\npublic class OPAConfig {\n    @Bean\n    public OPAInputContextCustomizer opaInputContextCustomizer() {\n        return (authentication, requestAuthorizationContext, context) -\u003e null;\n    }\n}\n```\n\n### Authorization Events\nSpring-Security supports\n[Authorization Events](https://docs.spring.io/spring-security/reference/servlet/authorization/events.html) which could\nbe used to publish events when a request is authorized or denied. By following the spring-security convention,\n`OPAAuthorizationEventPublisher` publishes `AuthorizationDeniedEvent` when a request is denied, however does not\npublish `AuthorizationGrantedEvent` when a request is granted (since it could be quite noisy). Clients could change\nthis behavior via `opa.authorization-event.denied.enabled` and `opa.authorization-event.granted.enabled` properties.\n\n\u003e [!IMPORTANT]\n\u003e Besides this feature, OPA server can periodically report decision logs to remote HTTP servers, using custom\nplugins, or to the console output; or any combination thereof. The decision logs contain events that describe policy\nqueries. The decision logs is the preferred logging mechanism for large-scale deployments, as it unifies decision logs\nregardless of the client technologies. For more information, see the\n[OPA Decision Logs](https://www.openpolicyagent.org/docs/latest/management-decision-logs/).\n\nEmitted `AuthorizationDeniedEvent` and `AuthorizationGrantedEvent` contain `OPAAuthorizationDecision` which has a\nreference to the corresponding `OPAResponse` and clients could access the response returned from the OPA server. In\norder to listen to these events, clients could annotate a method with `@EventListener` in a bean.\n\nExample listener to receive both denied and granted events:\n```java\nimport org.springframework.context.event.EventListener;\n\n@Component\npublic class OPAAuthorizationEventListener {\n\n    @EventListener\n    public void onDeny(AuthorizationDeniedEvent denied) {\n        // ...\n    }\n\n    @EventListener\n    public void onGrant(AuthorizationGrantedEvent granted) {\n        // ...\n    }\n}\n```\n\n### Handling OPAAccessDeniedException\nWhen a request is denied, `OPAAuthorizationManager` throws an `OPAAccessDeniedException`. Clients could handle this\nexception by implementing `AccessDeniedHandler` or extending `AccessDeniedHandlerImpl`.\n\nExample `AccessDeniedHandler` bean to handle `OPAAccessDeniedException` and generate HTTP responses based on\n[RFC 9457 - Problem Details for HTTP APIs](https://datatracker.ietf.org/doc/html/rfc9457):\n```java\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.styra.opa.springboot.authorization.OPAAccessDeniedException;\nimport org.springframework.security.access.AccessDeniedException;\nimport org.springframework.security.web.access.AccessDeniedHandlerImpl;\n\n@Component\npublic class OPAAccessDeniedHandler extends AccessDeniedHandlerImpl {\n\n    @Autowired\n    private ObjectMapper objectMapper;\n\n    @Override\n    public void handle(HttpServletRequest request, HttpServletResponse response,\n                       AccessDeniedException accessDeniedException) throws IOException, ServletException {\n        if (!(accessDeniedException instanceof OPAAccessDeniedException opaAccessDeniedException)) {\n            super.handle(request, response, accessDeniedException);\n            return;\n        }\n        Map\u003cString, Object\u003e body = new HashMap\u003c\u003e();\n        body.put(\"status\", HttpStatus.FORBIDDEN.value());\n        body.put(\"title\", opaAccessDeniedException.getMessage());\n        var subject = (Map\u003cString, Object\u003e) opaAccessDeniedException.getOpaResponse().getContext().getData().get(SUBJECT);\n        var subjectId = subject.get(SUBJECT_ID);\n        body.put(\"detail\", \"Access denied for subject: \" + subjectId);\n        body.put(\"subject\", subject);\n        response.setStatus(HttpStatus.FORBIDDEN.value());\n        response.setContentType(MediaType.APPLICATION_JSON_VALUE);\n        response.setCharacterEncoding(StandardCharsets.UTF_8.toString());\n        response.getWriter().write(objectMapper.writeValueAsString(body));\n        response.getWriter().flush();\n    }\n}\n```\n\n## Policy Input/Output Schema\n\nDocumentation for the required input and output schema of policies used by the OPA Spring Boot SDK can be found [here](https://docs.styra.com/sdk/springboot/reference/input-output-schema).\n\n## Build Instructions\n\n**To build the SDK**, use `./gradlew build`, the resulting JAR will be placed in `./build/libs/api.jar`.\n\n**To build the documentation** site, including JavaDoc, run `./scripts/build_docs.sh OUTPUT_DIR`. You should replace `OUTPUT_DIR` with a directory on your local system where you would like the generated docs to be placed. You can also preview the documentation site ephemerally using `./scripts/serve_docs.sh`, which will serve the docs on `http://localhost:8000` until you use Ctrl+C to exit the script.\n\n**To run the unit tests**, you can use `./gradlew test`.\n\n**To run the linter**, you can use `./gradlew lint`.\n\n## Community\n\nFor questions, discussions and announcements related to Styra products, services and open source projects, please join\nthe Styra community on [Slack](https://communityinviter.com/apps/styracommunity/signup)!\n\n## Development\n\nFor development docs, see [DEVELOPMENT.md](./DEVELOPMENT.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopen-policy-agent%2Fopa-springboot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopen-policy-agent%2Fopa-springboot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopen-policy-agent%2Fopa-springboot/lists"}