Skip to content

Commit 93f6608

Browse files
committed
Add support for normalizing bearerAuth
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 3ab495a commit 93f6608

3 files changed

Lines changed: 90 additions & 2 deletions

File tree

docs/customization.md

Lines changed: 24 additions & 0 deletions
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

Lines changed: 43 additions & 2 deletions
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

Lines changed: 23 additions & 0 deletions
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)