diff --git a/.github/workflows/auto-merge-dependabot.yml b/.github/workflows/auto-merge-dependabot.yml
index ba2243c97..62a99a480 100644
--- a/.github/workflows/auto-merge-dependabot.yml
+++ b/.github/workflows/auto-merge-dependabot.yml
@@ -19,7 +19,7 @@ jobs:
steps:
- name: Dependabot metadata
id: metadata
- uses: dependabot/fetch-metadata@v2.5.0
+ uses: dependabot/fetch-metadata@v3.0.0
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index bf0d03617..3549461d9 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "3.5.0"
+ ".": "3.5.1"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e0cc37e18..265529627 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
# Changelog
+## [3.5.1](https://github.com/microsoft/OpenAPI.NET/compare/v3.5.0...v3.5.1) (2026-03-31)
+
+
+### Bug Fixes
+
+* security scheme references serialization ([a5acb89](https://github.com/microsoft/OpenAPI.NET/commit/a5acb896cb46a58702c07bc742b5e114ba90f95a))
+
## [3.5.0](https://github.com/microsoft/OpenAPI.NET/compare/v3.4.0...v3.5.0) (2026-03-20)
diff --git a/Directory.Build.props b/Directory.Build.props
index 034c59b03..410c635e0 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -12,7 +12,7 @@
https://github.com/Microsoft/OpenAPI.NET
© Microsoft Corporation. All rights reserved.
OpenAPI .NET
- 3.5.0
+ 3.5.1
diff --git a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs
index bb4bc58d9..6d2282b32 100644
--- a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs
+++ b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs
@@ -5,7 +5,6 @@
using System.Text;
using System.Text.RegularExpressions;
using Humanizer;
-using Humanizer.Inflections;
using Microsoft.OpenApi.Hidi.Extensions;
namespace Microsoft.OpenApi.Hidi.Formatters
diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj
index 3352b5a21..d28fb038a 100644
--- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj
+++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj
@@ -28,7 +28,7 @@
-
+
diff --git a/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs b/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs
index 4a912c0de..766b73f0d 100644
--- a/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs
+++ b/src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs
@@ -79,11 +79,7 @@ private void SerializeInternal(IOpenApiWriter writer, Action p.Key?.Target is not null))
+ foreach (var securitySchemeAndScopesValuePair in this.Where(static p => CanSerializeSecurityScheme(p.Key)))
{
var securityScheme = securitySchemeAndScopesValuePair.Key;
var scopes = securitySchemeAndScopesValuePair.Value;
@@ -103,6 +99,25 @@ private void SerializeInternal(IOpenApiWriter writer, Action
/// Serialize to Open Api v2.0
///
diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs
index 1acd8ce8c..7a47b8597 100644
--- a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs
+++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs
@@ -9,6 +9,7 @@
using System.IO;
using System.Linq;
using System.Net.Http;
+using System.Text.Json.Nodes;
using System.Threading.Tasks;
using VerifyXunit;
using Xunit;
@@ -2387,6 +2388,56 @@ public async Task SerializeDocumentWithSelfPropertyAsV32Works()
Assert.Equal(expected.MakeLineBreaksEnvironmentNeutral(), actual.MakeLineBreaksEnvironmentNeutral());
}
+ [Theory]
+ [InlineData(OpenApiSpecVersion.OpenApi3_0)]
+ [InlineData(OpenApiSpecVersion.OpenApi3_1)]
+ [InlineData(OpenApiSpecVersion.OpenApi3_2)]
+ public async Task SerializeDocumentWithSecurityRequirementAsJsonWorks(OpenApiSpecVersion openApiSpecVersion)
+ {
+ // Arrange
+ var doc = new OpenApiDocument
+ {
+ Info = new OpenApiInfo { Title = "Test", Version = "1.0" },
+ Components = new OpenApiComponents
+ {
+ SecuritySchemes = new Dictionary(StringComparer.Ordinal)
+ {
+ ["Bearer"] = new OpenApiSecurityScheme
+ {
+ Type = SecuritySchemeType.Http,
+ Scheme = "Bearer",
+ BearerFormat = "JWT",
+ },
+ },
+ },
+ };
+
+ doc.Security =
+ [
+ new OpenApiSecurityRequirement
+ {
+ { new OpenApiSecuritySchemeReference("Bearer", doc), [] },
+ },
+ ];
+
+ var expected =
+ """
+ [
+ {
+ "Bearer": []
+ }
+ ]
+ """;
+
+ // Act
+ var actual = await doc.SerializeAsJsonAsync(openApiSpecVersion);
+
+ // Assert
+ var actualSecurity = JsonNode.Parse(actual)?["security"];
+ Assert.NotNull(actualSecurity);
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), actualSecurity));
+ }
+
[Fact]
public async Task SerializeDocumentWithSelfPropertyAsV31WritesAsExtension()
{
diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSecurityRequirementTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSecurityRequirementTests.cs
index 4ae9aedfd..29f5af3c6 100644
--- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSecurityRequirementTests.cs
+++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSecurityRequirementTests.cs
@@ -130,35 +130,10 @@ public async Task SerializeSecurityRequirementAsV3JsonWorksAsync(bool produceTer
await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput);
}
- [Fact]
- public async Task SerializeSecurityRequirementWithReferencedSecuritySchemeAsV3JsonWorks()
- {
- // Arrange
- var expected =
- """
- {
- "scheme1": [
- "scope1",
- "scope2",
- "scope3"
- ],
- "scheme2": [
- "scope4",
- "scope5"
- ],
- "scheme3": [ ]
- }
- """;
-
- // Act
- var actual = await SecurityRequirementWithReferencedSecurityScheme.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
-
- // Assert
- Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual)));
- }
-
- [Fact]
- public async Task SerializeSecurityRequirementWithReferencedSecuritySchemeAsV2JsonWorks()
+ [Theory]
+ [InlineData(OpenApiSpecVersion.OpenApi3_0)]
+ [InlineData(OpenApiSpecVersion.OpenApi2_0)]
+ public async Task SerializeSecurityRequirementWithReferencedSecuritySchemeAsJsonWorks(OpenApiSpecVersion openApiSpecVersion)
{
// Arrange
var expected =
@@ -178,37 +153,16 @@ public async Task SerializeSecurityRequirementWithReferencedSecuritySchemeAsV2Js
""";
// Act
- var actual = await SecurityRequirementWithReferencedSecurityScheme.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0);
+ var actual = await SecurityRequirementWithReferencedSecurityScheme.SerializeAsJsonAsync(openApiSpecVersion);
// Assert
Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual)));
}
- [Fact]
- public async Task SerializeSecurityRequirementWithUnreferencedSecuritySchemeAsV3JsonShouldSkipUnserializableKeyValuePair()
- {
- // Arrange
- var expected =
- """
- {
- "scheme1": [
- "scope1",
- "scope2",
- "scope3"
- ],
- "scheme3": [ ]
- }
- """;
-
- // Act
- var actual = await SecurityRequirementWithUnreferencedSecurityScheme.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
-
- // Assert
- Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual)));
- }
-
- [Fact]
- public async Task SerializeSecurityRequirementWithUnreferencedSecuritySchemeAsV2JsonShouldSkipUnserializableKeyValuePair()
+ [Theory]
+ [InlineData(OpenApiSpecVersion.OpenApi3_0)]
+ [InlineData(OpenApiSpecVersion.OpenApi2_0)]
+ public async Task SerializeSecurityRequirementWithUnreferencedSecuritySchemeAsJsonShouldSkipUnserializableKeyValuePair(OpenApiSpecVersion openApiSpecVersion)
{
// Arrange
var expected =
@@ -224,8 +178,7 @@ public async Task SerializeSecurityRequirementWithUnreferencedSecuritySchemeAsV2
""";
// Act
- var actual =
- await SecurityRequirementWithUnreferencedSecurityScheme.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0);
+ var actual = await SecurityRequirementWithUnreferencedSecurityScheme.SerializeAsJsonAsync(openApiSpecVersion);
// Assert
Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual)));