From 57c367cb35c0dd3a433fd3024dd8d74669fbd6d4 Mon Sep 17 00:00:00 2001 From: Mads Larsen Date: Sat, 20 Sep 2025 16:37:27 +0200 Subject: [PATCH] feat: Extension to configure oauth implicit flow --- .DS_Store | Bin 6148 -> 0 bytes .github/.DS_Store | Bin 6148 -> 0 bytes .gitignore | 2 +- src/.DS_Store | Bin 6148 -> 0 bytes .../Extensions/OpenApiOptionsExtensions.cs | 31 ++++++-- .../Options/ImplicitFlowOptions.cs | 10 +++ ...Auth2ImplicitFlowDocumentTransformation.cs | 71 ++++++++++++++++++ src/OpenApi.NodaTime/.DS_Store | Bin 6148 -> 0 bytes 8 files changed, 106 insertions(+), 8 deletions(-) delete mode 100644 .DS_Store delete mode 100644 .github/.DS_Store delete mode 100644 src/.DS_Store create mode 100644 src/OpenApi.Extensions/Options/ImplicitFlowOptions.cs create mode 100644 src/OpenApi.Extensions/Transformers/Documents/OAuth2ImplicitFlowDocumentTransformation.cs delete mode 100644 src/OpenApi.NodaTime/.DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index fb041889ff6aeb9470c7746c4d34eb5a33d3763a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK!D<^Z5FOc0yh{l9&_IrYTuo{xA))lLxakjcLwZPyyX$q6CEHc-uIqy_?797+ zeo4P4ZzRPuI6byBWd=rXG@8*$Pe$?(ks8gjAyJQr0w`lEMDv93IO~SAyk`rj>>M{V zr!=c3MQS#p#qlpPz-QN`L%OD%YWn5;Oo1b%kP@04Tl5m-%!t?!9

C7hN*%Tok-sfdz79%q+v&!biZXgJQaNOHpF3*n6`ucb{T=n(x)zP4@PmWJl zt1#F*c=`I>__p{`ns2;Z{7iXMEV~ZY?RQvyH&1NvYdk9pQ(hzJVS;t07{Y)sAPhV| z2K-eP>^#4v%Zh~oVc-ul!1sfOGDaR7hxY0~V@m*F2W~5{xt8D@?J@G$IK&7)C&BX4PfN4aR?7Y O{s>qaq!9-GDg*b8qgwd@ diff --git a/.github/.DS_Store b/.github/.DS_Store deleted file mode 100644 index 36b372c72cba58418798b30534145e40b446efdb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKJ5EC}5S)b+K{P2TeTCe>ioyxF0D>q@p7bOlMEfevm7_8HDTp3)NfXUV>#^56 zwmik#w*YMOxmyD(086?fzI~XR@4L_Jt|CUH^Nc+PjQGNFcbsMa9dPag86!S$_|1PG z-o|n8ZJ8910#ZN7!Kn+ zdI@6l0I?TNiHy)Jsl=pOwHTIk##`m}!YMK7uxdW6Zno-BENN(xAUn^M3Q+n4QzPpaBFdz{zWMt`My&WY~Ec~Ce+IVMIq=EBSI dQzT_x^Evl>;glG3#)D4O&w%S9lLFUP;0L2O71{s* diff --git a/.gitignore b/.gitignore index c786620..3c2a2d3 100644 --- a/.gitignore +++ b/.gitignore @@ -397,5 +397,5 @@ FodyWeavers.xsd # JetBrains Rider *.sln.iml -.DS_Store .idea/ +.DS_Store diff --git a/src/.DS_Store b/src/.DS_Store deleted file mode 100644 index c45eada9c1324cceedfebdc697526fe5326f53bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKyG{c^3>-s>NHh@@<$eJYf3QSJ3k7@tk4u3RIHXG?%Iosm89zW5F0>S2OWwKl zde*rq&M^R)Z<{M%24G58#7>v7>ACvIP9mZxcE>f|@q$Y%@iEFi9#HN%ZpmBW4MYCM zA|3B*dD1oA^ZKc6*DS>ZsBvC6zBDoac#V$~ThmJX?oxuycCz@Y-CzMX0RU($b={|`yIO9fJaKc#?77I%v| zUnzR)=;gH67WxDI)0k`NT&xuntrc^lt@vV)SM-_ZHL!OyI^#ws<{tsoB`p>B4F&d= CvmlcI diff --git a/src/OpenApi.Extensions/Extensions/OpenApiOptionsExtensions.cs b/src/OpenApi.Extensions/Extensions/OpenApiOptionsExtensions.cs index fcf64f2..67f8ecb 100644 --- a/src/OpenApi.Extensions/Extensions/OpenApiOptionsExtensions.cs +++ b/src/OpenApi.Extensions/Extensions/OpenApiOptionsExtensions.cs @@ -7,7 +7,9 @@ using Microsoft.AspNetCore.OpenApi; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; +using OpenApi.Extensions.Options; using OpenApi.Extensions.Transformers; +using OpenApi.Extensions.Transformers.Documents; using OpenApi.Extensions.Transformers.Operations; namespace OpenApi.Extensions.Extensions; @@ -29,6 +31,21 @@ public static OpenApiOptions AddDescription(this OpenApiOptions options, string return options; } + ///

+ /// Adds a document transformer to configure OAuth2 Implicit Flow. + /// + /// The OpenAPI options to configure. + /// + /// The updated instance. + public static OpenApiOptions AddOAuth2ImplicitFlow(this OpenApiOptions options, Action configure) + { + var opt = new ImplicitFlowOptions(); + configure(opt); + + options.AddDocumentTransformer(new OAuth2ImplicitFlowDocumentTransformation(opt.SecurityScheme, opt.TokenEndpoint, opt.AuthorizationEndpoint, opt.Description, opt.Scopes)); + return options; + } + /// /// Adds the given status code and description to all operations /// @@ -489,13 +506,6 @@ private static string FormatJson(T obj, JsonSerializerOptions? jsonSerializer return formatToJson; } - private static bool ShouldTransform(OpenApiSchemaTransformerContext context) - { - var jsonType = context.JsonTypeInfo.Type; - var type = Nullable.GetUnderlyingType(jsonType) ?? jsonType; - return type == typeof(T); - } - private static string GetTypeName() { if (typeof(T) == typeof(string)) @@ -505,4 +515,11 @@ private static string GetTypeName() return typeof(T).Name; } + + private static bool ShouldTransform(OpenApiSchemaTransformerContext context) + { + var jsonType = context.JsonTypeInfo.Type; + var type = Nullable.GetUnderlyingType(jsonType) ?? jsonType; + return type == typeof(T); + } } diff --git a/src/OpenApi.Extensions/Options/ImplicitFlowOptions.cs b/src/OpenApi.Extensions/Options/ImplicitFlowOptions.cs new file mode 100644 index 0000000..0b04890 --- /dev/null +++ b/src/OpenApi.Extensions/Options/ImplicitFlowOptions.cs @@ -0,0 +1,10 @@ +namespace OpenApi.Extensions.Options; + +public class ImplicitFlowOptions +{ + public string AuthorizationEndpoint { get; set; } = null!; + public string Description { get; set; } = null!; + public string[] Scopes { get; set; } = []; + public string SecurityScheme { get; set; } = null!; + public string TokenEndpoint { get; set; } = null!; +} diff --git a/src/OpenApi.Extensions/Transformers/Documents/OAuth2ImplicitFlowDocumentTransformation.cs b/src/OpenApi.Extensions/Transformers/Documents/OAuth2ImplicitFlowDocumentTransformation.cs new file mode 100644 index 0000000..df7a31f --- /dev/null +++ b/src/OpenApi.Extensions/Transformers/Documents/OAuth2ImplicitFlowDocumentTransformation.cs @@ -0,0 +1,71 @@ +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.OpenApi; +using Microsoft.OpenApi.Models; + +namespace OpenApi.Extensions.Transformers.Documents; + +public class OAuth2ImplicitFlowDocumentTransformation : IOpenApiDocumentTransformer +{ + private readonly string _authorizationEndpoint; + private readonly string _description; + private readonly string[] _scopes; + private readonly string _securityScheme; + private readonly string _tokenEndpoint; + + public OAuth2ImplicitFlowDocumentTransformation(string securityScheme, + string tokenEndpoint, + string authorizationEndpoint, + string description, + params string[] scopes) + { + _securityScheme = securityScheme; + _tokenEndpoint = tokenEndpoint; + _authorizationEndpoint = authorizationEndpoint; + _description = description; + _scopes = scopes; + } + + public Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken) + { + document.Components ??= new OpenApiComponents(); + document.Components.SecuritySchemes[_securityScheme] = + new OpenApiSecurityScheme + { + Type = SecuritySchemeType.OAuth2, + Description = _description, + Flows = new OpenApiOAuthFlows + { + Implicit = new OpenApiOAuthFlow + { + AuthorizationUrl = new Uri(_authorizationEndpoint), + TokenUrl = new Uri(_tokenEndpoint), + Scopes = _scopes.ToDictionary( + s => s, + s => s) + } + } + }; + + document.SecurityRequirements.Add( + new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType + .SecurityScheme, + Id = _securityScheme, + } + }, + _scopes + } + }); + + return Task.CompletedTask; + } +} diff --git a/src/OpenApi.NodaTime/.DS_Store b/src/OpenApi.NodaTime/.DS_Store deleted file mode 100644 index fb928a89d8366cbd02c2edd9d0a8d9c7bfcf915e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKyH3O~5S)c8PNGRk=`TRy55nnap@0wIkt>i6f`sT(@m+ixvyUbUR41C#th63` zy<^K$WU~Nl^Eq4s9e_365nnzm&G+3Gc2W@|(s{-e-tmG9++bW}{~mB|hgoX zgG00c#1+F~oJTJ~Y#t!?g;OFUG)pQmsa7q9C7tnBd41uOm~>b*A67S8bto3M^ZXX+ zus%_v6p#XQ1x|C>dHuhp|Iz=?Nm@w(DR5K@*lK&X-SA0OTNjV>THELkbkF&wyKx>A n4pEMYQI5Ira(o_1nb&;I{l0KY3_9aMC+cUwb&*Md|5o4!A^;ZQ