From 27b76232075639fa60dbd029a71f24c346c1ab1c Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Mon, 6 Mar 2023 14:10:32 +0300 Subject: [PATCH 1/2] Add logic to resolve a referenceable security scheme component --- .../V3/OpenApiSecuritySchemeDeserializer.cs | 6 +++++- .../Services/OpenApiWalker.cs | 19 +++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) 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; } From a6634071da11585772287638bf7c681c84448ea6 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Mon, 6 Mar 2023 14:10:55 +0300 Subject: [PATCH 2/2] Add tests to validate --- .../OpenApiYamlDocumentReader.cs | 1 - .../Microsoft.OpenApi.Readers.Tests.csproj | 3 +++ .../V3Tests/OpenApiDocumentTests.cs | 24 +++++++++++++++++-- .../docWithSecuritySchemeReference.yaml | 17 +++++++++++++ 4 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/docWithSecuritySchemeReference.yaml 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/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