Skip to content

Commit cd2fbd6

Browse files
authored
Add support for normalizing bearerAuth (#20860)
The openapi 2.0 spec did not support bearer authentication but it was added in openapi 3.0. In order to support client generation that includes support for bearerAuth, this change adds a new feature to the OpenapiNormalizer so that it can be configured to look for a specific securityDefinition name and convert it to bearerAuth.
1 parent 550e317 commit cd2fbd6

File tree

3 files changed

+90
-2
lines changed

3 files changed

+90
-2
lines changed

docs/customization.md

+24
Original file line numberDiff line numberDiff line change
@@ -646,3 +646,27 @@ Example:
646646
```
647647
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_1/java/petstore.yaml -o /tmp/java-okhttp/ --openapi-normalizer FIX_DUPLICATED_OPERATIONID=true
648648
```
649+
650+
- `SET_BEARER_AUTH_FOR_NAME`: When set to the name of an openapi 2.0 securityDefinition, that securityDefinition will be converted to the openapi 3.0 bearerAuth securityScheme.
651+
652+
Example:
653+
```
654+
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/2_0/globalSecurity.json -o /tmp/java-okhttp/ --openapi-normalizer SET_BEARER_AUTH_FOR_NAME=api_key
655+
```
656+
Transforms this securityDefinition:
657+
```
658+
"securityDefinitions": {
659+
"api_key": {
660+
"type": "apiKey",
661+
"name": "api_key",
662+
"in": "header"
663+
},
664+
},
665+
```
666+
Into this securityScheme:
667+
```
668+
securitySchemes:
669+
api_key:
670+
scheme: bearer
671+
type: http
672+
```

modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java

+43-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import io.swagger.v3.oas.models.parameters.RequestBody;
2727
import io.swagger.v3.oas.models.responses.ApiResponse;
2828
import io.swagger.v3.oas.models.responses.ApiResponses;
29+
import io.swagger.v3.oas.models.security.SecurityScheme;
2930
import org.apache.commons.lang3.StringUtils;
3031
import org.openapitools.codegen.utils.ModelUtils;
3132
import org.slf4j.Logger;
@@ -101,6 +102,10 @@ public class OpenAPINormalizer {
101102
String fixDuplicatedOperationId;
102103
HashSet<String> operationIdSet = new HashSet<>();
103104

105+
// when set to true, if a securityScheme is found with the specified name, it will be converted to bearerAuth
106+
final String SET_BEARER_AUTH_FOR_NAME = "SET_BEARER_AUTH_FOR_NAME";
107+
String bearerAuthSecuritySchemeName;
108+
104109
// when set to true, auto fix integer with maximum value 4294967295 (2^32-1) or long with 18446744073709551615 (2^64-1)
105110
// by adding x-unsigned to the schema
106111
final String ADD_UNSIGNED_TO_INTEGER_WITH_INVALID_MAX_VALUE = "ADD_UNSIGNED_TO_INTEGER_WITH_INVALID_MAX_VALUE";
@@ -167,6 +172,7 @@ public OpenAPINormalizer(OpenAPI openAPI, Map<String, String> inputRules) {
167172
ruleNames.add(SET_TAGS_TO_OPERATIONID);
168173
ruleNames.add(SET_TAGS_TO_VENDOR_EXTENSION);
169174
ruleNames.add(FIX_DUPLICATED_OPERATIONID);
175+
ruleNames.add(SET_BEARER_AUTH_FOR_NAME);
170176
ruleNames.add(ADD_UNSIGNED_TO_INTEGER_WITH_INVALID_MAX_VALUE);
171177
ruleNames.add(REFACTOR_ALLOF_WITH_PROPERTIES_ONLY);
172178
ruleNames.add(NORMALIZE_31SPEC);
@@ -301,6 +307,11 @@ public void processRules(Map<String, String> inputRules) {
301307
LOGGER.error("SET_PRIMITIVE_TYPES_TO_NULLABLE rule must be in the form of `string|integer|number|boolean`, e.g. `string`, `integer|number`: {}", inputRules.get(SET_PRIMITIVE_TYPES_TO_NULLABLE));
302308
}
303309
}
310+
311+
bearerAuthSecuritySchemeName = inputRules.get(SET_BEARER_AUTH_FOR_NAME);
312+
if (bearerAuthSecuritySchemeName != null) {
313+
rules.put(SET_BEARER_AUTH_FOR_NAME, true);
314+
}
304315
}
305316

306317
/**
@@ -322,6 +333,7 @@ void normalize() {
322333

323334
normalizeInfo();
324335
normalizePaths();
336+
normalizeComponentsSecuritySchemes();
325337
normalizeComponentsSchemas();
326338
normalizeComponentsResponses();
327339
}
@@ -547,6 +559,36 @@ private void normalizeHeaders(Map<String, Header> headers) {
547559
}
548560
}
549561

562+
/**
563+
* Normalizes securitySchemes in components
564+
*/
565+
private void normalizeComponentsSecuritySchemes() {
566+
if (StringUtils.isEmpty(bearerAuthSecuritySchemeName)) {
567+
return;
568+
}
569+
570+
Map<String, SecurityScheme> schemes = openAPI.getComponents().getSecuritySchemes();
571+
if (schemes == null) {
572+
return;
573+
}
574+
575+
for (String schemeKey : schemes.keySet()) {
576+
if (schemeKey.equals(bearerAuthSecuritySchemeName)) {
577+
SecurityScheme scheme = schemes.get(schemeKey);
578+
scheme.setType(SecurityScheme.Type.HTTP);
579+
scheme.setScheme("bearer");
580+
scheme.setIn(null);
581+
scheme.setName(null);
582+
scheme.setBearerFormat(null);
583+
scheme.setFlows(null);
584+
scheme.setOpenIdConnectUrl(null);
585+
scheme.setExtensions(null);
586+
scheme.set$ref(null);
587+
schemes.put(schemeKey, scheme);
588+
}
589+
}
590+
}
591+
550592
/**
551593
* Normalizes schemas in components
552594
*/
@@ -560,7 +602,7 @@ private void normalizeComponentsSchemas() {
560602
for (String schemaName : schemaNames) {
561603
Schema schema = schemas.get(schemaName);
562604
if (schema == null) {
563-
LOGGER.warn("{} not fount found in openapi/components/schemas.", schemaName);
605+
LOGGER.warn("{} not found in openapi/components/schemas.", schemaName);
564606
} else {
565607
// remove x-internal if needed
566608
if (schema.getExtensions() != null && getRule(REMOVE_X_INTERNAL)) {
@@ -1053,7 +1095,6 @@ private void processFixDuplicatedOperationId(Operation operation) {
10531095
}
10541096
}
10551097

1056-
10571098
/**
10581099
* If the schema contains anyOf/oneOf and properties, remove oneOf/anyOf as these serve as rules to
10591100
* ensure inter-dependency between properties. It's a workaround as such validation is not supported at the moment.

modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java

+23
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import io.swagger.v3.oas.models.PathItem;
2121
import io.swagger.v3.oas.models.media.*;
2222
import io.swagger.v3.oas.models.responses.ApiResponse;
23+
import io.swagger.v3.oas.models.security.SecurityScheme;
2324
import org.openapitools.codegen.utils.ModelUtils;
2425
import org.testng.annotations.Test;
2526

@@ -942,4 +943,26 @@ public void testOpenAPINormalizerComponentsResponses31Spec() {
942943
assertEquals(((Schema) apiResponse2.getContent().get("application/json").getSchema().getProperties().get("uuid")).getType(), "integer");
943944
assertEquals(((Schema) apiResponse2.getContent().get("application/json").getSchema().getProperties().get("label")).getType(), "string");
944945
}
946+
947+
@Test
948+
public void testOpenAPINormalizerBearerAuthSpec() {
949+
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/2_0/globalSecurity.json");
950+
SecurityScheme scheme = openAPI.getComponents().getSecuritySchemes().get("api_key");
951+
assertEquals(scheme.getType(), SecurityScheme.Type.APIKEY);
952+
assertEquals(scheme.getScheme(), null);
953+
assertEquals(scheme.getName(), "api_key");
954+
assertEquals(scheme.getIn(), SecurityScheme.In.HEADER);
955+
956+
Map<String, String> inputRules = Map.of(
957+
"SET_BEARER_AUTH_FOR_NAME", "api_key"
958+
);
959+
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, inputRules);
960+
openAPINormalizer.normalize();
961+
962+
SecurityScheme scheme2 = openAPI.getComponents().getSecuritySchemes().get("api_key");
963+
assertEquals(scheme.getType(), SecurityScheme.Type.HTTP);
964+
assertEquals(scheme.getScheme(), "bearer");
965+
assertEquals(scheme.getName(), null);
966+
assertEquals(scheme.getIn(), null);
967+
}
945968
}

0 commit comments

Comments
 (0)