diff --git a/src/Microsoft.OpenApi.Readers/OpenApiYamlDocumentReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiYamlDocumentReader.cs
index e43c64ac2..f6fd2325e 100644
--- a/src/Microsoft.OpenApi.Readers/OpenApiYamlDocumentReader.cs
+++ b/src/Microsoft.OpenApi.Readers/OpenApiYamlDocumentReader.cs
@@ -166,7 +166,6 @@ private void ResolveReferences(OpenApiDiagnostic diagnostic, OpenApiDocument doc
}
}
-
///
/// Reads the stream input and parses the fragment of an OpenAPI description into an Open API Element.
///
diff --git a/src/Microsoft.OpenApi.Readers/V3/OpenApiSecuritySchemeDeserializer.cs b/src/Microsoft.OpenApi.Readers/V3/OpenApiSecuritySchemeDeserializer.cs
index 0e7b1c39c..dd6ad4751 100644
--- a/src/Microsoft.OpenApi.Readers/V3/OpenApiSecuritySchemeDeserializer.cs
+++ b/src/Microsoft.OpenApi.Readers/V3/OpenApiSecuritySchemeDeserializer.cs
@@ -76,7 +76,11 @@ internal static partial class OpenApiV3Deserializer
public static OpenApiSecurityScheme LoadSecurityScheme(ParseNode node)
{
var mapNode = node.CheckMapNode("securityScheme");
-
+ var pointer = mapNode.GetReferencePointer();
+ if (pointer != null)
+ {
+ return mapNode.GetReferencedObject(ReferenceType.SecurityScheme, pointer);
+ }
var securityScheme = new OpenApiSecurityScheme();
foreach (var property in mapNode)
{
diff --git a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs
index 8c469261c..3d9e978c9 100644
--- a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs
+++ b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System;
@@ -116,7 +116,18 @@ internal void Walk(OpenApiComponents components)
}
}
});
-
+
+ Walk(OpenApiConstants.SecuritySchemes, () =>
+ {
+ if (components.SecuritySchemes != null)
+ {
+ foreach (var item in components.SecuritySchemes)
+ {
+ Walk(item.Key, () => Walk(item.Value, isComponent: true));
+ }
+ }
+ });
+
Walk(OpenApiConstants.Callbacks, () =>
{
if (components.Callbacks != null)
@@ -996,9 +1007,9 @@ internal void Walk(OpenApiSecurityRequirement securityRequirement)
///
/// Visits and child objects
///
- internal void Walk(OpenApiSecurityScheme securityScheme)
+ internal void Walk(OpenApiSecurityScheme securityScheme, bool isComponent = false)
{
- if (securityScheme == null || ProcessAsReference(securityScheme))
+ if (securityScheme == null || ProcessAsReference(securityScheme, isComponent))
{
return;
}
diff --git a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj
index 65833564f..aef3d92e0 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj
+++ b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj
@@ -137,6 +137,9 @@
Never
+
+ Never
+
Never
diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs
index 362609291..8a0da3481 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs
+++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.Contracts;
using System.Globalization;
using System.IO;
using System.Linq;
@@ -1334,10 +1335,10 @@ public void DoesNotChangeExternalReferences()
{
// Arrange
using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "documentWithExternalRefs.yaml"));
-
+
// Act
var doc = new OpenApiStreamReader(
- new OpenApiReaderSettings { ReferenceResolution = ReferenceResolutionSetting.DoNotResolveReferences})
+ new OpenApiReaderSettings { ReferenceResolution = ReferenceResolutionSetting.DoNotResolveReferences })
.Read(stream, out var diagnostic);
var externalRef = doc.Components.Schemas["Nested"].Properties["AnyOf"].AnyOf.First().Reference.ReferenceV3;
@@ -1347,5 +1348,24 @@ public void DoesNotChangeExternalReferences()
Assert.Equal("file:///C:/MySchemas.json#/definitions/ArrayObject", externalRef);
Assert.Equal("../foo/schemas.yaml#/components/schemas/Number", externalRef2);
}
+
+ [Fact]
+ public void ParseDocumentWithReferencedSecuritySchemeWorks()
+ {
+ // Arrange
+ using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "docWithSecuritySchemeReference.yaml"));
+
+ // Act
+ var doc = new OpenApiStreamReader(new OpenApiReaderSettings
+ {
+ ReferenceResolution = ReferenceResolutionSetting.ResolveLocalReferences
+ }).Read(stream, out var diagnostic);
+
+ var securityScheme = doc.Components.SecuritySchemes["OAuth2"];
+
+ // Assert
+ Assert.False(securityScheme.UnresolvedReference);
+ Assert.NotNull(securityScheme.Flows);
+ }
}
}
diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/docWithSecuritySchemeReference.yaml b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/docWithSecuritySchemeReference.yaml
new file mode 100644
index 000000000..3608635a2
--- /dev/null
+++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/docWithSecuritySchemeReference.yaml
@@ -0,0 +1,17 @@
+openapi: 3.0.0
+info:
+ title: Example API
+ version: 1.0.0
+paths: { }
+components:
+ securitySchemes:
+ OAuth2:
+ $ref: '#/components/securitySchemes/RefOAuth2'
+ RefOAuth2:
+ type: oauth2
+ flows:
+ implicit:
+ authorizationUrl: https://example.com/api/oauth/dialog
+ scopes:
+ write:pets: modify pets in your account
+ read:pets: read your pets
\ No newline at end of file