Skip to content

Commit aa25751

Browse files
authored
Merge pull request #2802 from microsoft/fix/security-requirement-ref
fix/security requirement ref
2 parents 4692c6b + a5acb89 commit aa25751

File tree

3 files changed

+81
-62
lines changed

3 files changed

+81
-62
lines changed

src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,7 @@ private void SerializeInternal(IOpenApiWriter writer, Action<IOpenApiWriter, Ope
7979

8080
writer.WriteStartObject();
8181

82-
// Reaching this point means the reference to a specific OpenApiSecurityScheme fails.
83-
// We are not able to serialize this SecurityScheme/Scopes key value pair since we do not know what
84-
// string to output.
85-
86-
foreach (var securitySchemeAndScopesValuePair in this.Where(static p => p.Key?.Target is not null))
82+
foreach (var securitySchemeAndScopesValuePair in this.Where(static p => CanSerializeSecurityScheme(p.Key)))
8783
{
8884
var securityScheme = securitySchemeAndScopesValuePair.Key;
8985
var scopes = securitySchemeAndScopesValuePair.Value;
@@ -103,6 +99,25 @@ private void SerializeInternal(IOpenApiWriter writer, Action<IOpenApiWriter, Ope
10399
writer.WriteEndObject();
104100
}
105101

102+
private static bool CanSerializeSecurityScheme(OpenApiSecuritySchemeReference? securityScheme)
103+
{
104+
if (securityScheme is null)
105+
{
106+
return false;
107+
}
108+
109+
if (securityScheme.Target is not null)
110+
{
111+
return true;
112+
}
113+
114+
var schemeId = securityScheme.Reference?.Id;
115+
var securitySchemes = securityScheme.Reference?.HostDocument?.Components?.SecuritySchemes;
116+
return !string.IsNullOrEmpty(schemeId)
117+
&& securitySchemes is not null
118+
&& securitySchemes.ContainsKey(schemeId!);
119+
}
120+
106121
/// <summary>
107122
/// Serialize <see cref="OpenApiSecurityRequirement"/> to Open Api v2.0
108123
/// </summary>

test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.IO;
1010
using System.Linq;
1111
using System.Net.Http;
12+
using System.Text.Json.Nodes;
1213
using System.Threading.Tasks;
1314
using VerifyXunit;
1415
using Xunit;
@@ -2387,6 +2388,56 @@ public async Task SerializeDocumentWithSelfPropertyAsV32Works()
23872388
Assert.Equal(expected.MakeLineBreaksEnvironmentNeutral(), actual.MakeLineBreaksEnvironmentNeutral());
23882389
}
23892390

2391+
[Theory]
2392+
[InlineData(OpenApiSpecVersion.OpenApi3_0)]
2393+
[InlineData(OpenApiSpecVersion.OpenApi3_1)]
2394+
[InlineData(OpenApiSpecVersion.OpenApi3_2)]
2395+
public async Task SerializeDocumentWithSecurityRequirementAsJsonWorks(OpenApiSpecVersion openApiSpecVersion)
2396+
{
2397+
// Arrange
2398+
var doc = new OpenApiDocument
2399+
{
2400+
Info = new OpenApiInfo { Title = "Test", Version = "1.0" },
2401+
Components = new OpenApiComponents
2402+
{
2403+
SecuritySchemes = new Dictionary<string, IOpenApiSecurityScheme>(StringComparer.Ordinal)
2404+
{
2405+
["Bearer"] = new OpenApiSecurityScheme
2406+
{
2407+
Type = SecuritySchemeType.Http,
2408+
Scheme = "Bearer",
2409+
BearerFormat = "JWT",
2410+
},
2411+
},
2412+
},
2413+
};
2414+
2415+
doc.Security =
2416+
[
2417+
new OpenApiSecurityRequirement
2418+
{
2419+
{ new OpenApiSecuritySchemeReference("Bearer", doc), [] },
2420+
},
2421+
];
2422+
2423+
var expected =
2424+
"""
2425+
[
2426+
{
2427+
"Bearer": []
2428+
}
2429+
]
2430+
""";
2431+
2432+
// Act
2433+
var actual = await doc.SerializeAsJsonAsync(openApiSpecVersion);
2434+
2435+
// Assert
2436+
var actualSecurity = JsonNode.Parse(actual)?["security"];
2437+
Assert.NotNull(actualSecurity);
2438+
Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), actualSecurity));
2439+
}
2440+
23902441
[Fact]
23912442
public async Task SerializeDocumentWithSelfPropertyAsV31WritesAsExtension()
23922443
{

test/Microsoft.OpenApi.Tests/Models/OpenApiSecurityRequirementTests.cs

Lines changed: 10 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -130,35 +130,10 @@ public async Task SerializeSecurityRequirementAsV3JsonWorksAsync(bool produceTer
130130
await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput);
131131
}
132132

