Skip to content

[Java][Spring] Add OAuth2 Preauthorize annotations based on scope #6358

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ee3ec61
preauthorize
nhomble May 18, 2020
c921dff
generate samples for spring
nhomble May 19, 2020
2a73520
doc updates
nhomble May 19, 2020
65f0249
fix tests
nhomble May 20, 2020
74cf997
Merge branch 'master' of https://github.com/OpenAPITools/openapi-gene…
nhomble Jun 16, 2020
ddb8d92
Merge branch 'master' of https://github.com/OpenAPITools/openapi-gene…
nhomble Jun 23, 2020
4ea0b7d
merge
nhomble Jun 24, 2020
e6a4220
samples
nhomble Jun 24, 2020
0d7945b
samples
nhomble Jun 24, 2020
0c7105a
samples
nhomble Jun 25, 2020
9e7342d
samples
nhomble Jun 25, 2020
b3b494f
Merge branch 'master' of https://github.com/OpenAPITools/openapi-gene…
nhomble Jun 29, 2020
a6cbc34
Merge branch 'master' of https://github.com/OpenAPITools/openapi-gene…
nhomble Jun 29, 2020
eaa0ecc
samples
nhomble Jun 29, 2020
b414d60
Merge branch 'master' of https://github.com/OpenAPITools/openapi-gene…
nhomble Jun 29, 2020
2be06bf
Merge branch 'master' of https://github.com/OpenAPITools/openapi-gene…
nhomble Jul 1, 2020
32aee59
Merge branch 'master' of https://github.com/OpenAPITools/openapi-gene…
nhomble Jul 2, 2020
169a09d
migrate checkFileContains to assertFileContains
nhomble Jul 2, 2020
f71c011
Merge remote-tracking branch 'origin/gh-1975-VI' into gh-1975-VI
nhomble Jul 2, 2020
62981f9
fix test
nhomble Jul 2, 2020
152f691
Merge branch 'master' of https://github.com/OpenAPITools/openapi-gene…
nhomble Jul 4, 2020
1ea958f
samples
nhomble Jul 4, 2020
9d75b1a
Merge branch 'gh-1975-VI' of https://github.com/nhomble/openapi-gener…
nhomble Jul 4, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions bin/configs/spring-boot-security-server.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
generatorName: spring
outputDir: samples/server/petstore/spring-security
library: spring-boot
inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml
templateDir: modules/openapi-generator/src/main/resources/JavaSpring
additionalProperties:
useSpringSecurity: true
hideGenerationTimestamp: "true"
1 change: 1 addition & 0 deletions docs/generators/spring.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ sidebar_label: spring
|unhandledException|Declare operation methods to throw a generic exception and allow unhandled exceptions (useful for Spring `@ControllerAdvice` directives).| |false|
|useBeanValidation|Use BeanValidation API annotations| |true|
|useOptional|Use Optional container for optional parameters| |false|
|useSpringSecurity|Use spring-security's @PreAuthorize annotation to invoke authorization rules| |false|
|useTags|use tags for creating interface and controller classnames| |false|
|virtualService|Generates the virtual service. For more details refer - https://github.com/elan-venture/virtualan/wiki| |false|
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1243,7 +1243,7 @@ private List<CodegenSecurity> filterAuthMethods(List<CodegenSecurity> authMethod

for (CodegenSecurity security : authMethods) {
boolean filtered = false;
if (security != null && security.scopes != null) {
if (security != null && security.scopes != null && SecurityScheme.Type.OAUTH2.toString().equals(security.type)) {
for (SecurityRequirement requirement : securities) {
List<String> opScopes = requirement.get(security.name);
if (opScopes != null) {
Expand All @@ -1259,6 +1259,30 @@ private List<CodegenSecurity> filterAuthMethods(List<CodegenSecurity> authMethod
}
}
}
// This is separate than the oauth2 case since bearerAuths aren't declared in the scheme definition. They
// only exist at the api definition level
if (security != null && SecurityScheme.Type.HTTP.toString().equals(security.type)) {
for (SecurityRequirement requirement : securities) {
List<String> opScopes = requirement.get(security.name);
if (opScopes != null) {
CodegenSecurity opSecurity = security.filterByScopeNames(Collections.emptyList());
opSecurity.bearerFormat = security.bearerFormat;
opSecurity.scheme = security.scheme;
Iterator<String> it = opScopes.iterator();
opSecurity.scopes = new ArrayList<>();
while(it.hasNext()){
Map<String, Object> scope = new HashMap<>();
scope.put("scope", it.next());
scope.put("hasMore", it.hasNext()? "true": null);
opSecurity.scopes.add(scope);
}
opSecurity.hasMore = security.hasMore;
result.add(opSecurity);
filtered = true;
break;
}
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @OpenAPITools/generator-core-team for review

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am happy to move this to a separate changeset as well so that this pr is focused on preauthorize being a capability on eligible authMethods and we can consider bearerAuth being another scheme later


// If we didn't get a filtered version, then we can keep the original auth method.
if (!filtered) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public class SpringCodegen extends AbstractJavaCodegen
public static final String HATEOAS = "hateoas";
public static final String RETURN_SUCCESS_CODE = "returnSuccessCode";
public static final String UNHANDLED_EXCEPTION_HANDLING = "unhandledException";
public static final String USE_SPRING_SECURITY = "useSpringSecurity";

public static final String OPEN_BRACE = "{";
public static final String CLOSE_BRACE = "}";
Expand Down Expand Up @@ -98,6 +99,7 @@ public class SpringCodegen extends AbstractJavaCodegen
protected boolean hateoas = false;
protected boolean returnSuccessCode = false;
protected boolean unhandledException = false;
protected boolean useSpringSecurity = false;

public SpringCodegen() {
super();
Expand Down Expand Up @@ -171,6 +173,7 @@ public SpringCodegen() {
cliOptions.add(CliOption.newBoolean(HATEOAS, "Use Spring HATEOAS library to allow adding HATEOAS links", hateoas));
cliOptions.add(CliOption.newBoolean(RETURN_SUCCESS_CODE, "Generated server returns 2xx code", returnSuccessCode));
cliOptions.add(CliOption.newBoolean(UNHANDLED_EXCEPTION_HANDLING, "Declare operation methods to throw a generic exception and allow unhandled exceptions (useful for Spring `@ControllerAdvice` directives).", unhandledException));
cliOptions.add(CliOption.newBoolean(USE_SPRING_SECURITY, "Use spring-security's @PreAuthorize annotation to invoke authorization rules"));

supportedLibraries.put(SPRING_BOOT, "Spring-boot Server application using the SpringFox integration.");
supportedLibraries.put(SPRING_MVC_LIBRARY, "Spring-MVC Server application using the SpringFox integration.");
Expand Down Expand Up @@ -336,6 +339,11 @@ public void processOpts() {
}
additionalProperties.put(UNHANDLED_EXCEPTION_HANDLING, this.isUnhandledException());

if (additionalProperties.containsKey(USE_SPRING_SECURITY)) {
this.setUseSpringSecurity(Boolean.valueOf(additionalProperties.get(USE_SPRING_SECURITY).toString()));
}
writePropertyBack(USE_SPRING_SECURITY, this.useSpringSecurity);

typeMapping.put("file", "Resource");
importMapping.put("Resource", "org.springframework.core.io.Resource");

Expand Down Expand Up @@ -820,6 +828,10 @@ public void setUnhandledException(boolean unhandledException) {
this.unhandledException = unhandledException;
}

public void setUseSpringSecurity(boolean useSpringSecurity) {
this.useSpringSecurity = useSpringSecurity;
}

@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
super.postProcessModelProperty(model, property);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
{{/jdk8-no-delegate}}
import org.springframework.http.ResponseEntity;
{{#useSpringSecurity}}
import org.springframework.security.access.prepost.PreAuthorize;
{{/useSpringSecurity}}
{{#useBeanValidation}}
import org.springframework.validation.annotation.Validated;
{{/useBeanValidation}}
Expand Down Expand Up @@ -123,6 +126,11 @@ public interface {{classname}} {
{{/headerParams}}
})
{{/implicitHeaders}}
{{#hasAuthMethods}}
{{#useSpringSecurity}}
@PreAuthorize("{{#authMethods}}{{#isOAuth}}({{#scopes}}hasAuthority('{{scope}}'){{#hasMore}} and {{/hasMore}}{{/scopes}}){{/isOAuth}}{{#isBasicBearer}}({{#scopes}}hasAuthority('{{scope}}'){{#hasMore}} and {{/hasMore}}{{/scopes}}){{/isBasicBearer}}{{#hasMore}} or {{/hasMore}}{{/authMethods}}")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will basicbearer auth method have scopes?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nevermind.. looks like the PR is adding the capability to do this.

{{/useSpringSecurity}}
{{/hasAuthMethods}}
@RequestMapping(value = "{{{path}}}",{{#singleContentTypes}}{{#hasProduces}}
produces = "{{{vendorExtensions.x-accepts}}}", {{/hasProduces}}{{#hasConsumes}}
consumes = "{{{vendorExtensions.x-contentType}}}",{{/hasConsumes}}{{/singleContentTypes}}{{^singleContentTypes}}{{#hasProduces}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
{{#useSpringfox}}
<springfox-version>2.8.0</springfox-version>
{{/useSpringfox}}
{{#useSpringSecurity}}
<spring-security-version>5.3.0.RELEASE</spring-security-version>
{{/useSpringSecurity}}
</properties>
{{#parentOverridden}}
<parent>
Expand Down Expand Up @@ -122,6 +125,13 @@
<artifactId>jackson-dataformat-yaml</artifactId>
</dependency>
{{/useSpringfox}}
{{#useSpringSecurity}}
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${spring-security-version}</version>
</dependency>
{{/useSpringSecurity}}
{{#withXml}}
<!-- XML processing: Jackson -->
<dependency>
Expand Down
Loading