Skip to content

Commit a4efdfe

Browse files
authored
Support mutualTLS security scheme type (#2696)
feat(models): support mutualTLS security scheme * fix(writers): throw for mutualTLS in OAS 3.0
1 parent 4ee34a8 commit a4efdfe

File tree

6 files changed

+64
-1
lines changed

6 files changed

+64
-1
lines changed

src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,14 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version
126126
// openIdConnectUrl
127127
writer.WriteProperty(OpenApiConstants.OpenIdConnectUrl, OpenIdConnectUrl?.ToString());
128128
break;
129+
case SecuritySchemeType.MutualTLS:
130+
// No additional properties for mutualTLS
131+
if (version < OpenApiSpecVersion.OpenApi3_1)
132+
{
133+
// mutualTLS is introduced in OpenAPI 3.1
134+
throw new OpenApiException($"mutualTLS security scheme is only supported in OpenAPI 3.1 and later versions. Current version: {version}");
135+
}
136+
break;
129137
}
130138

131139
// deprecated - serialize as native field for v3.2+ or as extension for earlier versions
@@ -170,6 +178,14 @@ public virtual void SerializeAsV2(IOpenApiWriter writer)
170178
return;
171179
}
172180

181+
if (Type == SecuritySchemeType.MutualTLS)
182+
{
183+
// Bail because V2 does not support mutualTLS
184+
writer.WriteStartObject();
185+
writer.WriteEndObject();
186+
return;
187+
}
188+
173189
writer.WriteStartObject();
174190

175191
// type

src/Microsoft.OpenApi/Models/SecuritySchemeType.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ public enum SecuritySchemeType
2626
/// <summary>
2727
/// Use OAuth2 with OpenId Connect URL to discover OAuth2 configuration value.
2828
/// </summary>
29-
[Display("openIdConnect")] OpenIdConnect
29+
[Display("openIdConnect")] OpenIdConnect,
30+
31+
/// <summary>
32+
/// Use mutual TLS authentication.
33+
/// </summary>
34+
[Display("mutualTLS")] MutualTLS
3035
}
3136
}

test/Microsoft.OpenApi.Readers.Tests/V32Tests/OpenApiSecuritySchemeTests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,25 @@ public async Task ParseOpenIdConnectSecuritySchemeShouldSucceed()
102102
}, securityScheme);
103103
}
104104

105+
[Fact]
106+
public async Task ParseMutualTlsSecuritySchemeShouldSucceed()
107+
{
108+
// Act
109+
var securityScheme = await OpenApiModelFactory.LoadAsync<OpenApiSecurityScheme>(
110+
Path.Combine(SampleFolderPath, "mutualTlsSecurityScheme.yaml"),
111+
OpenApiSpecVersion.OpenApi3_2,
112+
new(),
113+
SettingsFixture.ReaderSettings);
114+
115+
// Assert
116+
Assert.Equivalent(
117+
new OpenApiSecurityScheme
118+
{
119+
Type = SecuritySchemeType.MutualTLS,
120+
Description = "Sample Description"
121+
}, securityScheme);
122+
}
123+
105124
[Fact]
106125
public async Task ParseOAuth2SecuritySchemeWithDeviceAuthorizationUrlShouldSucceed()
107126
{
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
type: mutualTLS
2+
description: Sample Description

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ public class OpenApiSecuritySchemeTests
101101
OpenIdConnectUrl = new("https://example.com/openIdConnect")
102102
};
103103

104+
private static OpenApiSecurityScheme MutualTlsSecurityScheme => new()
105+
{
106+
Description = "description1",
107+
Type = SecuritySchemeType.MutualTLS
108+
};
109+
104110
private static OpenApiSecuritySchemeReference OpenApiSecuritySchemeReference => new("sampleSecurityScheme");
105111
private static OpenApiSecurityScheme ReferencedSecurityScheme => new()
106112
{
@@ -208,6 +214,19 @@ public async Task SerializeHttpBearerSecuritySchemeAsV3JsonWorks()
208214
Assert.Equal(expected, actual);
209215
}
210216

217+
[Fact]
218+
public void SerializeMutualTlsSecuritySchemeAsV3Throws()
219+
{
220+
// Arrange
221+
var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture);
222+
var writer = new OpenApiJsonWriter(outputStringWriter);
223+
224+
// Act & Assert
225+
var exception = Assert.Throws<OpenApiException>(() => MutualTlsSecurityScheme.SerializeAsV3(writer));
226+
Assert.Contains("mutualTLS security scheme is only supported in OpenAPI 3.1 and later versions", exception.Message);
227+
Assert.Contains($"Current version: {OpenApiSpecVersion.OpenApi3_0}", exception.Message);
228+
}
229+
211230
[Fact]
212231
public async Task SerializeOAuthSingleFlowSecuritySchemeAsV3JsonWorks()
213232
{

test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1933,6 +1933,8 @@ namespace Microsoft.OpenApi
19331933
OAuth2 = 2,
19341934
[Microsoft.OpenApi.Display("openIdConnect")]
19351935
OpenIdConnect = 3,
1936+
[Microsoft.OpenApi.Display("mutualTLS")]
1937+
MutualTLS = 4,
19361938
}
19371939
public abstract class SourceExpression : Microsoft.OpenApi.RuntimeExpression
19381940
{

0 commit comments

Comments
 (0)