133-
[Fact]
134-
public async Task SerializeSecurityRequirementWithReferencedSecuritySchemeAsV3JsonWorks()
135-
{
136-
// Arrange
137-
var expected =
138-
"""
139-
{
140-
"scheme1": [
141-
"scope1",
142-
"scope2",
143-
"scope3"
144-
],
145-
"scheme2": [
146-
"scope4",
147-
"scope5"
148-
],
149-
"scheme3": [ ]
150-
}
151-
""";
152-
153-
// Act
154-
var actual = await SecurityRequirementWithReferencedSecurityScheme.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
155-
156-
// Assert
157-
Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual)));
158-
}
159-
160-
[Fact]
161-
public async Task SerializeSecurityRequirementWithReferencedSecuritySchemeAsV2JsonWorks()
133+
[Theory]
134+
[InlineData(OpenApiSpecVersion.OpenApi3_0)]
135+
[InlineData(OpenApiSpecVersion.OpenApi2_0)]
136+
public async Task SerializeSecurityRequirementWithReferencedSecuritySchemeAsJsonWorks(OpenApiSpecVersion openApiSpecVersion)
162137
{
163138
// Arrange
164139
var expected =
@@ -178,37 +153,16 @@ public async Task SerializeSecurityRequirementWithReferencedSecuritySchemeAsV2Js
178153
""";
179154

180155
// Act
181-
var actual = await SecurityRequirementWithReferencedSecurityScheme.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0);
156+
var actual = await SecurityRequirementWithReferencedSecurityScheme.SerializeAsJsonAsync(openApiSpecVersion);
182157

183158
// Assert
184159
Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual)));
185160
}
186161

187-
[Fact]
188-
public async Task SerializeSecurityRequirementWithUnreferencedSecuritySchemeAsV3JsonShouldSkipUnserializableKeyValuePair()
189-
{
190-
// Arrange
191-
var expected =
192-
"""
193-
{
194-
"scheme1": [
195-
"scope1",
196-
"scope2",
197-
"scope3"
198-
],
199-
"scheme3": [ ]
200-
}
201-
""";
202-
203-
// Act
204-
var actual = await SecurityRequirementWithUnreferencedSecurityScheme.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
205-
206-
// Assert
207-
Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual)));
208-
}
209-
210-
[Fact]
211-
public async Task SerializeSecurityRequirementWithUnreferencedSecuritySchemeAsV2JsonShouldSkipUnserializableKeyValuePair()
162+
[Theory]
163+
[InlineData(OpenApiSpecVersion.OpenApi3_0)]
164+
[InlineData(OpenApiSpecVersion.OpenApi2_0)]
165+
public async Task SerializeSecurityRequirementWithUnreferencedSecuritySchemeAsJsonShouldSkipUnserializableKeyValuePair(OpenApiSpecVersion openApiSpecVersion)
212166
{
213167
// Arrange
214168
var expected =
@@ -224,8 +178,7 @@ public async Task SerializeSecurityRequirementWithUnreferencedSecuritySchemeAsV2
224178
""";
225179

226180
// Act
227-
var actual =
228-
await SecurityRequirementWithUnreferencedSecurityScheme.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0);
181+
var actual = await SecurityRequirementWithUnreferencedSecurityScheme.SerializeAsJsonAsync(openApiSpecVersion);
229182

230183
// Assert
231184
Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual)));

0 commit comments

Comments
 (0)