[spring-boot]: generate PreAuthorize from OpenAPI security scopes#24380
[spring-boot]: generate PreAuthorize from OpenAPI security scopes#24380JFCote wants to merge 5 commits into
Conversation
Add opt-in Spring Boot support to translate OAuth2/OIDC security requirements into @PreAuthorize expressions, preserving OpenAPI AND/OR semantics. Also: enable method security with @EnableMethodSecurity add Spring Security dependency when enabled support configurable authority prefix (SCOPE_ by default) add documentation, tests, and a generated sample
There was a problem hiding this comment.
3 issues found and verified against the latest diff
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="samples/server/others/springboot-pre-authorize/README.md">
<violation number="1" location="samples/server/others/springboot-pre-authorize/README.md:8">
P3: Use "an OpenAPI-enabled" instead of "a OpenAPI-enabled server" for correct grammar before a vowel sound.</violation>
</file>
<file name="modules/openapi-generator/src/main/resources/JavaSpring/api.mustache">
<violation number="1" location="modules/openapi-generator/src/main/resources/JavaSpring/api.mustache:279">
P2: OpenAPI scope names containing Java/SpEL string delimiters generate uncompilable or altered `@PreAuthorize` expressions because this interpolation bypasses Java-string escaping. Escape the generated expression for a Java annotation literal before rendering it.</violation>
</file>
<file name="modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java">
<violation number="1" location="modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java:4079">
P1: The test expects generated file `ApiApi.java` but the OpenAPI spec uses the tag `Overview` which generates `OverviewApi.java`. Verify the expected file name matches the tag-based naming convention or the test will fail with a NullPointerException.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| Map<String, File> files = generator.opts(input).generate().stream() | ||
| .collect(Collectors.toMap(File::getName, Function.identity())); | ||
|
|
||
| JavaFileAssert.assertThat(files.get("ApiApi.java")) |
There was a problem hiding this comment.
P1: The test expects generated file ApiApi.java but the OpenAPI spec uses the tag Overview which generates OverviewApi.java. Verify the expected file name matches the tag-based naming convention or the test will fail with a NullPointerException.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java, line 4079:
<comment>The test expects generated file `ApiApi.java` but the OpenAPI spec uses the tag `Overview` which generates `OverviewApi.java`. Verify the expected file name matches the tag-based naming convention or the test will fail with a NullPointerException.</comment>
<file context>
@@ -4053,6 +4053,76 @@ public void testHasOperationExtraAnnotation_issue12219_array() throws IOExceptio
+ Map<String, File> files = generator.opts(input).generate().stream()
+ .collect(Collectors.toMap(File::getName, Function.identity()));
+
+ JavaFileAssert.assertThat(files.get("ApiApi.java"))
+ .assertMethod("getOverview")
+ .assertMethodAnnotations()
</file context>
| {{{.}}} | ||
| {{/vendorExtensions.x-operation-extra-annotation}} | ||
| {{#vendorExtensions.x-spring-security-pre-authorize}} | ||
| @PreAuthorize("{{{.}}}") |
There was a problem hiding this comment.
P2: OpenAPI scope names containing Java/SpEL string delimiters generate uncompilable or altered @PreAuthorize expressions because this interpolation bypasses Java-string escaping. Escape the generated expression for a Java annotation literal before rendering it.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/JavaSpring/api.mustache, line 279:
<comment>OpenAPI scope names containing Java/SpEL string delimiters generate uncompilable or altered `@PreAuthorize` expressions because this interpolation bypasses Java-string escaping. Escape the generated expression for a Java annotation literal before rendering it.</comment>
<file context>
@@ -272,6 +275,9 @@ public interface {{classname}} {
{{{.}}}
{{/vendorExtensions.x-operation-extra-annotation}}
+ {{#vendorExtensions.x-spring-security-pre-authorize}}
+ @PreAuthorize("{{{.}}}")
+ {{/vendorExtensions.x-spring-security-pre-authorize}}
{{#vendorExtensions.x-sse}}
</file context>
| ## Overview | ||
| This server was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. | ||
| By using the [OpenAPI-Spec](https://openapis.org), you can easily generate a server stub. | ||
| This is an example of building a OpenAPI-enabled server in Java using the SpringBoot framework. |
There was a problem hiding this comment.
P3: Use "an OpenAPI-enabled" instead of "a OpenAPI-enabled server" for correct grammar before a vowel sound.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/server/others/springboot-pre-authorize/README.md, line 8:
<comment>Use "an OpenAPI-enabled" instead of "a OpenAPI-enabled server" for correct grammar before a vowel sound.</comment>
<file context>
@@ -0,0 +1,12 @@
+## Overview
+This server was generated by the [OpenAPI Generator](https://openapi-generator.tech) project.
+By using the [OpenAPI-Spec](https://openapis.org), you can easily generate a server stub.
+This is an example of building a OpenAPI-enabled server in Java using the SpringBoot framework.
+
+
</file context>
There was a problem hiding this comment.
All reported issues were addressed across 11 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
There was a problem hiding this comment.
2 issues found across 7 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/openapi2SpringBoot.mustache">
<violation number="1" location="modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/openapi2SpringBoot.mustache:36">
P1: Reactive generated servers fail to initialize when this option is enabled because WebFlux does not provide the servlet `HttpSecurity` builder required by this bean. Render a `ServerHttpSecurity`/`SecurityWebFilterChain` configuration for `reactive`, or reject this option combination.</violation>
</file>
<file name="samples/server/others/springboot-pre-authorize/src/main/java/org/openapitools/OpenApiGeneratorApplication.java">
<violation number="1" location="samples/server/others/springboot-pre-authorize/src/main/java/org/openapitools/OpenApiGeneratorApplication.java:28">
P2: A separately declared `SecurityFilterChain` can fail to replace this fallback because `@ConditionalOnMissingBean` only sees definitions processed so far in this non-auto-configuration class. When this chain is registered first, its universal matcher can take precedence over the application's OAuth/JWT chain; place the fallback in ordered auto-configuration or omit it from the sample application.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
| {{#useSpringSecurityPreAuthorize}} | ||
| @Bean | ||
| @ConditionalOnMissingBean(SecurityFilterChain.class) | ||
| public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { |
There was a problem hiding this comment.
P1: Reactive generated servers fail to initialize when this option is enabled because WebFlux does not provide the servlet HttpSecurity builder required by this bean. Render a ServerHttpSecurity/SecurityWebFilterChain configuration for reactive, or reject this option combination.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/openapi2SpringBoot.mustache, line 36:
<comment>Reactive generated servers fail to initialize when this option is enabled because WebFlux does not provide the servlet `HttpSecurity` builder required by this bean. Render a `ServerHttpSecurity`/`SecurityWebFilterChain` configuration for `reactive`, or reject this option combination.</comment>
<file context>
@@ -26,6 +30,17 @@ import org.springframework.context.annotation.FullyQualifiedAnnotationBeanNameGe
+{{#useSpringSecurityPreAuthorize}}
+ @Bean
+ @ConditionalOnMissingBean(SecurityFilterChain.class)
+ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+ return http
+ .csrf(AbstractHttpConfigurer::disable)
</file context>
| public class OpenApiGeneratorApplication { | ||
|
|
||
| @Bean | ||
| @ConditionalOnMissingBean(SecurityFilterChain.class) |
There was a problem hiding this comment.
P2: A separately declared SecurityFilterChain can fail to replace this fallback because @ConditionalOnMissingBean only sees definitions processed so far in this non-auto-configuration class. When this chain is registered first, its universal matcher can take precedence over the application's OAuth/JWT chain; place the fallback in ordered auto-configuration or omit it from the sample application.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/server/others/springboot-pre-authorize/src/main/java/org/openapitools/OpenApiGeneratorApplication.java, line 28:
<comment>A separately declared `SecurityFilterChain` can fail to replace this fallback because `@ConditionalOnMissingBean` only sees definitions processed so far in this non-auto-configuration class. When this chain is registered first, its universal matcher can take precedence over the application's OAuth/JWT chain; place the fallback in ordered auto-configuration or omit it from the sample application.</comment>
<file context>
@@ -20,6 +24,15 @@
public class OpenApiGeneratorApplication {
+ @Bean
+ @ConditionalOnMissingBean(SecurityFilterChain.class)
+ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+ return http
</file context>
|
Let me know if there is anything else to fix and I will take care of it. |
Add opt-in Spring Boot support to translate OAuth2/OIDC security requirements
into @PreAuthorize expressions, preserving OpenAPI AND/OR semantics.
@cachescrubber (2022/02) @welshm (2022/02) @MelleD (2022/02) @atextor (2022/02) @manedev79 (2022/02) @javisst (2022/02) @borsch (2022/02) @banlevente (2022/02) @Zomzog (2022/09) @martin-mfg (2023/08) @KannaKim (2026/07)
PR checklist
Commit all changed files.
This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
These must match the expectations made by your contribution.
You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example
./bin/generate-samples.sh bin/configs/java*.IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
Summary by cubic
Adds opt-in generation of Spring Security
@PreAuthorizefrom OpenAPI OAuth2/OIDC scopes for Spring Boot servers. Preserves OpenAPI AND/OR semantics and enables method security with a safe default when enabled.useSpringSecurityPreAuthorize(Spring Boot only; validated).@PreAuthorizewithhasAuthority()per scope; OR across requirements, AND within an entry; empty scopes →isAuthenticated(); handles quote escaping in scope names.springSecurityAuthorityPrefix(defaultSCOPE_).security, falling back to top-levelsecuritywhen missing.@EnableMethodSecurity,@PreAuthorizeimports, and a minimalSecurityFilterChainbean that permits all by default; addsspring-boot-starter-securityto the generatedpom.samples/server/others/springboot-pre-authorizeand configbin/configs/spring-boot-pre-authorize.yaml.Written for commit fd9d7b1. Summary will update on new commits.