[core] Enable multiple oauth2 flows (#7570)

This commit is contained in:
Lukáš Vasek
2020-10-02 03:26:37 +02:00
committed by GitHub
parent 626481bb07
commit e1fd221898
3 changed files with 100 additions and 23 deletions

View File

@@ -22,7 +22,6 @@ import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.Ticker;
import com.google.common.base.CaseFormat;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.samskivert.mustache.Mustache;
import com.samskivert.mustache.Mustache.Compiler;
import com.samskivert.mustache.Mustache.Lambda;
@@ -4447,26 +4446,17 @@ public class DefaultCodegen implements CodegenConfig {
List<CodegenSecurity> codegenSecurities = new ArrayList<CodegenSecurity>(securitySchemeMap.size());
for (String key : securitySchemeMap.keySet()) {
final SecurityScheme securityScheme = securitySchemeMap.get(key);
CodegenSecurity cs = CodegenModelFactory.newInstance(CodegenModelType.SECURITY);
cs.name = key;
cs.type = securityScheme.getType().toString();
cs.isCode = cs.isPassword = cs.isApplication = cs.isImplicit = false;
cs.isHttpSignature = false;
cs.isBasicBasic = cs.isBasicBearer = false;
cs.scheme = securityScheme.getScheme();
if (securityScheme.getExtensions() != null) {
cs.vendorExtensions.putAll(securityScheme.getExtensions());
}
if (SecurityScheme.Type.APIKEY.equals(securityScheme.getType())) {
final CodegenSecurity cs = defaultCodegenSecurity(key, securityScheme);
cs.isBasic = cs.isOAuth = false;
cs.isApiKey = true;
cs.keyParamName = securityScheme.getName();
cs.isKeyInHeader = securityScheme.getIn() == SecurityScheme.In.HEADER;
cs.isKeyInQuery = securityScheme.getIn() == SecurityScheme.In.QUERY;
cs.isKeyInCookie = securityScheme.getIn() == SecurityScheme.In.COOKIE; //it assumes a validation step prior to generation. (cookie-auth supported from OpenAPI 3.0.0)
codegenSecurities.add(cs);
} else if (SecurityScheme.Type.HTTP.equals(securityScheme.getType())) {
final CodegenSecurity cs = defaultCodegenSecurity(key, securityScheme);
cs.isKeyInHeader = cs.isKeyInQuery = cs.isKeyInCookie = cs.isApiKey = cs.isOAuth = false;
cs.isBasic = true;
if ("basic".equals(securityScheme.getScheme())) {
@@ -4483,35 +4473,41 @@ public class DefaultCodegen implements CodegenConfig {
cs.isHttpSignature = true;
once(LOGGER).warn("Security scheme 'HTTP signature' is a draft IETF RFC and subject to change.");
}
codegenSecurities.add(cs);
} else if (SecurityScheme.Type.OAUTH2.equals(securityScheme.getType())) {
cs.isKeyInHeader = cs.isKeyInQuery = cs.isKeyInCookie = cs.isApiKey = cs.isBasic = false;
cs.isOAuth = true;
final OAuthFlows flows = securityScheme.getFlows();
if (securityScheme.getFlows() == null) {
throw new RuntimeException("missing oauth flow in " + cs.name);
throw new RuntimeException("missing oauth flow in " + key);
}
if (flows.getPassword() != null) {
final CodegenSecurity cs = defaultOauthCodegenSecurity(key, securityScheme);
setOauth2Info(cs, flows.getPassword());
cs.isPassword = true;
cs.flow = "password";
} else if (flows.getImplicit() != null) {
codegenSecurities.add(cs);
}
if (flows.getImplicit() != null) {
final CodegenSecurity cs = defaultOauthCodegenSecurity(key, securityScheme);
setOauth2Info(cs, flows.getImplicit());
cs.isImplicit = true;
cs.flow = "implicit";
} else if (flows.getClientCredentials() != null) {
codegenSecurities.add(cs);
}
if (flows.getClientCredentials() != null) {
final CodegenSecurity cs = defaultOauthCodegenSecurity(key, securityScheme);
setOauth2Info(cs, flows.getClientCredentials());
cs.isApplication = true;
cs.flow = "application";
} else if (flows.getAuthorizationCode() != null) {
codegenSecurities.add(cs);
}
if (flows.getAuthorizationCode() != null) {
final CodegenSecurity cs = defaultOauthCodegenSecurity(key, securityScheme);
setOauth2Info(cs, flows.getAuthorizationCode());
cs.isCode = true;
cs.flow = "accessCode";
} else {
throw new RuntimeException("Could not identify any oauth2 flow in " + cs.name);
codegenSecurities.add(cs);
}
}
codegenSecurities.add(cs);
}
// sort auth methods to maintain the same order
@@ -4531,6 +4527,27 @@ public class DefaultCodegen implements CodegenConfig {
return codegenSecurities;
}
private CodegenSecurity defaultCodegenSecurity(String key, SecurityScheme securityScheme) {
final CodegenSecurity cs = CodegenModelFactory.newInstance(CodegenModelType.SECURITY);
cs.name = key;
cs.type = securityScheme.getType().toString();
cs.isCode = cs.isPassword = cs.isApplication = cs.isImplicit = false;
cs.isHttpSignature = false;
cs.isBasicBasic = cs.isBasicBearer = false;
cs.scheme = securityScheme.getScheme();
if (securityScheme.getExtensions() != null) {
cs.vendorExtensions.putAll(securityScheme.getExtensions());
}
return cs;
}
private CodegenSecurity defaultOauthCodegenSecurity(String key, SecurityScheme securityScheme) {
final CodegenSecurity cs = defaultCodegenSecurity(key, securityScheme);
cs.isKeyInHeader = cs.isKeyInQuery = cs.isKeyInCookie = cs.isApiKey = cs.isBasic = false;
cs.isOAuth = true;
return cs;
}
protected void setReservedWordsLowerCase(List<String> words) {
reservedWords = new HashSet<String>();
for (String word : words) {

View File

@@ -31,6 +31,7 @@ import io.swagger.v3.oas.models.parameters.QueryParameter;
import io.swagger.v3.oas.models.parameters.RequestBody;
import io.swagger.v3.oas.models.responses.ApiResponse;
import io.swagger.v3.oas.models.responses.ApiResponses;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.parser.core.models.ParseOptions;
import org.openapitools.codegen.config.CodegenConfigurator;
@@ -2286,4 +2287,18 @@ public class DefaultCodegenTest {
TestUtils.ensureDoesNotContainsFile(files, output, "src/main/java/org/openapitools/client/model/FreeForm.java");
output.deleteOnExit();
}
@Test
public void testOauthMultipleFlows() {
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue_7193.yaml");
final DefaultCodegen codegen = new DefaultCodegen();
codegen.setOpenAPI(openAPI);
final Map<String, SecurityScheme> securitySchemes = openAPI.getComponents().getSecuritySchemes();
final List<CodegenSecurity> securities = codegen.fromSecurity(securitySchemes);
assertEquals(securities.size(), 2);
final List<String> flows = securities.stream().map(c -> c.flow).collect(Collectors.toList());
assertTrue(flows.containsAll(Arrays.asList("password", "application")));
}
}

View File

@@ -0,0 +1,45 @@
openapi: 3.0.0
info:
title: test api
version: 0.0.1
paths:
/imports:
post:
summary: Creates import
operationId: createImport
responses:
201:
description: created
security:
- oauth_auth:
- import:create
/imports/{importId}/state:
put:
summary: Changes import state
operationId: changeImportState
parameters:
- name: importId
in: path
required: true
schema:
type: string
responses:
200:
description: State changed
security:
- oauht_auth:
- import:process
components:
securitySchemes:
oauth_auth:
type: oauth2
flows:
password:
tokenUrl: "../auth/realms/master/protocol/openid-connect/token"
scopes:
import:create: create import
clientCredentials:
tokenUrl: "../auth/realms/master/protocol/openid-connect/token"
scopes:
import:create: create import
import:process: process import