From 9e44d4b0fbabb212c3498656c5bb4e72a8daede8 Mon Sep 17 00:00:00 2001 From: jxnkwlp Date: Wed, 3 Jan 2024 15:50:16 +0800 Subject: [PATCH] update framework version to .net 8 --- .editorconfig | 6 +- common.props | 31 ++++++ .../source/ApiKeyExtensions.cs | 9 +- .../source/ApiKeyHandler.cs | 99 +++++++++++-------- ...nd.AspNetCore.Authentication.ApiKey.csproj | 42 ++------ .../Configuration/IConfigurationManager.cs | 7 -- .../StaticConfigurationManager.cs | 11 --- ...ind.AspNetCore.Authentication.Saml2.csproj | 40 ++------ .../source/Saml2Events.cs | 8 +- .../source/Saml2Handler.cs | 41 +++++--- .../source/Saml2OptionsConfigureOptions.cs | 17 ---- .../source/Saml2PostConfigureOptions.cs | 9 +- .../Passingwind.SwaggerExtensions.csproj | 4 +- 13 files changed, 151 insertions(+), 173 deletions(-) create mode 100644 common.props delete mode 100644 src/Authentication.Saml2/source/Saml2OptionsConfigureOptions.cs diff --git a/.editorconfig b/.editorconfig index 1e503d1..382ea0b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -489,10 +489,14 @@ roslynator_refactorings.enabled = true roslynator_compiler_diagnostic_fixes.enabled = true tab_width = 4 -# +# default|none|silent|suggestion|warning|error dotnet_diagnostic.CA1848.severity = silent dotnet_diagnostic.CA1305.severity = silent dotnet_diagnostic.CA2016.severity = warning +dotnet_diagnostic.RCS1163.severity = silent +dotnet_diagnostic.RCS1228.severity = silent +dotnet_diagnostic.RCS1141.severity = silent +dotnet_diagnostic.RCS1006.severity = suggestion [{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.stylelintrc,bowerrc,jest.config}] indent_style = space diff --git a/common.props b/common.props new file mode 100644 index 0000000..b5cb0f2 --- /dev/null +++ b/common.props @@ -0,0 +1,31 @@ + + + enable + latest-minimum + True + 1701;1702;CS1591 + latest + Passingwind + https://github.com/jxnkwlp/Passingwind.CommonLibs + https://github.com/jxnkwlp/Passingwind.CommonLibs + git + README.md + MIT + True + snupkg + + + + + True + \ + + + + + + all + runtime; build; native; contentfiles; analyzers + + + diff --git a/src/Authentication.ApiKey/source/ApiKeyExtensions.cs b/src/Authentication.ApiKey/source/ApiKeyExtensions.cs index 19d6441..36d5062 100644 --- a/src/Authentication.ApiKey/source/ApiKeyExtensions.cs +++ b/src/Authentication.ApiKey/source/ApiKeyExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -14,6 +14,7 @@ public static class ApiKeyExtensions /// /// Enables ApiKey authentication using the default scheme /// + /// public static AuthenticationBuilder AddApiKey(this AuthenticationBuilder builder) where TApiKeyProvider : class, IApiKeyProvider { return AddApiKey(builder: builder, authenticationScheme: ApiKeyDefaults.AuthenticationScheme, displayName: null, configureOptions: _ => { }); @@ -22,6 +23,7 @@ public static AuthenticationBuilder AddApiKey(this Authenticati /// /// Enables ApiKey authentication /// + /// public static AuthenticationBuilder AddApiKey(this AuthenticationBuilder builder, string authenticationScheme) where TApiKeyProvider : class, IApiKeyProvider { return AddApiKey(builder: builder, authenticationScheme: authenticationScheme, displayName: null, configureOptions: _ => { }); @@ -30,6 +32,7 @@ public static AuthenticationBuilder AddApiKey(this Authenticati /// /// Enables ApiKey authentication /// + /// public static AuthenticationBuilder AddApiKey(this AuthenticationBuilder builder, Action configureOptions) where TApiKeyProvider : class, IApiKeyProvider { return AddApiKey(builder: builder, authenticationScheme: ApiKeyDefaults.AuthenticationScheme, displayName: null, configureOptions: configureOptions); @@ -38,6 +41,7 @@ public static AuthenticationBuilder AddApiKey(this Authenticati /// /// Enables ApiKey authentication /// + /// public static AuthenticationBuilder AddApiKey(this AuthenticationBuilder builder, string authenticationScheme, Action configureOptions) where TApiKeyProvider : class, IApiKeyProvider { return AddApiKey(builder: builder, authenticationScheme: authenticationScheme, displayName: null, configureOptions: configureOptions); @@ -46,6 +50,7 @@ public static AuthenticationBuilder AddApiKey(this Authenticati /// /// Enables ApiKey authentication /// + /// public static AuthenticationBuilder AddApiKey(this AuthenticationBuilder builder, string authenticationScheme, string? displayName, Action configureOptions) where TApiKeyProvider : class, IApiKeyProvider { builder.Services.TryAddTransient(); @@ -58,4 +63,4 @@ public static AuthenticationBuilder AddApiKey(this Authenticati return builder; } -} \ No newline at end of file +} diff --git a/src/Authentication.ApiKey/source/ApiKeyHandler.cs b/src/Authentication.ApiKey/source/ApiKeyHandler.cs index a0a558f..0feec53 100644 --- a/src/Authentication.ApiKey/source/ApiKeyHandler.cs +++ b/src/Authentication.ApiKey/source/ApiKeyHandler.cs @@ -1,3 +1,4 @@ +using System; using System.Net.Http.Headers; using System.Security.Claims; using System.Text; @@ -22,11 +23,30 @@ public class ApiKeyHandler : AuthenticationHandler /// protected new ApiKeyEvents Events { get => (ApiKeyEvents)base.Events!; set => base.Events = value; } +#if NET8_0_OR_GREATER /// + [Obsolete("ISystemClock is obsolete, use TimeProvider on AuthenticationSchemeOptions instead.")] public ApiKeyHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IApiKeyProvider apiKeyProvider) : base(options, logger, encoder, clock) { ApiKeyProvider = apiKeyProvider; } + /// + public ApiKeyHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, IApiKeyProvider apiKeyProvider) : base(options, logger, encoder) + { + ApiKeyProvider = apiKeyProvider; + } +#else + /// + public ApiKeyHandler( + IOptionsMonitor options, + ILoggerFactory logger, + UrlEncoder encoder, + ISystemClock clock, + IApiKeyProvider apiKeyProvider) : base(options, logger, encoder, clock) + { + ApiKeyProvider = apiKeyProvider; + } +#endif /// protected override Task CreateEventsAsync() @@ -37,16 +57,18 @@ protected override Task CreateEventsAsync() /// protected override async Task HandleAuthenticateAsync() { - var messageReceivedContext = new ApiKeyMessageReceivedContext(Context, Scheme, Options); + ApiKeyMessageReceivedContext messageReceivedContext = new(Context, Scheme, Options); await Events.MessageReceivedAsync(messageReceivedContext).ConfigureAwait(false); if (messageReceivedContext.Result != null) + { return messageReceivedContext.Result; + } - var request = Request; + HttpRequest request = Request; - var isApiKeyAvailable = CanHandle(request); + bool isApiKeyAvailable = CanHandle(request); if (!isApiKeyAvailable) { @@ -59,38 +81,29 @@ protected override async Task HandleAuthenticateAsync() { return AuthenticateResult.NoResult(); } - else - { - Logger.LogDebug("The Api Key '{token}' was found in the request.", token); - } + + Logger.LogDebug("The Api Key '{token}' was found in the request.", token); try { - var validationResult = await ApiKeyProvider.ValidateAsync(token).ConfigureAwait(false); + ApiKeyValidationResult validationResult = await ApiKeyProvider.ValidateAsync(token).ConfigureAwait(false); if (validationResult.Exception != null) { - Logger.LogError(validationResult.Exception, "The API Key verification failed by {0}.", ApiKeyProvider.GetType().Name); + Logger.LogError(validationResult.Exception, "The API Key verification failed by {Name}.", ApiKeyProvider.GetType().Name); - var authenticationFailedContext = new ApiKeyAuthenticationFailedContext(Context, Scheme, Options) { Exception = validationResult.Exception }; + ApiKeyAuthenticationFailedContext authenticationFailedContext = new(Context, Scheme, Options) { Exception = validationResult.Exception }; await Events.AuthenticationFailedAsync(authenticationFailedContext).ConfigureAwait(false); - if (authenticationFailedContext.Result != null) - { - return authenticationFailedContext.Result; - } - - return AuthenticateResult.Fail(authenticationFailedContext.Exception); - } - else - { - Logger.LogInformation("The API Key verification successful by {0}.", ApiKeyProvider.GetType().Name); + return authenticationFailedContext.Result ?? AuthenticateResult.Fail(authenticationFailedContext.Exception); } - var identity = validationResult.Identity; + Logger.LogInformation("The API Key verification successful by {Name}.", ApiKeyProvider.GetType().Name); - var tokenValidatedContext = new ApiKeyTokenValidatedContext(Context, Scheme, Options) + ClaimsIdentity identity = validationResult.Identity; + + ApiKeyTokenValidatedContext tokenValidatedContext = new(Context, Scheme, Options) { Token = token, Principal = new ClaimsPrincipal(identity), @@ -99,7 +112,9 @@ protected override async Task HandleAuthenticateAsync() await Events.TokenValidatedAsync(tokenValidatedContext).ConfigureAwait(false); if (tokenValidatedContext.Result != null) + { return tokenValidatedContext.Result; + } if (Options.SaveToken) { @@ -112,9 +127,9 @@ protected override async Task HandleAuthenticateAsync() } catch (System.Exception exception) { - Logger.LogError("Exception occurred while processing message.", exception); + Logger.LogError(exception, "Exception occurred while processing message."); - var authenticationFailedContext = new ApiKeyAuthenticationFailedContext(Context, Scheme, Options) { Exception = exception }; + ApiKeyAuthenticationFailedContext authenticationFailedContext = new(Context, Scheme, Options) { Exception = exception }; await Events.AuthenticationFailedAsync(authenticationFailedContext).ConfigureAwait(false); @@ -130,9 +145,9 @@ protected override async Task HandleAuthenticateAsync() /// protected override async Task HandleChallengeAsync(AuthenticationProperties properties) { - var authResult = await HandleAuthenticateOnceSafeAsync().ConfigureAwait(false); + AuthenticateResult authResult = await HandleAuthenticateOnceSafeAsync().ConfigureAwait(false); - var eventContext = new ApiKeyChallengeContext(Context, Scheme, Options, properties) + ApiKeyChallengeContext eventContext = new(Context, Scheme, Options, properties) { AuthenticateFailure = authResult?.Failure }; @@ -154,11 +169,11 @@ protected override async Task HandleChallengeAsync(AuthenticationProperties prop { // WWW-Authenticate: ApiKey realm="example", charset="UTF-8", in="authorization_header", in="header_or_query_params", key_name="mykey"; - var builder = new StringBuilder(Options.Challenge); + StringBuilder builder = new(Options.Challenge); if (!string.IsNullOrWhiteSpace(Options.Realm)) { - builder.Append($"realm=\"{Options.Realm}\""); + builder.Append("realm=\"").Append(Options.Realm).Append('\"'); } if (Options.Challenge.IndexOf(' ') > 0) { @@ -167,9 +182,9 @@ protected override async Task HandleChallengeAsync(AuthenticationProperties prop } if (!string.IsNullOrEmpty(eventContext.Error)) { - builder.Append(" error=\""); - builder.Append(eventContext.Error); - builder.Append('\"'); + builder.Append(" error=\"") + .Append(eventContext.Error) + .Append('\"'); } // TODO @@ -181,7 +196,7 @@ protected override async Task HandleChallengeAsync(AuthenticationProperties prop /// protected override Task HandleForbiddenAsync(AuthenticationProperties properties) { - var forbiddenContext = new ApiKeyForbiddenContext(Context, Scheme, Options); + ApiKeyForbiddenContext forbiddenContext = new(Context, Scheme, Options); return Events.ForbiddenAsync(forbiddenContext); } @@ -189,14 +204,20 @@ protected override Task HandleForbiddenAsync(AuthenticationProperties properties /// protected virtual string? GetToken(HttpRequest request) { - if (!string.IsNullOrWhiteSpace(Options.QueryStringName) && request.Query.TryGetValue(Options.QueryStringName, out var queryToken)) - return queryToken; + if (!string.IsNullOrWhiteSpace(Options.QueryStringName) && request.Query.TryGetValue(Options.QueryStringName, out Microsoft.Extensions.Primitives.StringValues queryToken)) + { + return (string?)queryToken; + } - if (!string.IsNullOrWhiteSpace(Options.HeaderName) && request.Headers.TryGetValue(Options.HeaderName, out var headerToken)) - return headerToken; + if (!string.IsNullOrWhiteSpace(Options.HeaderName) && request.Headers.TryGetValue(Options.HeaderName, out Microsoft.Extensions.Primitives.StringValues headerToken)) + { + return (string?)headerToken; + } - if (!string.IsNullOrWhiteSpace(Options.HeaderAuthenticationSchemeName) && request.Headers.ContainsKey(HeaderNames.Authorization) && AuthenticationHeaderValue.TryParse(request.Headers[HeaderNames.Authorization], out var headerValue)) + if (!string.IsNullOrWhiteSpace(Options.HeaderAuthenticationSchemeName) && request.Headers.TryGetValue(HeaderNames.Authorization, out Microsoft.Extensions.Primitives.StringValues value) && AuthenticationHeaderValue.TryParse(value, out AuthenticationHeaderValue? headerValue)) + { return headerValue.Parameter; + } return string.Empty; } @@ -206,6 +227,6 @@ protected virtual bool CanHandle(HttpRequest request) { return (!string.IsNullOrWhiteSpace(Options.HeaderName) && request.Headers.ContainsKey(Options.HeaderName)) || (!string.IsNullOrWhiteSpace(Options.QueryStringName) && request.Query.ContainsKey(Options.QueryStringName)) - || (!string.IsNullOrWhiteSpace(Options.HeaderAuthenticationSchemeName) && AuthenticationHeaderValue.TryParse(request.Headers[HeaderNames.Authorization], out var headerValue) && headerValue.Scheme.Equals(Options.HeaderAuthenticationSchemeName, System.StringComparison.OrdinalIgnoreCase)); + || (!string.IsNullOrWhiteSpace(Options.HeaderAuthenticationSchemeName) && AuthenticationHeaderValue.TryParse(request.Headers[HeaderNames.Authorization], out AuthenticationHeaderValue? headerValue) && headerValue.Scheme.Equals(Options.HeaderAuthenticationSchemeName, System.StringComparison.OrdinalIgnoreCase)); } -} \ No newline at end of file +} diff --git a/src/Authentication.ApiKey/source/Passingwind.AspNetCore.Authentication.ApiKey.csproj b/src/Authentication.ApiKey/source/Passingwind.AspNetCore.Authentication.ApiKey.csproj index 1fc291e..e3f5d1d 100644 --- a/src/Authentication.ApiKey/source/Passingwind.AspNetCore.Authentication.ApiKey.csproj +++ b/src/Authentication.ApiKey/source/Passingwind.AspNetCore.Authentication.ApiKey.csproj @@ -1,48 +1,24 @@ - + + + - net6;net7 - enable - Passingwind.AspNetCore.Authentication.ApiKey - latest - True - $(AssemblyVersion) - 0.2 + net6;net7;net8 + Passingwind.AspNetCore.Authentication.ApiKey + 0.3.0 1701;1702;CS1591 Passingwind.AspNetCore.Authentication.ApiKey - Passingwind.AspNetCore.Authentication.ApiKey - Passingwind - https://github.com/jxnkwlp/Passingwind.CommonLibs - https://github.com/jxnkwlp/Passingwind.CommonLibs - git + Passingwind.AspNetCore.Authentication.ApiKey authentication, ApiKey - ASP.NET Core authentication handler for the ApiKey protocol - README.md - MIT - True - snupkg - 0.2.0 + ASP.NET Core authentication handler for the ApiKey protocol + 0.3.0 - - - True - \ - - - - - - all - runtime; build; native; contentfiles; analyzers - - - diff --git a/src/Authentication.Saml2/source/Configuration/IConfigurationManager.cs b/src/Authentication.Saml2/source/Configuration/IConfigurationManager.cs index 31104e8..2a96ad1 100644 --- a/src/Authentication.Saml2/source/Configuration/IConfigurationManager.cs +++ b/src/Authentication.Saml2/source/Configuration/IConfigurationManager.cs @@ -4,14 +4,7 @@ namespace Passingwind.AspNetCore.Authentication.Saml2.Configuration; -/// -/// -/// public interface IConfigurationManager { - /// - /// - /// - /// Task GetConfigurationAsync(CancellationToken cancellationToken = default); } diff --git a/src/Authentication.Saml2/source/Configuration/StaticConfigurationManager.cs b/src/Authentication.Saml2/source/Configuration/StaticConfigurationManager.cs index 8be7ab2..be7eb48 100644 --- a/src/Authentication.Saml2/source/Configuration/StaticConfigurationManager.cs +++ b/src/Authentication.Saml2/source/Configuration/StaticConfigurationManager.cs @@ -4,26 +4,15 @@ namespace Passingwind.AspNetCore.Authentication.Saml2.Configuration; -/// -/// -/// public class StaticConfigurationManager : IConfigurationManager { private readonly Saml2Configuration _saml2Configuration; - /// - /// - /// - /// public StaticConfigurationManager(Saml2Configuration saml2Configuration) { _saml2Configuration = saml2Configuration; } - /// - /// - /// - /// public Task GetConfigurationAsync(CancellationToken cancellationToken = default) { return Task.FromResult(_saml2Configuration); diff --git a/src/Authentication.Saml2/source/Passingwind.AspNetCore.Authentication.Saml2.csproj b/src/Authentication.Saml2/source/Passingwind.AspNetCore.Authentication.Saml2.csproj index ae2aedf..4928c7c 100644 --- a/src/Authentication.Saml2/source/Passingwind.AspNetCore.Authentication.Saml2.csproj +++ b/src/Authentication.Saml2/source/Passingwind.AspNetCore.Authentication.Saml2.csproj @@ -1,52 +1,28 @@  + + - net6;net7 - enable + net6;net7;net8 Passingwind.AspNetCore.Authentication.Saml2 - latest-minimum - True - 1701;1702;CS1591 $(Version) 0.2.0 Passingwind.AspNetCore.Authentication.Saml2 - Passingwind.AspNetCore.Authentication.Saml2 - Passingwind - https://github.com/jxnkwlp/Passingwind.CommonLibs - https://github.com/jxnkwlp/Passingwind.CommonLibs - git + Passingwind.AspNetCore.Authentication.Saml2 authentication, SAML2 - ASP.NET Core authentication handler for the SAML2 protocol - README.md - MIT - True - snupkg - 0.2.1 + ASP.NET Core authentication handler for the SAML2 protocol + 0.3.0 - + - - - - True - \ - - - - - - all - runtime; build; native; contentfiles; analyzers - - - + diff --git a/src/Authentication.Saml2/source/Saml2Events.cs b/src/Authentication.Saml2/source/Saml2Events.cs index fe4dfc3..b047ec0 100644 --- a/src/Authentication.Saml2/source/Saml2Events.cs +++ b/src/Authentication.Saml2/source/Saml2Events.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Security.Claims; using System.Threading.Tasks; using ITfoxtec.Identity.Saml2; @@ -42,7 +42,6 @@ public class Saml2Events : RemoteAuthenticationEvents /// /// Invoked if exceptions are thrown during request processing. The exceptions will be re-thrown after this event unless suppressed. /// - /// public virtual Task AuthenticationFailed(AuthenticationFailedContext context) { return OnAuthenticationFailed(context); @@ -51,7 +50,6 @@ public virtual Task AuthenticationFailed(AuthenticationFailedContext context) /// /// Invoked to manipulate redirects to the identity provider for SignIn, SignOut, or Challenge. /// - /// public virtual Task RedirectToIdentityProvider(RedirectContext context) { return OnRedirectToIdentityProvider(context); @@ -60,7 +58,6 @@ public virtual Task RedirectToIdentityProvider(RedirectContext context) /// /// Invoked when a protocol message is first received. /// - /// public virtual Task MessageReceived(MessageReceivedContext context) { return OnMessageReceived(context); @@ -69,7 +66,6 @@ public virtual Task MessageReceived(MessageReceivedContext context) /// /// Invoked when a wsignoutcleanup request is received at the RemoteSignOutPath endpoint. /// - /// public virtual Task RemoteSignOut(RemoteSignOutContext context) { return OnRemoteSignOut(context); @@ -78,7 +74,6 @@ public virtual Task RemoteSignOut(RemoteSignOutContext context) /// /// Invoked with the security token that has been extracted from the protocol message. /// - /// public virtual Task SecurityTokenReceived(SecurityTokenReceivedContext context) { return OnSecurityTokenReceived(context); @@ -87,7 +82,6 @@ public virtual Task SecurityTokenReceived(SecurityTokenReceivedContext context) /// /// Invoked after the security token has passed validation and a ClaimsIdentity has been generated. /// - /// public virtual Task SecurityTokenValidated(SecurityTokenValidatedContext context) { return OnSecurityTokenValidated(context); diff --git a/src/Authentication.Saml2/source/Saml2Handler.cs b/src/Authentication.Saml2/source/Saml2Handler.cs index 8e283ed..03922f3 100644 --- a/src/Authentication.Saml2/source/Saml2Handler.cs +++ b/src/Authentication.Saml2/source/Saml2Handler.cs @@ -16,7 +16,6 @@ namespace Passingwind.AspNetCore.Authentication.Saml2; public class Saml2Handler : RemoteAuthenticationHandler, IAuthenticationSignOutHandler { private const string RelayStateName = "State"; - private const string CorrelationProperty = ".xsrf"; private Saml2Configuration? _configuration; @@ -26,9 +25,23 @@ public class Saml2Handler : RemoteAuthenticationHandler, IAuthenti set => base.Events = value; } +#if NET8_0_OR_GREATER + /// + public Saml2Handler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder) : base(options, logger, encoder) + { + } + /// + [Obsolete("ISystemClock is obsolete, use TimeProvider on AuthenticationSchemeOptions instead.")] + public Saml2Handler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) + { + } + +#else + /// public Saml2Handler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { } +#endif public override async Task HandleRequestAsync() { @@ -54,20 +67,20 @@ protected override async Task HandleChallengeAsync(AuthenticationProperties prop properties.RedirectUri = OriginalPathBase + OriginalPath + Request.QueryString; } - GenerateCorrelationId(properties); - Saml2AuthnRequest saml2AuthnRequest = new(_configuration) { ForceAuthn = Options.ForceAuthn, }; - Dictionary relayStateQuery = new(); + Dictionary relayStateQuery = []; if (!string.IsNullOrEmpty(properties.RedirectUri)) { relayStateQuery[Options.ReturnUrlParameter] = properties.RedirectUri; } + GenerateCorrelationId(properties); + relayStateQuery[RelayStateName] = Options.StateDataFormat.Protect(properties); Saml2RedirectBinding binding = new(); @@ -96,7 +109,7 @@ protected override async Task HandleChallengeAsync(AuthenticationProperties prop public Task SignOutAsync(AuthenticationProperties? properties) { - var target = ResolveTarget(Options.ForwardSignOut); + string? target = ResolveTarget(Options.ForwardSignOut); return (target != null) ? Context.SignOutAsync(target, properties) : HandleSignOutAsync(properties ?? new AuthenticationProperties()); @@ -107,8 +120,8 @@ protected virtual async Task HandleSignOutAsync(AuthenticationProperties? proper _configuration ??= await Options.ConfigurationManager.GetConfigurationAsync(Context.RequestAborted); Saml2StatusCodes status; - var requestBinding = new Saml2PostBinding(); - var logoutRequest = new Saml2LogoutRequest(_configuration, Context.User); + Saml2PostBinding requestBinding = new(); + Saml2LogoutRequest logoutRequest = new(_configuration, Context.User); try { @@ -123,12 +136,12 @@ protected virtual async Task HandleSignOutAsync(AuthenticationProperties? proper status = Saml2StatusCodes.RequestDenied; } - var responseBinding = new Saml2PostBinding + Saml2PostBinding responseBinding = new() { RelayState = requestBinding.RelayState }; - var saml2LogoutResponse = new Saml2LogoutResponse(_configuration) + Saml2LogoutResponse saml2LogoutResponse = new(_configuration) { InResponseToAsString = logoutRequest.IdAsString, Status = status, @@ -176,14 +189,12 @@ protected override async Task HandleRemoteAuthenticateAsync throw new AuthenticationException($"Saml2 response method '{Request.Method}' not support"); } - if (!relayStateQuery.ContainsKey(RelayStateName)) + if (!relayStateQuery.TryGetValue(RelayStateName, out string? relayStateValue)) { throw new AuthenticationException("Saml2 response missing relay state "); } - string state = relayStateQuery[RelayStateName]; - - properties = Options.StateDataFormat.Unprotect(state); + properties = Options.StateDataFormat.Unprotect(relayStateValue); MessageReceivedContext messageReceivedContext = new(Context, Scheme, Options, properties) { @@ -198,9 +209,7 @@ protected override async Task HandleRemoteAuthenticateAsync saml2AuthnResponse = messageReceivedContext.Saml2AuthnResponse; properties = messageReceivedContext.Properties!; // Provides a new instance if not set. - // If state did flow from the challenge then validate it. See AllowUnsolicitedLogins above. - if (properties.Items.TryGetValue(CorrelationProperty, out string? correlationId) - && !ValidateCorrelationId(properties)) + if (!ValidateCorrelationId(properties)) { return HandleRequestResult.Fail("Correlation failed.", properties); } diff --git a/src/Authentication.Saml2/source/Saml2OptionsConfigureOptions.cs b/src/Authentication.Saml2/source/Saml2OptionsConfigureOptions.cs deleted file mode 100644 index 223a875..0000000 --- a/src/Authentication.Saml2/source/Saml2OptionsConfigureOptions.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using Microsoft.Extensions.Options; - -namespace Passingwind.AspNetCore.Authentication.Saml2; - -public class Saml2OptionsConfigureOptions : IConfigureNamedOptions -{ - public void Configure(string name, Saml2Options options) - { - throw new NotImplementedException(); - } - - public void Configure(Saml2Options options) - { - throw new NotImplementedException(); - } -} \ No newline at end of file diff --git a/src/Authentication.Saml2/source/Saml2PostConfigureOptions.cs b/src/Authentication.Saml2/source/Saml2PostConfigureOptions.cs index 5651dd3..ee8f5ea 100644 --- a/src/Authentication.Saml2/source/Saml2PostConfigureOptions.cs +++ b/src/Authentication.Saml2/source/Saml2PostConfigureOptions.cs @@ -16,17 +16,14 @@ public Saml2PostConfigureOptions(IDataProtectionProvider dp) _dp = dp; } - public void PostConfigure(string name, Saml2Options options) + public void PostConfigure(string? name, Saml2Options options) { if (string.IsNullOrEmpty(name)) { throw new ArgumentException($"'{nameof(name)}' cannot be null or empty.", nameof(name)); } - if (options is null) - { - throw new ArgumentNullException(nameof(options)); - } + ArgumentNullException.ThrowIfNull(options); if (string.IsNullOrEmpty(options.SignOutScheme)) { @@ -38,7 +35,7 @@ public void PostConfigure(string name, Saml2Options options) if (options.Backchannel == null) { options.Backchannel = new HttpClient(options.BackchannelHttpHandler ?? new HttpClientHandler()); - options.Backchannel.DefaultRequestHeaders.UserAgent.ParseAdd("Saml2 handler"); + options.Backchannel.DefaultRequestHeaders.UserAgent.ParseAdd("SAML2 handler"); options.Backchannel.Timeout = options.BackchannelTimeout; options.Backchannel.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB } diff --git a/src/SwaggerExtensions/source/Passingwind.SwaggerExtensions.csproj b/src/SwaggerExtensions/source/Passingwind.SwaggerExtensions.csproj index f72d172..29b1a04 100644 --- a/src/SwaggerExtensions/source/Passingwind.SwaggerExtensions.csproj +++ b/src/SwaggerExtensions/source/Passingwind.SwaggerExtensions.csproj @@ -1,4 +1,4 @@ - + netstandard2.0 @@ -26,7 +26,7 @@ - +