From 65b9a4b2acc2e9aef12e35a4d7e7006826be1831 Mon Sep 17 00:00:00 2001 From: Inf1mum Date: Sat, 7 Nov 2026 20:08:36 +0300 Subject: [PATCH 1/3] Fix #893: render changed security requirements in MarkdownRender MarkdownRender listed changed operations without any detail when the only change was in the security scheme definitions (e.g. OAuth2 flow authorizationUrl/tokenUrl), and the final result still reported a breaking change, which made the output misleading. Add a 'Security Requirements' section to changed operations that renders added/deleted requirements and, for changed ones, the scheme-level changes (type, in, scheme, bearerFormat, openIdConnectUrl, scopes, description) and OAuth flow URL changes (authorizationUrl/tokenUrl/refreshUrl old -> new). The compatibility verdict is untouched: it keeps following the diff model, where OAuth2/OpenID Connect URL changes are configurable via incompatible.security.scheme.oauth2.*.url.changed properties. --- .../core/output/MarkdownRender.java | 132 ++++++++++++++++++ .../core/output/MarkdownRenderTest.java | 48 +++++++ .../src/test/resources/issue-893-oauth-1.yaml | 22 +++ .../src/test/resources/issue-893-oauth-2.yaml | 22 +++ 4 files changed, 224 insertions(+) create mode 100644 core/src/test/resources/issue-893-oauth-1.yaml create mode 100644 core/src/test/resources/issue-893-oauth-2.yaml diff --git a/core/src/main/java/org/openapitools/openapidiff/core/output/MarkdownRender.java b/core/src/main/java/org/openapitools/openapidiff/core/output/MarkdownRender.java index 531fd380..a257d323 100644 --- a/core/src/main/java/org/openapitools/openapidiff/core/output/MarkdownRender.java +++ b/core/src/main/java/org/openapitools/openapidiff/core/output/MarkdownRender.java @@ -11,6 +11,9 @@ import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.responses.ApiResponse; +import io.swagger.v3.oas.models.security.OAuthFlow; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; import java.io.IOException; import java.io.OutputStreamWriter; import java.util.HashSet; @@ -152,9 +155,138 @@ protected void listEndpoints( safelyAppend(outputStreamWriter, titleH5("Return Type:")); safelyAppend(outputStreamWriter, responses(operation.getApiResponses())); } + if (operation.resultSecurityRequirements().isDifferent()) { + safelyAppend(outputStreamWriter, titleH5("Security Requirements:")); + safelyAppend( + outputStreamWriter, securityRequirements(operation.getSecurityRequirements())); + } }); } + protected String securityRequirements(ChangedSecurityRequirements changedSecurityRequirements) { + StringBuilder sb = new StringBuilder("\n"); + if (changedSecurityRequirements.getIncreased() != null) { + changedSecurityRequirements.getIncreased().stream() + .map(item -> itemSecurityRequirement("New security requirement", item)) + .forEach(sb::append); + } + if (changedSecurityRequirements.getMissing() != null) { + changedSecurityRequirements.getMissing().stream() + .map(item -> itemSecurityRequirement("Deleted security requirement", item)) + .forEach(sb::append); + } + changedSecurityRequirements.getChanged().stream() + .map(this::itemSecurityRequirement) + .forEach(sb::append); + return sb.toString(); + } + + protected String itemSecurityRequirement(String title, SecurityRequirement securityRequirement) { + return format("%s: %s\n\n", title, code(securityRequirementName(securityRequirement))); + } + + protected String itemSecurityRequirement(ChangedSecurityRequirement changedSecurityRequirement) { + StringBuilder sb = new StringBuilder(); + SecurityRequirement nameSource = changedSecurityRequirement.getNewSecurityRequirement(); + if (nameSource == null || nameSource.isEmpty()) { + nameSource = changedSecurityRequirement.getOldSecurityRequirement(); + } + sb.append( + format("Changed security requirement: %s\n", code(securityRequirementName(nameSource)))); + changedSecurityRequirement.getChanged().forEach(scheme -> sb.append(securityScheme(scheme))); + return sb.append('\n').toString(); + } + + private String securityRequirementName(SecurityRequirement securityRequirement) { + return securityRequirement == null ? "" : String.join(", ", securityRequirement.keySet()); + } + + protected String securityScheme(ChangedSecurityScheme changedSecurityScheme) { + StringBuilder sb = new StringBuilder(); + SecurityScheme oldScheme = changedSecurityScheme.getOldSecurityScheme(); + SecurityScheme newScheme = changedSecurityScheme.getNewSecurityScheme(); + if (changedSecurityScheme.isChangedType()) { + sb.append( + format( + "%s* Changed security scheme type: `%s` -> `%s`\n", + indent(1), oldScheme.getType(), newScheme.getType())); + } + if (changedSecurityScheme.isChangedIn()) { + sb.append( + format( + "%s* Changed security scheme location: `%s` -> `%s`\n", + indent(1), oldScheme.getIn(), newScheme.getIn())); + } + if (changedSecurityScheme.isChangedScheme()) { + sb.append( + format( + "%s* Changed security scheme: `%s` -> `%s`\n", + indent(1), oldScheme.getScheme(), newScheme.getScheme())); + } + if (changedSecurityScheme.isChangedBearerFormat()) { + sb.append( + format( + "%s* Changed bearer format: `%s` -> `%s`\n", + indent(1), oldScheme.getBearerFormat(), newScheme.getBearerFormat())); + } + if (changedSecurityScheme.isChangedOpenIdConnectUrl()) { + sb.append( + format( + "%s* Changed openIdConnectUrl: %s -> %s\n", + indent(1), + url(oldScheme.getOpenIdConnectUrl()), + url(newScheme.getOpenIdConnectUrl()))); + } + sb.append(listDiff(1, "scope", changedSecurityScheme.getChangedScopes())); + sb.append(metadata(indent(1), "description", changedSecurityScheme.getDescription())); + if (changedSecurityScheme.getOAuthFlows() != null) { + sb.append(oAuthFlows(changedSecurityScheme.getOAuthFlows())); + } + return sb.toString(); + } + + protected String oAuthFlows(ChangedOAuthFlows changedOAuthFlows) { + return oAuthFlow("implicit", changedOAuthFlows.getImplicitOAuthFlow()) + + oAuthFlow("password", changedOAuthFlows.getPasswordOAuthFlow()) + + oAuthFlow("clientCredentials", changedOAuthFlows.getClientCredentialOAuthFlow()) + + oAuthFlow("authorizationCode", changedOAuthFlows.getAuthorizationCodeOAuthFlow()); + } + + protected String oAuthFlow(String flowName, ChangedOAuthFlow changedOAuthFlow) { + if (changedOAuthFlow == null) { + return ""; + } + StringBuilder sb = new StringBuilder(); + OAuthFlow oldFlow = changedOAuthFlow.getOldOAuthFlow(); + OAuthFlow newFlow = changedOAuthFlow.getNewOAuthFlow(); + if (changedOAuthFlow.isAuthorizationUrl()) { + sb.append( + format( + "%s* authorizationUrl: %s -> %s\n", + indent(2), url(oldFlow.getAuthorizationUrl()), url(newFlow.getAuthorizationUrl()))); + } + if (changedOAuthFlow.isTokenUrl()) { + sb.append( + format( + "%s* tokenUrl: %s -> %s\n", + indent(2), url(oldFlow.getTokenUrl()), url(newFlow.getTokenUrl()))); + } + if (changedOAuthFlow.isRefreshUrl()) { + sb.append( + format( + "%s* refreshUrl: %s -> %s\n", + indent(2), url(oldFlow.getRefreshUrl()), url(newFlow.getRefreshUrl()))); + } + if (sb.length() == 0) { + return ""; + } + return format("%s* Changed %s flow:\n", indent(1), flowName) + sb; + } + + private String url(String url) { + return code(StringUtils.defaultString(url)); + } + protected String responses(ChangedApiResponse changedApiResponse) { StringBuilder sb = new StringBuilder("\n"); sb.append(listResponse("New response", changedApiResponse.getIncreased())); diff --git a/core/src/test/java/org/openapitools/openapidiff/core/output/MarkdownRenderTest.java b/core/src/test/java/org/openapitools/openapidiff/core/output/MarkdownRenderTest.java index 59788210..e99e4e71 100644 --- a/core/src/test/java/org/openapitools/openapidiff/core/output/MarkdownRenderTest.java +++ b/core/src/test/java/org/openapitools/openapidiff/core/output/MarkdownRenderTest.java @@ -1,11 +1,14 @@ package org.openapitools.openapidiff.core.output; import static org.assertj.core.api.Assertions.assertThat; +import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SECURITY_SCHEME_OAUTH2_AUTH_URL_CHANGED; +import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SECURITY_SCHEME_OAUTH2_TOKEN_URL_CHANGED; import java.io.ByteArrayOutputStream; import java.io.OutputStreamWriter; import org.junit.jupiter.api.Test; import org.openapitools.openapidiff.core.OpenApiCompare; +import org.openapitools.openapidiff.core.compare.OpenApiDiffOptions; import org.openapitools.openapidiff.core.model.ChangedOpenApi; public class MarkdownRenderTest { @@ -52,4 +55,49 @@ public void issue870_renderDoesNotFailWhenSchemaIsNullButExampleChanged() { render.render(diff, outputStreamWriter); assertThat(outputStream.toString()).isNotBlank(); } + + @Test + public void issue893_renderChangedSecuritySchemeDetailsInMarkdown() { + MarkdownRender render = new MarkdownRender(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); + ChangedOpenApi diff = + OpenApiCompare.fromLocations("issue-893-oauth-1.yaml", "issue-893-oauth-2.yaml"); + render.render(diff, outputStreamWriter); + String output = outputStream.toString(); + assertThat(output).contains("##### `POST` /users"); + assertThat(output).contains("Security Requirements:"); + assertThat(output).contains("Changed security requirement: `OAuth2`"); + assertThat(output).contains("Changed authorizationCode flow:"); + assertThat(output).contains("authorizationUrl: `` -> `some_value`"); + assertThat(output).contains("tokenUrl: `` -> `some_value`"); + // the compatibility status follows the diff model, which marks OAuth2 flow URL + // changes as incompatible unless configured otherwise + assertThat(diff.isIncompatible()).isTrue(); + assertThat(output).contains("API changes broke backward compatibility"); + } + + @Test + public void issue893_securitySchemeUrlChangeIsCompatibleWhenConfigDisabled() { + OpenApiDiffOptions options = + OpenApiDiffOptions.builder() + .configProperty(SECURITY_SCHEME_OAUTH2_AUTH_URL_CHANGED.getPropertyName(), "false") + .configProperty(SECURITY_SCHEME_OAUTH2_TOKEN_URL_CHANGED.getPropertyName(), "false") + .build(); + ChangedOpenApi diff = + OpenApiCompare.fromLocations( + "issue-893-oauth-1.yaml", "issue-893-oauth-2.yaml", null, options); + assertThat(diff.isDifferent()).isTrue(); + assertThat(diff.isCompatible()).isTrue(); + + MarkdownRender render = new MarkdownRender(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); + render.render(diff, outputStreamWriter); + String output = outputStream.toString(); + assertThat(output).contains("Security Requirements:"); + assertThat(output).contains("Changed security requirement: `OAuth2`"); + assertThat(output).contains("authorizationUrl: `` -> `some_value`"); + assertThat(output).contains("API changes are backward compatible"); + } } diff --git a/core/src/test/resources/issue-893-oauth-1.yaml b/core/src/test/resources/issue-893-oauth-1.yaml new file mode 100644 index 00000000..6dde72be --- /dev/null +++ b/core/src/test/resources/issue-893-oauth-1.yaml @@ -0,0 +1,22 @@ +openapi: 3.1.0 +info: + title: Company API + version: V0 +paths: + /users: + post: + operationId: createUser + responses: + '201': + description: Created + security: + - OAuth2: [] +components: + securitySchemes: + OAuth2: + type: oauth2 + flows: + authorizationCode: + authorizationUrl: '' + tokenUrl: '' + scopes: {} diff --git a/core/src/test/resources/issue-893-oauth-2.yaml b/core/src/test/resources/issue-893-oauth-2.yaml new file mode 100644 index 00000000..ba7f439e --- /dev/null +++ b/core/src/test/resources/issue-893-oauth-2.yaml @@ -0,0 +1,22 @@ +openapi: 3.1.0 +info: + title: Company API + version: V0 +paths: + /users: + post: + operationId: createUser + responses: + '201': + description: Created + security: + - OAuth2: [] +components: + securitySchemes: + OAuth2: + type: oauth2 + flows: + authorizationCode: + authorizationUrl: some_value + tokenUrl: some_value + scopes: {} From 713bb72ca1cb7adb0cc9394666c2c0ee019ddbaf Mon Sep 17 00:00:00 2001 From: openapi-diff-agent Date: Sun, 8 Nov 2026 00:44:36 +0300 Subject: [PATCH 2/3] Fix #893: render security requirement scopes and unmatched schemes in Markdown - render each security requirement's scopes (scheme: [scope, ...]) instead of bare scheme names, so OAuth2: [read] is distinguishable from OAuth2: [] - render increased/missing schemes of a changed security requirement (New/Deleted security scheme) in the Markdown details - add a blank line between the changed-requirement heading and the nested scheme bullets so they do not merge into one paragraph - extend issue-893 fixtures with a multi-scheme requirement covering added/deleted requirements, unmatched schemes and changed scopes --- .../core/output/MarkdownRender.java | 23 +++++++++++++++++-- .../core/output/MarkdownRenderTest.java | 22 ++++++++++++++++++ .../src/test/resources/issue-893-oauth-1.yaml | 17 ++++++++++++++ .../src/test/resources/issue-893-oauth-2.yaml | 17 ++++++++++++++ 4 files changed, 77 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/openapitools/openapidiff/core/output/MarkdownRender.java b/core/src/main/java/org/openapitools/openapidiff/core/output/MarkdownRender.java index a257d323..5b62d86b 100644 --- a/core/src/main/java/org/openapitools/openapidiff/core/output/MarkdownRender.java +++ b/core/src/main/java/org/openapitools/openapidiff/core/output/MarkdownRender.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.openapitools.openapidiff.core.exception.RendererException; import org.openapitools.openapidiff.core.model.*; @@ -182,7 +183,7 @@ protected String securityRequirements(ChangedSecurityRequirements changedSecurit } protected String itemSecurityRequirement(String title, SecurityRequirement securityRequirement) { - return format("%s: %s\n\n", title, code(securityRequirementName(securityRequirement))); + return format("%s: %s\n\n", title, code(securityRequirementWithScopes(securityRequirement))); } protected String itemSecurityRequirement(ChangedSecurityRequirement changedSecurityRequirement) { @@ -192,11 +193,29 @@ protected String itemSecurityRequirement(ChangedSecurityRequirement changedSecur nameSource = changedSecurityRequirement.getOldSecurityRequirement(); } sb.append( - format("Changed security requirement: %s\n", code(securityRequirementName(nameSource)))); + format("Changed security requirement: %s\n\n", code(securityRequirementName(nameSource)))); + if (changedSecurityRequirement.getIncreased() != null) { + sb.append( + itemSecurityRequirement( + "New security scheme", changedSecurityRequirement.getIncreased())); + } + if (changedSecurityRequirement.getMissing() != null) { + sb.append( + itemSecurityRequirement( + "Deleted security scheme", changedSecurityRequirement.getMissing())); + } changedSecurityRequirement.getChanged().forEach(scheme -> sb.append(securityScheme(scheme))); return sb.append('\n').toString(); } + private String securityRequirementWithScopes(SecurityRequirement securityRequirement) { + return securityRequirement == null + ? "" + : securityRequirement.entrySet().stream() + .map(entry -> format("%s: [%s]", entry.getKey(), String.join(", ", entry.getValue()))) + .collect(Collectors.joining(", ")); + } + private String securityRequirementName(SecurityRequirement securityRequirement) { return securityRequirement == null ? "" : String.join(", ", securityRequirement.keySet()); } diff --git a/core/src/test/java/org/openapitools/openapidiff/core/output/MarkdownRenderTest.java b/core/src/test/java/org/openapitools/openapidiff/core/output/MarkdownRenderTest.java index e99e4e71..0fb59cbe 100644 --- a/core/src/test/java/org/openapitools/openapidiff/core/output/MarkdownRenderTest.java +++ b/core/src/test/java/org/openapitools/openapidiff/core/output/MarkdownRenderTest.java @@ -1,8 +1,11 @@ package org.openapitools.openapidiff.core.output; import static org.assertj.core.api.Assertions.assertThat; +import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SECURITY_REQUIREMENTS_DECREASED; +import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SECURITY_REQUIREMENT_SCHEMES_INCREASED; import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SECURITY_SCHEME_OAUTH2_AUTH_URL_CHANGED; import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SECURITY_SCHEME_OAUTH2_TOKEN_URL_CHANGED; +import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SECURITY_SCHEME_SCOPES_INCREASED; import java.io.ByteArrayOutputStream; import java.io.OutputStreamWriter; @@ -68,9 +71,21 @@ public void issue893_renderChangedSecuritySchemeDetailsInMarkdown() { assertThat(output).contains("##### `POST` /users"); assertThat(output).contains("Security Requirements:"); assertThat(output).contains("Changed security requirement: `OAuth2`"); + // a blank line separates the heading from the nested scheme bullets + assertThat(output).contains("Changed security requirement: `OAuth2`\n\n"); assertThat(output).contains("Changed authorizationCode flow:"); assertThat(output).contains("authorizationUrl: `` -> `some_value`"); assertThat(output).contains("tokenUrl: `` -> `some_value`"); + // added and deleted security requirements are rendered with their scopes + assertThat(output).contains("##### `GET` /orders"); + assertThat(output).contains("New security requirement: `OpenIdConnect: [openid, profile]`"); + assertThat(output).contains("Deleted security requirement: `BasicAuth: [user]`"); + // schemes added to or removed from a changed requirement are rendered with their scopes + assertThat(output).contains("Changed security requirement: `OAuth2, NewApiKey`"); + assertThat(output).contains("New security scheme: `NewApiKey: [admin]`"); + assertThat(output).contains("Deleted security scheme: `OldApiKey: []`"); + assertThat(output).contains("Added scope value:"); + assertThat(output).contains("* `write`"); // the compatibility status follows the diff model, which marks OAuth2 flow URL // changes as incompatible unless configured otherwise assertThat(diff.isIncompatible()).isTrue(); @@ -83,6 +98,9 @@ public void issue893_securitySchemeUrlChangeIsCompatibleWhenConfigDisabled() { OpenApiDiffOptions.builder() .configProperty(SECURITY_SCHEME_OAUTH2_AUTH_URL_CHANGED.getPropertyName(), "false") .configProperty(SECURITY_SCHEME_OAUTH2_TOKEN_URL_CHANGED.getPropertyName(), "false") + .configProperty(SECURITY_REQUIREMENTS_DECREASED.getPropertyName(), "false") + .configProperty(SECURITY_REQUIREMENT_SCHEMES_INCREASED.getPropertyName(), "false") + .configProperty(SECURITY_SCHEME_SCOPES_INCREASED.getPropertyName(), "false") .build(); ChangedOpenApi diff = OpenApiCompare.fromLocations( @@ -98,6 +116,10 @@ public void issue893_securitySchemeUrlChangeIsCompatibleWhenConfigDisabled() { assertThat(output).contains("Security Requirements:"); assertThat(output).contains("Changed security requirement: `OAuth2`"); assertThat(output).contains("authorizationUrl: `` -> `some_value`"); + assertThat(output).contains("New security requirement: `OpenIdConnect: [openid, profile]`"); + assertThat(output).contains("Deleted security requirement: `BasicAuth: [user]`"); + assertThat(output).contains("New security scheme: `NewApiKey: [admin]`"); + assertThat(output).contains("Deleted security scheme: `OldApiKey: []`"); assertThat(output).contains("API changes are backward compatible"); } } diff --git a/core/src/test/resources/issue-893-oauth-1.yaml b/core/src/test/resources/issue-893-oauth-1.yaml index 6dde72be..58d91341 100644 --- a/core/src/test/resources/issue-893-oauth-1.yaml +++ b/core/src/test/resources/issue-893-oauth-1.yaml @@ -11,6 +11,16 @@ paths: description: Created security: - OAuth2: [] + /orders: + get: + operationId: listOrders + responses: + '200': + description: OK + security: + - OAuth2: [read] + OldApiKey: [] + - BasicAuth: [user] components: securitySchemes: OAuth2: @@ -20,3 +30,10 @@ components: authorizationUrl: '' tokenUrl: '' scopes: {} + OldApiKey: + type: apiKey + in: header + name: X-Old-Key + BasicAuth: + type: http + scheme: basic diff --git a/core/src/test/resources/issue-893-oauth-2.yaml b/core/src/test/resources/issue-893-oauth-2.yaml index ba7f439e..0350d0cb 100644 --- a/core/src/test/resources/issue-893-oauth-2.yaml +++ b/core/src/test/resources/issue-893-oauth-2.yaml @@ -11,6 +11,16 @@ paths: description: Created security: - OAuth2: [] + /orders: + get: + operationId: listOrders + responses: + '200': + description: OK + security: + - OAuth2: [read, write] + NewApiKey: [admin] + - OpenIdConnect: [openid, profile] components: securitySchemes: OAuth2: @@ -20,3 +30,10 @@ components: authorizationUrl: some_value tokenUrl: some_value scopes: {} + NewApiKey: + type: apiKey + in: header + name: X-New-Key + OpenIdConnect: + type: openIdConnect + openIdConnectUrl: https://example.com/.well-known/openid-configuration From 113fe7fb7fd2a33b26f334e508af4ed80d86cb65 Mon Sep 17 00:00:00 2001 From: Inf1mum Date: Mon, 9 Nov 2026 20:57:02 +0300 Subject: [PATCH 3/3] test: make issue-893 security fixtures spec-conformant Per the OpenAPI security-requirement rules only oauth2 and openIdConnect schemes may list scope names, so the HTTP basic requirement now uses an empty array (BasicAuth: []) and the apiKey requirement likewise (NewApiKey: []). The OAuth2 authorizationCode flow declares the read and write scopes its requirements reference, keeping named-scope rendering covered. Expected Markdown assertions updated to the corrected fixtures. The diff model already treats increased OAuth2 scopes as backward incompatible by default (incompatible.security.scheme.scopes.increased), so the compatibility assertions follow the model unchanged. --- .../openapidiff/core/output/MarkdownRenderTest.java | 10 +++++----- core/src/test/resources/issue-893-oauth-1.yaml | 5 +++-- core/src/test/resources/issue-893-oauth-2.yaml | 6 ++++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/core/src/test/java/org/openapitools/openapidiff/core/output/MarkdownRenderTest.java b/core/src/test/java/org/openapitools/openapidiff/core/output/MarkdownRenderTest.java index 0fb59cbe..9a150bed 100644 --- a/core/src/test/java/org/openapitools/openapidiff/core/output/MarkdownRenderTest.java +++ b/core/src/test/java/org/openapitools/openapidiff/core/output/MarkdownRenderTest.java @@ -79,15 +79,15 @@ public void issue893_renderChangedSecuritySchemeDetailsInMarkdown() { // added and deleted security requirements are rendered with their scopes assertThat(output).contains("##### `GET` /orders"); assertThat(output).contains("New security requirement: `OpenIdConnect: [openid, profile]`"); - assertThat(output).contains("Deleted security requirement: `BasicAuth: [user]`"); + assertThat(output).contains("Deleted security requirement: `BasicAuth: []`"); // schemes added to or removed from a changed requirement are rendered with their scopes assertThat(output).contains("Changed security requirement: `OAuth2, NewApiKey`"); - assertThat(output).contains("New security scheme: `NewApiKey: [admin]`"); + assertThat(output).contains("New security scheme: `NewApiKey: []`"); assertThat(output).contains("Deleted security scheme: `OldApiKey: []`"); assertThat(output).contains("Added scope value:"); assertThat(output).contains("* `write`"); // the compatibility status follows the diff model, which marks OAuth2 flow URL - // changes as incompatible unless configured otherwise + // changes and increased OAuth2 scopes as incompatible unless configured otherwise assertThat(diff.isIncompatible()).isTrue(); assertThat(output).contains("API changes broke backward compatibility"); } @@ -117,8 +117,8 @@ public void issue893_securitySchemeUrlChangeIsCompatibleWhenConfigDisabled() { assertThat(output).contains("Changed security requirement: `OAuth2`"); assertThat(output).contains("authorizationUrl: `` -> `some_value`"); assertThat(output).contains("New security requirement: `OpenIdConnect: [openid, profile]`"); - assertThat(output).contains("Deleted security requirement: `BasicAuth: [user]`"); - assertThat(output).contains("New security scheme: `NewApiKey: [admin]`"); + assertThat(output).contains("Deleted security requirement: `BasicAuth: []`"); + assertThat(output).contains("New security scheme: `NewApiKey: []`"); assertThat(output).contains("Deleted security scheme: `OldApiKey: []`"); assertThat(output).contains("API changes are backward compatible"); } diff --git a/core/src/test/resources/issue-893-oauth-1.yaml b/core/src/test/resources/issue-893-oauth-1.yaml index 58d91341..b9f9c10b 100644 --- a/core/src/test/resources/issue-893-oauth-1.yaml +++ b/core/src/test/resources/issue-893-oauth-1.yaml @@ -20,7 +20,7 @@ paths: security: - OAuth2: [read] OldApiKey: [] - - BasicAuth: [user] + - BasicAuth: [] components: securitySchemes: OAuth2: @@ -29,7 +29,8 @@ components: authorizationCode: authorizationUrl: '' tokenUrl: '' - scopes: {} + scopes: + read: Read access OldApiKey: type: apiKey in: header diff --git a/core/src/test/resources/issue-893-oauth-2.yaml b/core/src/test/resources/issue-893-oauth-2.yaml index 0350d0cb..7d6a6494 100644 --- a/core/src/test/resources/issue-893-oauth-2.yaml +++ b/core/src/test/resources/issue-893-oauth-2.yaml @@ -19,7 +19,7 @@ paths: description: OK security: - OAuth2: [read, write] - NewApiKey: [admin] + NewApiKey: [] - OpenIdConnect: [openid, profile] components: securitySchemes: @@ -29,7 +29,9 @@ components: authorizationCode: authorizationUrl: some_value tokenUrl: some_value - scopes: {} + scopes: + read: Read access + write: Write access NewApiKey: type: apiKey in: header