From 8729ac4166665ae369b7b964b92bbe52fbf5e12d Mon Sep 17 00:00:00 2001 From: Subhan Ashraf <68732277+velaskuez@users.noreply.github.com> Date: Thu, 23 Jul 2026 12:14:05 +0100 Subject: [PATCH] allow missing security schemes --- .../core/compare/SecurityRequirementDiff.java | 15 +++++++++++++-- .../core/compare/SecurityRequirementsDiff.java | 16 +++++++--------- .../core/compare/SecuritySchemeDiff.java | 12 ++++++++++-- .../openapidiff/core/SecurityDiffTest.java | 11 +++++------ 4 files changed, 35 insertions(+), 19 deletions(-) diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/SecurityRequirementDiff.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/SecurityRequirementDiff.java index 76b51a5d..ca36e527 100644 --- a/core/src/main/java/org/openapitools/openapidiff/core/compare/SecurityRequirementDiff.java +++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/SecurityRequirementDiff.java @@ -35,11 +35,22 @@ public static SecurityRequirement getCopy(LinkedHashMap> ri private LinkedHashMap> contains( SecurityRequirement right, String schemeRef) { - SecurityScheme leftSecurityScheme = leftComponents.getSecuritySchemes().get(schemeRef); + Map leftSchemes = + leftComponents != null ? leftComponents.getSecuritySchemes() : null; + Map rightSchemes = + rightComponents != null ? rightComponents.getSecuritySchemes() : null; LinkedHashMap> found = new LinkedHashMap<>(); + if (leftSchemes == null || rightSchemes == null) { + if (right.containsKey(schemeRef)) { + found.put(schemeRef, right.get(schemeRef)); + } + return found; + } + + SecurityScheme leftSecurityScheme = leftSchemes.get(schemeRef); for (Map.Entry> entry : right.entrySet()) { - SecurityScheme rightSecurityScheme = rightComponents.getSecuritySchemes().get(entry.getKey()); + SecurityScheme rightSecurityScheme = rightSchemes.get(entry.getKey()); if (leftSecurityScheme.getType() == rightSecurityScheme.getType()) { switch (leftSecurityScheme.getType()) { case APIKEY: diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/SecurityRequirementsDiff.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/SecurityRequirementsDiff.java index 324bf001..067b5040 100644 --- a/core/src/main/java/org/openapitools/openapidiff/core/compare/SecurityRequirementsDiff.java +++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/SecurityRequirementsDiff.java @@ -52,22 +52,20 @@ public boolean same(SecurityRequirement left, SecurityRequirement right) { private List> getListOfSecuritySchemes( Components components, SecurityRequirement securityRequirement) { + if (components == null) { + throw new IllegalArgumentException("Missing components definition."); + } + Map securitySchemes = components.getSecuritySchemes(); + if (securitySchemes == null) { + return new ArrayList<>(); + } return securityRequirement.keySet().stream() .map( x -> { - if (components == null) { - throw new IllegalArgumentException("Missing securitySchemes component definition."); - } - Map securitySchemes = components.getSecuritySchemes(); - if (securitySchemes == null) { - throw new IllegalArgumentException("Missing securitySchemes component definition."); - } - SecurityScheme result = securitySchemes.get(x); if (result == null) { throw new IllegalArgumentException("Impossible to find security scheme: " + x); } - return result; }) .map(this::getPair) diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/SecuritySchemeDiff.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/SecuritySchemeDiff.java index f68d638d..2297c341 100644 --- a/core/src/main/java/org/openapitools/openapidiff/core/compare/SecuritySchemeDiff.java +++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/SecuritySchemeDiff.java @@ -6,6 +6,7 @@ import io.swagger.v3.oas.models.security.SecurityScheme; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; import org.openapitools.openapidiff.core.model.ChangedSecurityScheme; import org.openapitools.openapidiff.core.model.ChangedSecuritySchemeScopes; @@ -36,8 +37,15 @@ public DeferredChanged diff( String rightSchemeRef, List rightScopes, DiffContext context) { - SecurityScheme leftSecurityScheme = leftComponents.getSecuritySchemes().get(leftSchemeRef); - SecurityScheme rightSecurityScheme = rightComponents.getSecuritySchemes().get(rightSchemeRef); + Map leftSchemes = + leftComponents != null ? leftComponents.getSecuritySchemes() : null; + Map rightSchemes = + rightComponents != null ? rightComponents.getSecuritySchemes() : null; + if (leftSchemes == null || rightSchemes == null) { + return RealizedChanged.empty(); + } + SecurityScheme leftSecurityScheme = leftSchemes.get(leftSchemeRef); + SecurityScheme rightSecurityScheme = rightSchemes.get(rightSchemeRef); DeferredChanged changedSecuritySchemeOpt = cachedDiff( new HashSet<>(), diff --git a/core/src/test/java/org/openapitools/openapidiff/core/SecurityDiffTest.java b/core/src/test/java/org/openapitools/openapidiff/core/SecurityDiffTest.java index 8c830ad5..ce05f1ec 100644 --- a/core/src/test/java/org/openapitools/openapidiff/core/SecurityDiffTest.java +++ b/core/src/test/java/org/openapitools/openapidiff/core/SecurityDiffTest.java @@ -2,6 +2,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged; import io.swagger.v3.oas.models.security.SecurityRequirement; import org.junit.jupiter.api.Test; @@ -90,15 +91,13 @@ public void testWithUnknownSecurityScheme() { assertThrows( IllegalArgumentException.class, () -> OpenApiCompare.fromLocations(OPENAPI_DOC3, OPENAPI_DOC3)); - assertThrows( - IllegalArgumentException.class, - () -> OpenApiCompare.fromLocations(OPENAPI_DOC4, OPENAPI_DOC4)); } @Test public void testMissingSecurityDefinition() { - assertThrows( - IllegalArgumentException.class, - () -> OpenApiCompare.fromLocations(OPENAPI_DOC5, OPENAPI_DOC5)); + // A missing securitySchemes map (DOC4) or an entirely empty components block (DOC5) is valid + // OpenAPI + assertSpecUnchanged(OPENAPI_DOC4, OPENAPI_DOC4); + assertSpecUnchanged(OPENAPI_DOC5, OPENAPI_DOC5); } }