From e755f6017c1be34d25c9381af87f50d1b31abe40 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Fri, 2 Oct 2020 13:12:16 -0700 Subject: [PATCH] Add docs for Auth, Auth.Cookies, Auth.Certificate (#26503) * Add docs for Auth, Auth.Cookies, Auth.Certificate Contributes to https://github.com/dotnet/aspnetcore/issues/26397 * Also add JWT * Apply suggestions from code review Co-authored-by: Hao Kung Co-authored-by: Chris Ross * Update src/Security/Authentication/Core/src/TicketSerializer.cs * Update src/Security/Authentication/Core/src/TicketSerializer.cs * Update src/Security/Authentication/Core/src/TicketSerializer.cs * Apply suggestions from code review Co-authored-by: Hao Kung Co-authored-by: Chris Ross --- .../CertificateAuthenticationExtensions.cs | 26 +++++++ .../src/CertificateAuthenticationOptions.cs | 18 +++++ .../src/CertificateValidationCache.cs | 8 +- .../src/CertificateValidationCacheOptions.cs | 11 +-- ...pNetCore.Authentication.Certificate.csproj | 3 +- .../Cookies/src/CookieAuthenticationEvents.cs | 53 +++++++------ .../src/CookieAuthenticationHandler.cs | 17 +++++ .../Cookies/src/CookieExtensions.cs | 52 +++++++++++++ ...t.AspNetCore.Authentication.Cookies.csproj | 2 +- ...ostConfigureCookieAuthenticationOptions.cs | 4 + .../Core/src/AuthenticationBuilder.cs | 2 +- .../Core/src/AuthenticationHandler.cs | 74 ++++++++++++++++++- .../Core/src/AuthenticationMiddleware.cs | 17 ++++- ...thenticationServiceCollectionExtensions.cs | 22 +++++- .../Core/src/Events/AccessDeniedContext.cs | 6 ++ .../Core/src/Events/HandleRequestContext.cs | 10 +++ .../src/Events/RemoteAuthenticationContext.cs | 8 ++ .../src/Events/RemoteAuthenticationEvents.cs | 15 +++- .../Core/src/Events/RemoteFailureContext.cs | 7 ++ .../Core/src/Events/ResultContext.cs | 2 +- .../Core/src/Events/TicketReceivedContext.cs | 11 ++- .../Core/src/HandleRequestResult.cs | 4 + .../Core/src/IDataSerializer.cs | 14 ++++ .../Core/src/ISecureDataFormat.cs | 26 +++++++ .../Authentication/Core/src/ISystemClock.cs | 1 - .../Core/src/JsonDocumentAuthExtensions.cs | 9 +++ ...Microsoft.AspNetCore.Authentication.csproj | 2 +- .../Core/src/PolicySchemeHandler.cs | 12 +++ .../Core/src/PropertiesDataFormat.cs | 8 ++ .../Core/src/PropertiesSerializer.cs | 10 +++ .../Core/src/RemoteAuthenticationHandler.cs | 42 +++++++++++ .../Core/src/RemoteAuthenticationOptions.cs | 3 + .../Core/src/RequestPathBaseCookieBuilder.cs | 4 + .../Core/src/SecureDataFormat.cs | 13 ++++ .../Core/src/SignInAuthenticationHandler.cs | 9 ++- .../Core/src/SignOutAuthenticationHandler.cs | 10 ++- .../Authentication/Core/src/TextEncoder.cs | 3 + .../Core/src/TicketDataFormat.cs | 8 ++ .../Core/src/TicketSerializer.cs | 35 +++++++++ .../src/AuthenticationFailedContext.cs | 12 ++- .../JwtBearer/src/ForbiddenContext.cs | 7 ++ .../src/JwtBearerChallengeContext.cs | 7 ++ .../JwtBearer/src/JwtBearerEvents.cs | 17 ++++- .../JwtBearer/src/JwtBearerExtensions.cs | 41 ++++++++++ .../JwtBearer/src/JwtBearerHandler.cs | 11 ++- .../JwtBearer/src/JwtBearerOptions.cs | 5 +- .../JwtBearer/src/MessageReceivedContext.cs | 9 ++- ...AspNetCore.Authentication.JwtBearer.csproj | 4 +- .../JwtBearer/src/TokenValidatedContext.cs | 10 +++ .../ChunkingCookieManager.cs | 3 + 50 files changed, 650 insertions(+), 57 deletions(-) diff --git a/src/Security/Authentication/Certificate/src/CertificateAuthenticationExtensions.cs b/src/Security/Authentication/Certificate/src/CertificateAuthenticationExtensions.cs index 8da8e2e1c9..a100710827 100644 --- a/src/Security/Authentication/Certificate/src/CertificateAuthenticationExtensions.cs +++ b/src/Security/Authentication/Certificate/src/CertificateAuthenticationExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Security.Claims; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Certificate; @@ -15,6 +16,11 @@ namespace Microsoft.Extensions.DependencyInjection { /// /// Adds certificate authentication. + /// + /// Certificate authentication uses a authentication handler that validates client certificate and + /// raises an event where the certificate is resolved to a . + /// See https://tools.ietf.org/html/rfc5246#section-7.4.4 to read more about certicate authentication. + /// /// /// The . /// The . @@ -23,6 +29,11 @@ namespace Microsoft.Extensions.DependencyInjection /// /// Adds certificate authentication. + /// + /// Certificate authentication uses a authentication handler that validates client certificate and + /// raises an event where the certificate is resolved to a . + /// See https://tools.ietf.org/html/rfc5246#section-7.4.4 to read more about certicate authentication. + /// /// /// The . /// @@ -32,6 +43,11 @@ namespace Microsoft.Extensions.DependencyInjection /// /// Adds certificate authentication. + /// + /// Certificate authentication uses a authentication handler that validates client certificate and + /// raises an event where the certificate is resolved to a . + /// See https://tools.ietf.org/html/rfc5246#section-7.4.4 to read more about certicate authentication. + /// /// /// The . /// @@ -41,6 +57,11 @@ namespace Microsoft.Extensions.DependencyInjection /// /// Adds certificate authentication. + /// + /// Certificate authentication uses a authentication handler that validates client certificate and + /// raises an event where the certificate is resolved to a . + /// See https://tools.ietf.org/html/rfc5246#section-7.4.4 to read more about certicate authentication. + /// /// /// The . /// @@ -54,6 +75,11 @@ namespace Microsoft.Extensions.DependencyInjection /// /// Adds certificate authentication. + /// + /// Certificate authentication uses a authentication handler that validates client certificate and + /// raises an event where the certificate is resolved to a . + /// See https://tools.ietf.org/html/rfc5246#section-7.4.4 to read more about certicate authentication. + /// /// /// The . /// diff --git a/src/Security/Authentication/Certificate/src/CertificateAuthenticationOptions.cs b/src/Security/Authentication/Certificate/src/CertificateAuthenticationOptions.cs index 70789514ac..66f3773bf8 100644 --- a/src/Security/Authentication/Certificate/src/CertificateAuthenticationOptions.cs +++ b/src/Security/Authentication/Certificate/src/CertificateAuthenticationOptions.cs @@ -13,6 +13,9 @@ namespace Microsoft.AspNetCore.Authentication.Certificate /// /// Value indicating the types of certificates accepted by the authentication middleware. /// + /// + /// Defaults to . + /// public CertificateTypes AllowedCertificateTypes { get; set; } = CertificateTypes.Chained; /// @@ -23,6 +26,9 @@ namespace Microsoft.AspNetCore.Authentication.Certificate /// /// Method used to validate certificate chains against . /// + /// + /// Defaults to . + /// /// This property must be set to to enable to be used in certificate chain validation. public X509ChainTrustMode ChainTrustValidationMode { get; set; } = X509ChainTrustMode.System; @@ -32,21 +38,33 @@ namespace Microsoft.AspNetCore.Authentication.Certificate /// at all. If the certificate chains to a root CA all certificates in the chain must be validated /// for the client authentication EKU. /// + /// + /// Defaults to . + /// public bool ValidateCertificateUse { get; set; } = true; /// /// Flag indicating whether the client certificate validity period should be checked. /// + /// + /// Defaults to . + /// public bool ValidateValidityPeriod { get; set; } = true; /// /// Specifies which X509 certificates in the chain should be checked for revocation. /// + /// + /// Defaults to . + /// public X509RevocationFlag RevocationFlag { get; set; } = X509RevocationFlag.ExcludeRoot; /// /// Specifies conditions under which verification of certificates in the X509 chain should be conducted. /// + /// + /// Defaults to . + /// public X509RevocationMode RevocationMode { get; set; } = X509RevocationMode.Online; /// diff --git a/src/Security/Authentication/Certificate/src/CertificateValidationCache.cs b/src/Security/Authentication/Certificate/src/CertificateValidationCache.cs index df65030435..63dc7839c9 100644 --- a/src/Security/Authentication/Certificate/src/CertificateValidationCache.cs +++ b/src/Security/Authentication/Certificate/src/CertificateValidationCache.cs @@ -14,9 +14,13 @@ namespace Microsoft.AspNetCore.Authentication.Certificate /// public class CertificateValidationCache : ICertificateValidationCache { - private MemoryCache _cache; - private CertificateValidationCacheOptions _options; + private readonly MemoryCache _cache; + private readonly CertificateValidationCacheOptions _options; + /// + /// Initializes a new instance of . + /// + /// An accessor to public CertificateValidationCache(IOptions options) { _options = options.Value; diff --git a/src/Security/Authentication/Certificate/src/CertificateValidationCacheOptions.cs b/src/Security/Authentication/Certificate/src/CertificateValidationCacheOptions.cs index e8f443c4f5..32b8c9bcce 100644 --- a/src/Security/Authentication/Certificate/src/CertificateValidationCacheOptions.cs +++ b/src/Security/Authentication/Certificate/src/CertificateValidationCacheOptions.cs @@ -1,9 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - using System; namespace Microsoft.AspNetCore.Authentication.Certificate @@ -14,14 +11,18 @@ namespace Microsoft.AspNetCore.Authentication.Certificate public class CertificateValidationCacheOptions { /// - /// The expiration that should be used for entries in the MemoryCache, defaults to 2 minutes. + /// Gets or sets the expiration that should be used for entries in the MemoryCache. /// This is a sliding expiration that will extend each time the certificate is used, so long as the certificate is valid (see X509Certificate2.NotAfter). /// + /// Defaults to 2 minutes. public TimeSpan CacheEntryExpiration { get; set; } = TimeSpan.FromMinutes(2); /// - /// How many validated certificate results to store in the cache, defaults to 1024. + /// Gets or sets the maximum number of validated certificate results that are allowed to cached. /// + /// + /// Defaults to 1024. + /// public int CacheSize { get; set; } = 1024; } } diff --git a/src/Security/Authentication/Certificate/src/Microsoft.AspNetCore.Authentication.Certificate.csproj b/src/Security/Authentication/Certificate/src/Microsoft.AspNetCore.Authentication.Certificate.csproj index 0b0e574160..bab75ff2d2 100644 --- a/src/Security/Authentication/Certificate/src/Microsoft.AspNetCore.Authentication.Certificate.csproj +++ b/src/Security/Authentication/Certificate/src/Microsoft.AspNetCore.Authentication.Certificate.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core middleware that enables an application to support certificate authentication. @@ -6,6 +6,7 @@ $(DefineConstants);SECURITY true aspnetcore;authentication;security;x509;certificate + $(NoWarn.Replace('1591', '')) diff --git a/src/Security/Authentication/Cookies/src/CookieAuthenticationEvents.cs b/src/Security/Authentication/Cookies/src/CookieAuthenticationEvents.cs index a751c3eb53..39a29331e3 100644 --- a/src/Security/Authentication/Cookies/src/CookieAuthenticationEvents.cs +++ b/src/Security/Authentication/Cookies/src/CookieAuthenticationEvents.cs @@ -9,34 +9,32 @@ using Microsoft.Net.Http.Headers; namespace Microsoft.AspNetCore.Authentication.Cookies { /// - /// This default implementation of the ICookieAuthenticationEvents may be used if the - /// application only needs to override a few of the interface methods. This may be used as a base class - /// or may be instantiated directly. + /// Allows subscribing to events raised during cookie authentication. /// public class CookieAuthenticationEvents { /// - /// A delegate assigned to this property will be invoked when the related method is called. + /// Invoked to validate the principal. /// public Func OnValidatePrincipal { get; set; } = context => Task.CompletedTask; /// - /// A delegate assigned to this property will be invoked when the related method is called. + /// Invoked on signing in. /// public Func OnSigningIn { get; set; } = context => Task.CompletedTask; /// - /// A delegate assigned to this property will be invoked when the related method is called. + /// Invoked after sign in has completed. /// public Func OnSignedIn { get; set; } = context => Task.CompletedTask; /// - /// A delegate assigned to this property will be invoked when the related method is called. + /// Invoked on signing out. /// public Func OnSigningOut { get; set; } = context => Task.CompletedTask; /// - /// A delegate assigned to this property will be invoked when the related method is called. + /// Invoked when the client needs to be redirected to the sign in url. /// public Func, Task> OnRedirectToLogin { get; set; } = context => { @@ -53,7 +51,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies }; /// - /// A delegate assigned to this property will be invoked when the related method is called. + /// Invoked when the client needs to be redirected to the access denied url. /// public Func, Task> OnRedirectToAccessDenied { get; set; } = context => { @@ -70,7 +68,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies }; /// - /// A delegate assigned to this property will be invoked when the related method is called. + /// Invoked when the client is to be redirected to logout. /// public Func, Task> OnRedirectToLogout { get; set; } = context => { @@ -86,7 +84,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies }; /// - /// A delegate assigned to this property will be invoked when the related method is called. + /// Invoked when the client is to be redirected after logout. /// public Func, Task> OnRedirectToReturnUrl { get; set; } = context => { @@ -108,52 +106,51 @@ namespace Microsoft.AspNetCore.Authentication.Cookies } /// - /// Implements the interface method by invoking the related delegate method. + /// Invoked to validate the prinicipal. /// - /// - /// + /// The . public virtual Task ValidatePrincipal(CookieValidatePrincipalContext context) => OnValidatePrincipal(context); /// - /// Implements the interface method by invoking the related delegate method. + /// Invoked during sign in. /// - /// + /// The . public virtual Task SigningIn(CookieSigningInContext context) => OnSigningIn(context); /// - /// Implements the interface method by invoking the related delegate method. + /// Invoked after sign in has completed. /// - /// + /// The . public virtual Task SignedIn(CookieSignedInContext context) => OnSignedIn(context); /// - /// Implements the interface method by invoking the related delegate method. + /// Invoked on sign out. /// - /// + /// The . public virtual Task SigningOut(CookieSigningOutContext context) => OnSigningOut(context); /// - /// Implements the interface method by invoking the related delegate method. + /// Invoked when the client is being redirected to the log out url. /// - /// Contains information about the event + /// The . public virtual Task RedirectToLogout(RedirectContext context) => OnRedirectToLogout(context); /// - /// Implements the interface method by invoking the related delegate method. + /// Invoked when the client is being redirected to the log in url. /// - /// Contains information about the event + /// The . public virtual Task RedirectToLogin(RedirectContext context) => OnRedirectToLogin(context); /// - /// Implements the interface method by invoking the related delegate method. + /// Invoked when the client is being redirected after log out. /// - /// Contains information about the event + /// The . public virtual Task RedirectToReturnUrl(RedirectContext context) => OnRedirectToReturnUrl(context); /// - /// Implements the interface method by invoking the related delegate method. + /// Invoked when the client is being redirected to the access denied url. /// - /// Contains information about the event + /// The . public virtual Task RedirectToAccessDenied(RedirectContext context) => OnRedirectToAccessDenied(context); } } diff --git a/src/Security/Authentication/Cookies/src/CookieAuthenticationHandler.cs b/src/Security/Authentication/Cookies/src/CookieAuthenticationHandler.cs index f10e6114cd..bc257c9d71 100644 --- a/src/Security/Authentication/Cookies/src/CookieAuthenticationHandler.cs +++ b/src/Security/Authentication/Cookies/src/CookieAuthenticationHandler.cs @@ -15,6 +15,9 @@ using Microsoft.Net.Http.Headers; namespace Microsoft.AspNetCore.Authentication.Cookies { + /// + /// Implementation for the cookie-based authentication handler. + /// public class CookieAuthenticationHandler : SignInAuthenticationHandler { private const string HeaderValueNoCache = "no-cache"; @@ -32,6 +35,13 @@ namespace Microsoft.AspNetCore.Authentication.Cookies private Task? _readCookieTask; private AuthenticationTicket? _refreshTicket; + /// + /// Initializes a new instance of . + /// + /// Accessor to . + /// The . + /// The . + /// The . public CookieAuthenticationHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { } @@ -46,6 +56,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies set { base.Events = value; } } + /// protected override Task InitializeHandlerAsync() { // Cookies needs to finish the response @@ -169,6 +180,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies return AuthenticateResult.Success(ticket); } + /// protected override async Task HandleAuthenticateAsync() { var result = await EnsureCookieTicket(); @@ -203,6 +215,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies return cookieOptions; } + /// protected virtual async Task FinishResponseAsync() { // Only renew if requested, and neither sign in or sign out was called @@ -254,6 +267,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies } } + /// protected async override Task HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties? properties) { if (user == null) @@ -346,6 +360,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies Logger.AuthenticationSchemeSignedIn(Scheme.Name); } + /// protected async override Task HandleSignOutAsync(AuthenticationProperties? properties) { properties = properties ?? new AuthenticationProperties(); @@ -426,6 +441,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies return path[0] == '/' && path[1] != '/' && path[1] != '\\'; } + /// protected override async Task HandleForbiddenAsync(AuthenticationProperties properties) { var returnUrl = properties.RedirectUri; @@ -438,6 +454,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies await Events.RedirectToAccessDenied(redirectContext); } + /// protected override async Task HandleChallengeAsync(AuthenticationProperties properties) { var redirectUri = properties.RedirectUri; diff --git a/src/Security/Authentication/Cookies/src/CookieExtensions.cs b/src/Security/Authentication/Cookies/src/CookieExtensions.cs index 252bfe988c..23680542e6 100644 --- a/src/Security/Authentication/Cookies/src/CookieExtensions.cs +++ b/src/Security/Authentication/Cookies/src/CookieExtensions.cs @@ -9,20 +9,72 @@ using Microsoft.Extensions.Options; namespace Microsoft.Extensions.DependencyInjection { + /// + /// Extension methods to configure cookie authentication. + /// public static class CookieExtensions { + /// + /// Adds cookie authentication to using the default scheme. + /// The default scheme is specified by . + /// + /// Cookie authentication uses a HTTP cookie persisted in the client to perform authentication. + /// + /// + /// The . + /// A reference to after the operation has completed. public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder) => builder.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme); + /// + /// Adds cookie authentication to using the specified scheme. + /// + /// Cookie authentication uses a HTTP cookie persisted in the client to perform authentication. + /// + /// + /// The . + /// The authentication scheme. + /// A reference to after the operation has completed. public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, string authenticationScheme) => builder.AddCookie(authenticationScheme, configureOptions: null!); + /// + /// Adds cookie authentication to using the default scheme. + /// The default scheme is specified by . + /// + /// Cookie authentication uses a HTTP cookie persisted in the client to perform authentication. + /// + /// + /// The . + /// A delegate to configure . + /// A reference to after the operation has completed. public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, Action configureOptions) => builder.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, configureOptions); + /// + /// Adds cookie authentication to using the specified scheme. + /// + /// Cookie authentication uses a HTTP cookie persisted in the client to perform authentication. + /// + /// + /// The . + /// The authentication scheme. + /// A delegate to configure . + /// A reference to after the operation has completed. public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, string authenticationScheme, Action configureOptions) => builder.AddCookie(authenticationScheme, displayName: null, configureOptions: configureOptions); + /// + /// Adds cookie authentication to using the specified scheme. + /// + /// Cookie authentication uses a HTTP cookie persisted in the client to perform authentication. + /// + /// + /// The . + /// The authentication scheme. + /// A display name for the authentication handler. + /// A delegate to configure . + /// A reference to after the operation has completed. public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, string authenticationScheme, string? displayName, Action configureOptions) { builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton, PostConfigureCookieAuthenticationOptions>()); diff --git a/src/Security/Authentication/Cookies/src/Microsoft.AspNetCore.Authentication.Cookies.csproj b/src/Security/Authentication/Cookies/src/Microsoft.AspNetCore.Authentication.Cookies.csproj index af13015b04..ddb920fc3a 100644 --- a/src/Security/Authentication/Cookies/src/Microsoft.AspNetCore.Authentication.Cookies.csproj +++ b/src/Security/Authentication/Cookies/src/Microsoft.AspNetCore.Authentication.Cookies.csproj @@ -5,7 +5,7 @@ $(DefaultNetCoreTargetFramework) true $(DefineConstants);SECURITY - $(NoWarn);CS1591 + $(NoWarn.Replace('1591', '')) true aspnetcore;authentication;security false diff --git a/src/Security/Authentication/Cookies/src/PostConfigureCookieAuthenticationOptions.cs b/src/Security/Authentication/Cookies/src/PostConfigureCookieAuthenticationOptions.cs index 4892287fb7..5039ae36d7 100644 --- a/src/Security/Authentication/Cookies/src/PostConfigureCookieAuthenticationOptions.cs +++ b/src/Security/Authentication/Cookies/src/PostConfigureCookieAuthenticationOptions.cs @@ -14,6 +14,10 @@ namespace Microsoft.AspNetCore.Authentication.Cookies { private readonly IDataProtectionProvider _dp; + /// + /// Initializes a new instance of . + /// + /// The . public PostConfigureCookieAuthenticationOptions(IDataProtectionProvider dataProtection) { _dp = dataProtection; diff --git a/src/Security/Authentication/Core/src/AuthenticationBuilder.cs b/src/Security/Authentication/Core/src/AuthenticationBuilder.cs index ba461dc4c3..d79b7c4892 100644 --- a/src/Security/Authentication/Core/src/AuthenticationBuilder.cs +++ b/src/Security/Authentication/Core/src/AuthenticationBuilder.cs @@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Authentication public class AuthenticationBuilder { /// - /// Constructor. + /// Initializes a new instance of . /// /// The services being configured. public AuthenticationBuilder(IServiceCollection services) diff --git a/src/Security/Authentication/Core/src/AuthenticationHandler.cs b/src/Security/Authentication/Core/src/AuthenticationHandler.cs index d19286d030..337090a58f 100644 --- a/src/Security/Authentication/Core/src/AuthenticationHandler.cs +++ b/src/Security/Authentication/Core/src/AuthenticationHandler.cs @@ -11,34 +11,73 @@ using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Authentication { + /// + /// An opinionated abstraction for implementing . + /// + /// The type for the options used to configure the authentication handler. public abstract class AuthenticationHandler : IAuthenticationHandler where TOptions : AuthenticationSchemeOptions, new() { private Task? _authenticateTask; + /// + /// Gets or sets the asssociated with this authentication handler. + /// public AuthenticationScheme Scheme { get; private set; } = default!; + + /// + /// Gets or sets the options associated with this authentication handler. + /// public TOptions Options { get; private set; } = default!; + + /// + /// Gets or sets the . + /// protected HttpContext Context { get; private set; } = default!; + /// + /// Gets the associated with the current request. + /// protected HttpRequest Request { get => Context.Request; } + /// + /// Gets the associated with the current request. + /// protected HttpResponse Response { get => Context.Response; } + /// + /// Gets the path as seen by the authentication middleware. + /// protected PathString OriginalPath => Context.Features.Get()?.OriginalPath ?? Request.Path; + /// + /// Gets the path base as seen by the authentication middleware. + /// protected PathString OriginalPathBase => Context.Features.Get()?.OriginalPathBase ?? Request.PathBase; + /// + /// Gets the . + /// protected ILogger Logger { get; } + /// + /// Gets the . + /// protected UrlEncoder UrlEncoder { get; } + /// + /// Gets the . + /// protected ISystemClock Clock { get; } + /// + /// Gets the to detect changes to options. + /// protected IOptionsMonitor OptionsMonitor { get; } /// @@ -47,13 +86,29 @@ namespace Microsoft.AspNetCore.Authentication /// protected virtual object? Events { get; set; } + /// + /// Gets the issuer that should be used when any claims are issued. + /// + /// + /// The ClaimsIssuer configured in , if configured, otherwise . + /// protected virtual string ClaimsIssuer => Options.ClaimsIssuer ?? Scheme.Name; + /// + /// Gets the absolute current url. + /// protected string CurrentUri { get => Request.Scheme + "://" + Request.Host + Request.PathBase + Request.Path + Request.QueryString; } - + + /// + /// Initializes a new instance of . + /// + /// The monitor for the options instance. + /// The . + /// The . + /// The . protected AuthenticationHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) { Logger = logger.CreateLogger(this.GetType().FullName); @@ -113,9 +168,19 @@ namespace Microsoft.AspNetCore.Authentication /// A task protected virtual Task InitializeHandlerAsync() => Task.CompletedTask; + /// + /// Constructs an absolute url for the specified . + /// + /// The path. + /// The absolute url. protected string BuildRedirectUri(string targetPath) => Request.Scheme + "://" + Request.Host + OriginalPathBase + targetPath; + /// + /// Resolves the scheme that this authentication operation is forwarded to. + /// + /// The scheme to forward. One of ForwardAuthenticate, ForwardChallenge, ForwardForbid, ForwardSignIn, or ForwardSignOut. + /// The forwarded scheme or . protected virtual string? ResolveTarget(string? scheme) { var target = scheme ?? Options.ForwardDefaultSelector?.Invoke(Context) ?? Options.ForwardDefault; @@ -126,6 +191,7 @@ namespace Microsoft.AspNetCore.Authentication : target; } + /// public async Task AuthenticateAsync() { var target = ResolveTarget(Options.ForwardAuthenticate); @@ -186,6 +252,10 @@ namespace Microsoft.AspNetCore.Authentication } } + /// + /// Allows derived types to handle authentication. + /// + /// The . protected abstract Task HandleAuthenticateAsync(); /// @@ -212,6 +282,7 @@ namespace Microsoft.AspNetCore.Authentication return Task.CompletedTask; } + /// public async Task ChallengeAsync(AuthenticationProperties? properties) { var target = ResolveTarget(Options.ForwardChallenge); @@ -226,6 +297,7 @@ namespace Microsoft.AspNetCore.Authentication Logger.AuthenticationSchemeChallenged(Scheme.Name); } + /// public async Task ForbidAsync(AuthenticationProperties? properties) { var target = ResolveTarget(Options.ForwardForbid); diff --git a/src/Security/Authentication/Core/src/AuthenticationMiddleware.cs b/src/Security/Authentication/Core/src/AuthenticationMiddleware.cs index 0c62cc3c39..8a1fa97b0a 100644 --- a/src/Security/Authentication/Core/src/AuthenticationMiddleware.cs +++ b/src/Security/Authentication/Core/src/AuthenticationMiddleware.cs @@ -8,10 +8,18 @@ using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Authentication { + /// + /// Middleware that performs authentication. + /// public class AuthenticationMiddleware { private readonly RequestDelegate _next; + /// + /// Initializes a new instance of . + /// + /// The next item in the middleware pipeline. + /// The . public AuthenticationMiddleware(RequestDelegate next, IAuthenticationSchemeProvider schemes) { if (next == null) @@ -27,8 +35,15 @@ namespace Microsoft.AspNetCore.Authentication Schemes = schemes; } + /// + /// Gets or sets the . + /// public IAuthenticationSchemeProvider Schemes { get; set; } + /// + /// Invokes the middleware performing authentication. + /// + /// The . public async Task Invoke(HttpContext context) { context.Features.Set(new AuthenticationFeature @@ -61,4 +76,4 @@ namespace Microsoft.AspNetCore.Authentication await _next(context); } } -} \ No newline at end of file +} diff --git a/src/Security/Authentication/Core/src/AuthenticationServiceCollectionExtensions.cs b/src/Security/Authentication/Core/src/AuthenticationServiceCollectionExtensions.cs index 70e707f34d..b9c86a37ea 100644 --- a/src/Security/Authentication/Core/src/AuthenticationServiceCollectionExtensions.cs +++ b/src/Security/Authentication/Core/src/AuthenticationServiceCollectionExtensions.cs @@ -13,6 +13,11 @@ namespace Microsoft.Extensions.DependencyInjection /// public static class AuthenticationServiceCollectionExtensions { + /// + /// Registers services required by authentication services. + /// + /// The . + /// A that can be used to further configure authentication. public static AuthenticationBuilder AddAuthentication(this IServiceCollection services) { if (services == null) @@ -27,10 +32,24 @@ namespace Microsoft.Extensions.DependencyInjection return new AuthenticationBuilder(services); } + /// + /// Registers services required by authentication services. specifies the name of the + /// scheme to use by default when a specific scheme isn't requested. + /// + /// The . + /// The default scheme used as a fallback for all other schemes. + /// A that can be used to further configure authentication. public static AuthenticationBuilder AddAuthentication(this IServiceCollection services, string defaultScheme) => services.AddAuthentication(o => o.DefaultScheme = defaultScheme); - public static AuthenticationBuilder AddAuthentication(this IServiceCollection services, Action configureOptions) { + /// + /// Registers services required by authentication services and configures . + /// + /// The . + /// A delegate to configure . + /// A that can be used to further configure authentication. + public static AuthenticationBuilder AddAuthentication(this IServiceCollection services, Action configureOptions) + { if (services == null) { throw new ArgumentNullException(nameof(services)); @@ -61,6 +80,5 @@ namespace Microsoft.Extensions.DependencyInjection options.SignInScheme ??= _authOptions.DefaultSignInScheme; } } - } } diff --git a/src/Security/Authentication/Core/src/Events/AccessDeniedContext.cs b/src/Security/Authentication/Core/src/Events/AccessDeniedContext.cs index 30cfee4e69..969c819974 100644 --- a/src/Security/Authentication/Core/src/Events/AccessDeniedContext.cs +++ b/src/Security/Authentication/Core/src/Events/AccessDeniedContext.cs @@ -10,6 +10,12 @@ namespace Microsoft.AspNetCore.Authentication /// public class AccessDeniedContext : HandleRequestContext { + /// + /// Initializes a new instance of . + /// + /// The . + /// The . + /// The . public AccessDeniedContext( HttpContext context, AuthenticationScheme scheme, diff --git a/src/Security/Authentication/Core/src/Events/HandleRequestContext.cs b/src/Security/Authentication/Core/src/Events/HandleRequestContext.cs index d31cc921e2..b55ea24066 100644 --- a/src/Security/Authentication/Core/src/Events/HandleRequestContext.cs +++ b/src/Security/Authentication/Core/src/Events/HandleRequestContext.cs @@ -5,8 +5,18 @@ using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Authentication { + /// + /// Base context type for handling authentication request. + /// + /// public class HandleRequestContext : BaseContext where TOptions : AuthenticationSchemeOptions { + /// + /// Initializes a new instance of . + /// + /// The . + /// The . + /// The authentication scheme options. protected HandleRequestContext( HttpContext context, AuthenticationScheme scheme, diff --git a/src/Security/Authentication/Core/src/Events/RemoteAuthenticationContext.cs b/src/Security/Authentication/Core/src/Events/RemoteAuthenticationContext.cs index 76b42239bc..de21178a8e 100644 --- a/src/Security/Authentication/Core/src/Events/RemoteAuthenticationContext.cs +++ b/src/Security/Authentication/Core/src/Events/RemoteAuthenticationContext.cs @@ -42,8 +42,16 @@ namespace Microsoft.AspNetCore.Authentication /// public void Success() => Result = HandleRequestResult.Success(new AuthenticationTicket(Principal!, Properties, Scheme.Name)); + /// + /// Indicates that authentication failed. + /// + /// The exception associated with the failure. public void Fail(Exception failure) => Result = HandleRequestResult.Fail(failure); + /// + /// Indicates that authentication failed. + /// + /// The exception associated with the failure. public void Fail(string failureMessage) => Result = HandleRequestResult.Fail(failureMessage); } } diff --git a/src/Security/Authentication/Core/src/Events/RemoteAuthenticationEvents.cs b/src/Security/Authentication/Core/src/Events/RemoteAuthenticationEvents.cs index be4c6ab49e..6804702c7b 100644 --- a/src/Security/Authentication/Core/src/Events/RemoteAuthenticationEvents.cs +++ b/src/Security/Authentication/Core/src/Events/RemoteAuthenticationEvents.cs @@ -6,11 +6,24 @@ using System.Threading.Tasks; namespace Microsoft.AspNetCore.Authentication { + /// + /// Allows subscribing to events raised during remote authentication. + /// public class RemoteAuthenticationEvents { + /// + /// Invoked when an access denied error was returned by the remote server. + /// public Func OnAccessDenied { get; set; } = context => Task.CompletedTask; + + /// + /// Invoked when there is a remote failure. + /// public Func OnRemoteFailure { get; set; } = context => Task.CompletedTask; + /// + /// Invoked after the remote ticket has been received. + /// public Func OnTicketReceived { get; set; } = context => Task.CompletedTask; /// @@ -28,4 +41,4 @@ namespace Microsoft.AspNetCore.Authentication /// public virtual Task TicketReceived(TicketReceivedContext context) => OnTicketReceived(context); } -} \ No newline at end of file +} diff --git a/src/Security/Authentication/Core/src/Events/RemoteFailureContext.cs b/src/Security/Authentication/Core/src/Events/RemoteFailureContext.cs index c39956aa3f..44d5a507ff 100644 --- a/src/Security/Authentication/Core/src/Events/RemoteFailureContext.cs +++ b/src/Security/Authentication/Core/src/Events/RemoteFailureContext.cs @@ -11,6 +11,13 @@ namespace Microsoft.AspNetCore.Authentication /// public class RemoteFailureContext : HandleRequestContext { + /// + /// Initializes a new instance of . + /// + /// The . + /// The . + /// The . + /// User friendly error message for the error. public RemoteFailureContext( HttpContext context, AuthenticationScheme scheme, diff --git a/src/Security/Authentication/Core/src/Events/ResultContext.cs b/src/Security/Authentication/Core/src/Events/ResultContext.cs index b8ca95b43e..43ca3eefab 100644 --- a/src/Security/Authentication/Core/src/Events/ResultContext.cs +++ b/src/Security/Authentication/Core/src/Events/ResultContext.cs @@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Authentication private AuthenticationProperties? _properties; /// - /// Constructor. + /// Initializes a new instance of . /// /// The context. /// The authentication scheme. diff --git a/src/Security/Authentication/Core/src/Events/TicketReceivedContext.cs b/src/Security/Authentication/Core/src/Events/TicketReceivedContext.cs index 665cb2769a..63270bcebe 100644 --- a/src/Security/Authentication/Core/src/Events/TicketReceivedContext.cs +++ b/src/Security/Authentication/Core/src/Events/TicketReceivedContext.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System.Security.Claims; using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Authentication @@ -11,6 +10,13 @@ namespace Microsoft.AspNetCore.Authentication /// public class TicketReceivedContext : RemoteAuthenticationContext { + /// + /// Initializes a new instance of . + /// + /// The . + /// The . + /// The . + /// The received ticket. public TicketReceivedContext( HttpContext context, AuthenticationScheme scheme, @@ -19,6 +25,9 @@ namespace Microsoft.AspNetCore.Authentication : base(context, scheme, options, ticket?.Properties) => Principal = ticket?.Principal; + /// + /// Gets or sets the URL to redirect to after signin. + /// public string? ReturnUri { get; set; } } } diff --git a/src/Security/Authentication/Core/src/HandleRequestResult.cs b/src/Security/Authentication/Core/src/HandleRequestResult.cs index 0a9a179db3..606517218d 100644 --- a/src/Security/Authentication/Core/src/HandleRequestResult.cs +++ b/src/Security/Authentication/Core/src/HandleRequestResult.cs @@ -93,6 +93,10 @@ namespace Microsoft.AspNetCore.Authentication return new HandleRequestResult() { Skipped = true }; } + /// + /// Indicates that there were no results produced during authentication. + /// + /// The result. public new static HandleRequestResult NoResult() { return new HandleRequestResult() { None = true }; diff --git a/src/Security/Authentication/Core/src/IDataSerializer.cs b/src/Security/Authentication/Core/src/IDataSerializer.cs index be1367600c..74883f043c 100644 --- a/src/Security/Authentication/Core/src/IDataSerializer.cs +++ b/src/Security/Authentication/Core/src/IDataSerializer.cs @@ -5,10 +5,24 @@ using System.Diagnostics.CodeAnalysis; namespace Microsoft.AspNetCore.Authentication { + /// + /// Contract for serialzing authentication data. + /// + /// The type of the model being serialized. public interface IDataSerializer { + /// + /// Serializes the specified . + /// + /// The value to serialize. + /// The serialized data. byte[] Serialize(TModel model); + /// + /// Deserializes the specified as an instance of type . + /// + /// The bytes being deserialized. + /// The model. [return: MaybeNull] TModel Deserialize(byte[] data); } diff --git a/src/Security/Authentication/Core/src/ISecureDataFormat.cs b/src/Security/Authentication/Core/src/ISecureDataFormat.cs index 56b815440b..6b546101bb 100644 --- a/src/Security/Authentication/Core/src/ISecureDataFormat.cs +++ b/src/Security/Authentication/Core/src/ISecureDataFormat.cs @@ -5,15 +5,41 @@ using System.Diagnostics.CodeAnalysis; namespace Microsoft.AspNetCore.Authentication { + /// + /// A contract for securing data. + /// + /// The type of the data to protect. public interface ISecureDataFormat { + /// + /// Protects the specified . + /// + /// The value to protect + /// The data protected value. string Protect(TData data); + /// + /// Protects the specified for the specified . + /// + /// The value to protect + /// The purpose. + /// A data protected value. string Protect(TData data, string? purpose); + /// + /// Unprotects the specified . + /// + /// The data protected value. + /// An instance of . [return: MaybeNull] TData Unprotect(string protectedText); + /// + /// Unprotects the specified using the specified . + /// + /// The data protected value. + /// The purpose. + /// An instance of . [return: MaybeNull] TData Unprotect(string protectedText, string? purpose); } diff --git a/src/Security/Authentication/Core/src/ISystemClock.cs b/src/Security/Authentication/Core/src/ISystemClock.cs index 5582669861..a51b2fc332 100644 --- a/src/Security/Authentication/Core/src/ISystemClock.cs +++ b/src/Security/Authentication/Core/src/ISystemClock.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - using System; namespace Microsoft.AspNetCore.Authentication diff --git a/src/Security/Authentication/Core/src/JsonDocumentAuthExtensions.cs b/src/Security/Authentication/Core/src/JsonDocumentAuthExtensions.cs index eaa3ea5c30..e67eb7b1dd 100644 --- a/src/Security/Authentication/Core/src/JsonDocumentAuthExtensions.cs +++ b/src/Security/Authentication/Core/src/JsonDocumentAuthExtensions.cs @@ -5,8 +5,17 @@ using System.Text.Json; namespace Microsoft.AspNetCore.Authentication { + /// + /// Authentication extensions to . + /// public static class JsonDocumentAuthExtensions { + /// + /// Gets a string property value from the specified . + /// + /// The . + /// The property name. + /// The property value. public static string? GetString(this JsonElement element, string key) { if (element.TryGetProperty(key, out var property) && property.ValueKind != JsonValueKind.Null) diff --git a/src/Security/Authentication/Core/src/Microsoft.AspNetCore.Authentication.csproj b/src/Security/Authentication/Core/src/Microsoft.AspNetCore.Authentication.csproj index 5d8135751d..71ad2ac0f3 100644 --- a/src/Security/Authentication/Core/src/Microsoft.AspNetCore.Authentication.csproj +++ b/src/Security/Authentication/Core/src/Microsoft.AspNetCore.Authentication.csproj @@ -4,7 +4,7 @@ ASP.NET Core common types used by the various authentication middleware components. $(DefaultNetCoreTargetFramework) true - $(NoWarn);CS1591 + $(NoWarn.Replace('1591', '')) true aspnetcore;authentication;security false diff --git a/src/Security/Authentication/Core/src/PolicySchemeHandler.cs b/src/Security/Authentication/Core/src/PolicySchemeHandler.cs index 3a171f1cf2..eef547f27e 100644 --- a/src/Security/Authentication/Core/src/PolicySchemeHandler.cs +++ b/src/Security/Authentication/Core/src/PolicySchemeHandler.cs @@ -15,21 +15,33 @@ namespace Microsoft.AspNetCore.Authentication /// public class PolicySchemeHandler : SignInAuthenticationHandler { + /// + /// Initializes a new instance of . + /// + /// The monitor for the options instance. + /// The . + /// The . + /// The . public PolicySchemeHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { } + /// protected override Task HandleChallengeAsync(AuthenticationProperties? properties) => throw new NotImplementedException(); + /// protected override Task HandleForbiddenAsync(AuthenticationProperties? properties) => throw new NotImplementedException(); + /// protected override Task HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties? properties) => throw new NotImplementedException(); + /// protected override Task HandleSignOutAsync(AuthenticationProperties? properties) => throw new NotImplementedException(); + /// protected override Task HandleAuthenticateAsync() => throw new NotImplementedException(); } diff --git a/src/Security/Authentication/Core/src/PropertiesDataFormat.cs b/src/Security/Authentication/Core/src/PropertiesDataFormat.cs index cb35d39dee..8690b86169 100644 --- a/src/Security/Authentication/Core/src/PropertiesDataFormat.cs +++ b/src/Security/Authentication/Core/src/PropertiesDataFormat.cs @@ -5,8 +5,16 @@ using Microsoft.AspNetCore.DataProtection; namespace Microsoft.AspNetCore.Authentication { + /// + /// A instance to secure + /// . + /// public class PropertiesDataFormat : SecureDataFormat { + /// + /// Initializes a new instance of . + /// + /// The . public PropertiesDataFormat(IDataProtector protector) : base(new PropertiesSerializer(), protector) { diff --git a/src/Security/Authentication/Core/src/PropertiesSerializer.cs b/src/Security/Authentication/Core/src/PropertiesSerializer.cs index 0789d1e1a1..7c1a69c502 100644 --- a/src/Security/Authentication/Core/src/PropertiesSerializer.cs +++ b/src/Security/Authentication/Core/src/PropertiesSerializer.cs @@ -7,12 +7,19 @@ using System.IO; namespace Microsoft.AspNetCore.Authentication { + /// + /// A for . + /// public class PropertiesSerializer : IDataSerializer { private const int FormatVersion = 1; + /// + /// Gets the default instance of . + /// public static PropertiesSerializer Default { get; } = new PropertiesSerializer(); + /// public virtual byte[] Serialize(AuthenticationProperties model) { using (var memory = new MemoryStream()) @@ -26,6 +33,7 @@ namespace Microsoft.AspNetCore.Authentication } } + /// public virtual AuthenticationProperties? Deserialize(byte[] data) { using (var memory = new MemoryStream(data)) @@ -37,6 +45,7 @@ namespace Microsoft.AspNetCore.Authentication } } + /// public virtual void Write(BinaryWriter writer, AuthenticationProperties properties) { if (writer == null) @@ -59,6 +68,7 @@ namespace Microsoft.AspNetCore.Authentication } } + /// public virtual AuthenticationProperties? Read(BinaryReader reader) { if (reader == null) diff --git a/src/Security/Authentication/Core/src/RemoteAuthenticationHandler.cs b/src/Security/Authentication/Core/src/RemoteAuthenticationHandler.cs index 7d56d3d580..9809663627 100644 --- a/src/Security/Authentication/Core/src/RemoteAuthenticationHandler.cs +++ b/src/Security/Authentication/Core/src/RemoteAuthenticationHandler.cs @@ -12,6 +12,12 @@ using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Authentication { + /// + /// An opinionated abstraction for an that performs authentication using a separately hosted + /// provider. + /// + /// The type for the options used to configure the authentication handler. + public abstract class RemoteAuthenticationHandler : AuthenticationHandler, IAuthenticationRequestHandler where TOptions : RemoteAuthenticationOptions, new() { @@ -19,6 +25,9 @@ namespace Microsoft.AspNetCore.Authentication private const string CorrelationMarker = "N"; private const string AuthSchemeKey = ".AuthScheme"; + /// + /// The authentication scheme used by default for signin. + /// protected string? SignInScheme => Options.SignInScheme; /// @@ -31,15 +40,32 @@ namespace Microsoft.AspNetCore.Authentication set { base.Events = value; } } + /// + /// Initializes a new instance of . + /// + /// The monitor for the options instance. + /// The . + /// The . + /// The . protected RemoteAuthenticationHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { } + + /// protected override Task CreateEventsAsync() => Task.FromResult(new RemoteAuthenticationEvents()); + /// + /// Gets a value that determines if the current authentication request should be handled by . + /// + /// to handle the operation, otherwise . public virtual Task ShouldHandleRequestAsync() => Task.FromResult(Options.CallbackPath == Request.Path); + /// + /// Handles the current authentication request. + /// + /// if authentication was handled, otherwise . public virtual async Task HandleRequestAsync() { if (!await ShouldHandleRequestAsync()) @@ -156,6 +182,7 @@ namespace Microsoft.AspNetCore.Authentication /// protected abstract Task HandleRemoteAuthenticateAsync(); + /// protected override async Task HandleAuthenticateAsync() { var result = await Context.AuthenticateAsync(SignInScheme); @@ -182,9 +209,14 @@ namespace Microsoft.AspNetCore.Authentication return AuthenticateResult.Fail("Remote authentication does not directly support AuthenticateAsync"); } + /// protected override Task HandleForbiddenAsync(AuthenticationProperties properties) => Context.ForbidAsync(SignInScheme); + /// + /// Produces a cookie containing a nonce used to correlate the current remote authentication request. + /// + /// protected virtual void GenerateCorrelationId(AuthenticationProperties properties) { if (properties == null) @@ -205,6 +237,11 @@ namespace Microsoft.AspNetCore.Authentication Response.Cookies.Append(cookieName, CorrelationMarker, cookieOptions); } + /// + /// Validates that the current request correlates wit hthe + /// + /// + /// protected virtual bool ValidateCorrelationId(AuthenticationProperties properties) { if (properties == null) @@ -242,6 +279,11 @@ namespace Microsoft.AspNetCore.Authentication return true; } + /// + /// Derived types may override this method to handle access denied errors. + /// + /// The . + /// The . protected virtual async Task HandleAccessDeniedErrorAsync(AuthenticationProperties properties) { Logger.AccessDeniedError(); diff --git a/src/Security/Authentication/Core/src/RemoteAuthenticationOptions.cs b/src/Security/Authentication/Core/src/RemoteAuthenticationOptions.cs index 933d6e000d..3676a16bc1 100644 --- a/src/Security/Authentication/Core/src/RemoteAuthenticationOptions.cs +++ b/src/Security/Authentication/Core/src/RemoteAuthenticationOptions.cs @@ -117,6 +117,9 @@ namespace Microsoft.AspNetCore.Authentication /// public TimeSpan RemoteAuthenticationTimeout { get; set; } = TimeSpan.FromMinutes(15); + /// + /// Gets or sets a value that allows subscribing to remote authentication events. + /// public new RemoteAuthenticationEvents Events { get => (RemoteAuthenticationEvents)base.Events!; diff --git a/src/Security/Authentication/Core/src/RequestPathBaseCookieBuilder.cs b/src/Security/Authentication/Core/src/RequestPathBaseCookieBuilder.cs index d4f81c85ca..db7e5a5d01 100644 --- a/src/Security/Authentication/Core/src/RequestPathBaseCookieBuilder.cs +++ b/src/Security/Authentication/Core/src/RequestPathBaseCookieBuilder.cs @@ -16,6 +16,10 @@ namespace Microsoft.AspNetCore.Authentication /// protected virtual string? AdditionalPath { get; } + /// + /// Configures if not explicitly configured. + /// + /// public override CookieOptions Build(HttpContext context, DateTimeOffset expiresFrom) { // check if the user has overridden the default value of path. If so, use that instead of our default value. diff --git a/src/Security/Authentication/Core/src/SecureDataFormat.cs b/src/Security/Authentication/Core/src/SecureDataFormat.cs index e53a51e71a..d48b29921c 100644 --- a/src/Security/Authentication/Core/src/SecureDataFormat.cs +++ b/src/Security/Authentication/Core/src/SecureDataFormat.cs @@ -6,22 +6,33 @@ using Microsoft.AspNetCore.DataProtection; namespace Microsoft.AspNetCore.Authentication { + /// + /// An implementation for . + /// + /// public class SecureDataFormat : ISecureDataFormat { private readonly IDataSerializer _serializer; private readonly IDataProtector _protector; + /// + /// Initializes a new instance of . + /// + /// The . + /// The . public SecureDataFormat(IDataSerializer serializer, IDataProtector protector) { _serializer = serializer; _protector = protector; } + /// public string Protect(TData data) { return Protect(data, purpose: null); } + /// public string Protect(TData data, string? purpose) { var userData = _serializer.Serialize(data); @@ -36,12 +47,14 @@ namespace Microsoft.AspNetCore.Authentication return Base64UrlTextEncoder.Encode(protectedData); } + /// [return: MaybeNull] public TData Unprotect(string protectedText) { return Unprotect(protectedText, purpose: null); } + /// [return: MaybeNull] public TData Unprotect(string protectedText, string? purpose) { diff --git a/src/Security/Authentication/Core/src/SignInAuthenticationHandler.cs b/src/Security/Authentication/Core/src/SignInAuthenticationHandler.cs index 064ea47ae0..a5787c768d 100644 --- a/src/Security/Authentication/Core/src/SignInAuthenticationHandler.cs +++ b/src/Security/Authentication/Core/src/SignInAuthenticationHandler.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.Security.Claims; using System.Text.Encodings.Web; using System.Threading.Tasks; @@ -16,9 +15,17 @@ namespace Microsoft.AspNetCore.Authentication public abstract class SignInAuthenticationHandler : SignOutAuthenticationHandler, IAuthenticationSignInHandler where TOptions : AuthenticationSchemeOptions, new() { + /// + /// Initializes a new instance of . + /// + /// The monitor for the options instance. + /// The . + /// The . + /// The . public SignInAuthenticationHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { } + /// public virtual Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties? properties) { var target = ResolveTarget(Options.ForwardSignIn); diff --git a/src/Security/Authentication/Core/src/SignOutAuthenticationHandler.cs b/src/Security/Authentication/Core/src/SignOutAuthenticationHandler.cs index 12b2027fc4..cab34890c0 100644 --- a/src/Security/Authentication/Core/src/SignOutAuthenticationHandler.cs +++ b/src/Security/Authentication/Core/src/SignOutAuthenticationHandler.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.Text.Encodings.Web; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -15,9 +14,17 @@ namespace Microsoft.AspNetCore.Authentication public abstract class SignOutAuthenticationHandler : AuthenticationHandler, IAuthenticationSignOutHandler where TOptions : AuthenticationSchemeOptions, new() { + /// + /// Initializes a new instance of . + /// + /// The monitor for the options instance. + /// The . + /// The . + /// The . public SignOutAuthenticationHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { } + /// public virtual Task SignOutAsync(AuthenticationProperties? properties) { var target = ResolveTarget(Options.ForwardSignOut); @@ -30,7 +37,6 @@ namespace Microsoft.AspNetCore.Authentication /// Override this method to handle SignOut. /// /// - /// A Task. protected abstract Task HandleSignOutAsync(AuthenticationProperties? properties); } } diff --git a/src/Security/Authentication/Core/src/TextEncoder.cs b/src/Security/Authentication/Core/src/TextEncoder.cs index 1f7ecc7184..b161a79fa9 100644 --- a/src/Security/Authentication/Core/src/TextEncoder.cs +++ b/src/Security/Authentication/Core/src/TextEncoder.cs @@ -3,6 +3,9 @@ namespace Microsoft.AspNetCore.Authentication { + /// + /// Allows encoding and decoding base-64 url encoded text. + /// public static class Base64UrlTextEncoder { /// diff --git a/src/Security/Authentication/Core/src/TicketDataFormat.cs b/src/Security/Authentication/Core/src/TicketDataFormat.cs index e43943cfc8..520b64eb02 100644 --- a/src/Security/Authentication/Core/src/TicketDataFormat.cs +++ b/src/Security/Authentication/Core/src/TicketDataFormat.cs @@ -5,8 +5,16 @@ using Microsoft.AspNetCore.DataProtection; namespace Microsoft.AspNetCore.Authentication { + /// + /// A instance to secure + /// . + /// public class TicketDataFormat : SecureDataFormat { + /// + /// Initializes a new instance of . + /// + /// The . public TicketDataFormat(IDataProtector protector) : base(TicketSerializer.Default, protector) { diff --git a/src/Security/Authentication/Core/src/TicketSerializer.cs b/src/Security/Authentication/Core/src/TicketSerializer.cs index 0ef6664675..ff9a9a275e 100644 --- a/src/Security/Authentication/Core/src/TicketSerializer.cs +++ b/src/Security/Authentication/Core/src/TicketSerializer.cs @@ -9,13 +9,20 @@ using System.Security.Claims; namespace Microsoft.AspNetCore.Authentication { // This MUST be kept in sync with Microsoft.Owin.Security.Interop.AspNetTicketSerializer + /// + /// Serializes and deserializes instances. + /// public class TicketSerializer : IDataSerializer { private const string DefaultStringPlaceholder = "\0"; private const int FormatVersion = 5; + /// + /// Gets the default implementation for . + /// public static TicketSerializer Default { get; } = new TicketSerializer(); + /// public virtual byte[] Serialize(AuthenticationTicket ticket) { using (var memory = new MemoryStream()) @@ -28,6 +35,7 @@ namespace Microsoft.AspNetCore.Authentication } } + /// public virtual AuthenticationTicket? Deserialize(byte[] data) { using (var memory = new MemoryStream(data)) @@ -39,6 +47,11 @@ namespace Microsoft.AspNetCore.Authentication } } + /// + /// Writes the using the specified . + /// + /// The . + /// The . public virtual void Write(BinaryWriter writer, AuthenticationTicket ticket) { if (writer == null) @@ -66,6 +79,11 @@ namespace Microsoft.AspNetCore.Authentication PropertiesSerializer.Default.Write(writer, ticket.Properties); } + /// + /// Writes the specified . + /// + /// The . + /// The . protected virtual void WriteIdentity(BinaryWriter writer, ClaimsIdentity identity) { if (writer == null) @@ -114,6 +132,7 @@ namespace Microsoft.AspNetCore.Authentication } } + /// protected virtual void WriteClaim(BinaryWriter writer, Claim claim) { if (writer == null) @@ -142,6 +161,11 @@ namespace Microsoft.AspNetCore.Authentication } } + /// + /// Reads an . + /// + /// The . + /// The if the format is supported, otherwise . public virtual AuthenticationTicket? Read(BinaryReader reader) { if (reader == null) @@ -175,6 +199,11 @@ namespace Microsoft.AspNetCore.Authentication return new AuthenticationTicket(new ClaimsPrincipal(identities), properties, scheme); } + /// + /// Reads a from a . + /// + /// The . + /// The read . protected virtual ClaimsIdentity ReadIdentity(BinaryReader reader) { if (reader == null) @@ -216,6 +245,12 @@ namespace Microsoft.AspNetCore.Authentication return identity; } + /// + /// Reads a and adds it to the specified . + /// + /// The . + /// The to add the claim to. + /// The read . protected virtual Claim ReadClaim(BinaryReader reader, ClaimsIdentity identity) { if (reader == null) diff --git a/src/Security/Authentication/JwtBearer/src/AuthenticationFailedContext.cs b/src/Security/Authentication/JwtBearer/src/AuthenticationFailedContext.cs index 1c2efd6c73..d2cb4d6469 100644 --- a/src/Security/Authentication/JwtBearer/src/AuthenticationFailedContext.cs +++ b/src/Security/Authentication/JwtBearer/src/AuthenticationFailedContext.cs @@ -6,14 +6,24 @@ using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Authentication.JwtBearer { + /// + /// A when authentication has failed. + /// public class AuthenticationFailedContext : ResultContext { + /// + /// Initializes a new instance of . + /// + /// public AuthenticationFailedContext( HttpContext context, AuthenticationScheme scheme, JwtBearerOptions options) : base(context, scheme, options) { } + /// + /// Gets or sets the exception associated with the authentication failure. + /// public Exception Exception { get; set; } } -} \ No newline at end of file +} diff --git a/src/Security/Authentication/JwtBearer/src/ForbiddenContext.cs b/src/Security/Authentication/JwtBearer/src/ForbiddenContext.cs index deb75ee378..36a35cc487 100644 --- a/src/Security/Authentication/JwtBearer/src/ForbiddenContext.cs +++ b/src/Security/Authentication/JwtBearer/src/ForbiddenContext.cs @@ -6,8 +6,15 @@ using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Authentication.JwtBearer { + /// + /// A when access to a resource is forbidden. + /// public class ForbiddenContext : ResultContext { + /// + /// Initializes a new instance of . + /// + /// public ForbiddenContext( HttpContext context, AuthenticationScheme scheme, diff --git a/src/Security/Authentication/JwtBearer/src/JwtBearerChallengeContext.cs b/src/Security/Authentication/JwtBearer/src/JwtBearerChallengeContext.cs index 6500e1e3f7..454cd9ed4a 100644 --- a/src/Security/Authentication/JwtBearer/src/JwtBearerChallengeContext.cs +++ b/src/Security/Authentication/JwtBearer/src/JwtBearerChallengeContext.cs @@ -6,8 +6,15 @@ using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Authentication.JwtBearer { + /// + /// A when access to a resource authenticated using JWT bearer is challenged. + /// public class JwtBearerChallengeContext : PropertiesContext { + /// + /// Initializes a new instance of . + /// + /// public JwtBearerChallengeContext( HttpContext context, AuthenticationScheme scheme, diff --git a/src/Security/Authentication/JwtBearer/src/JwtBearerEvents.cs b/src/Security/Authentication/JwtBearer/src/JwtBearerEvents.cs index c79e342740..be8700528c 100755 --- a/src/Security/Authentication/JwtBearer/src/JwtBearerEvents.cs +++ b/src/Security/Authentication/JwtBearer/src/JwtBearerEvents.cs @@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer public Func OnAuthenticationFailed { get; set; } = context => Task.CompletedTask; /// - /// Invoked if Authorization fails and results in a Forbidden response + /// Invoked if Authorization fails and results in a Forbidden response. /// public Func OnForbidden { get; set; } = context => Task.CompletedTask; @@ -36,14 +36,29 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer /// public Func OnChallenge { get; set; } = context => Task.CompletedTask; + /// + /// 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) => OnAuthenticationFailed(context); + /// + /// Invoked if Authorization fails and results in a Forbidden response + /// public virtual Task Forbidden(ForbiddenContext context) => OnForbidden(context); + /// + /// Invoked when a protocol message is first received. + /// public virtual Task MessageReceived(MessageReceivedContext context) => OnMessageReceived(context); + /// + /// Invoked after the security token has passed validation and a ClaimsIdentity has been generated. + /// public virtual Task TokenValidated(TokenValidatedContext context) => OnTokenValidated(context); + /// + /// Invoked before a challenge is sent back to the caller. + /// public virtual Task Challenge(JwtBearerChallengeContext context) => OnChallenge(context); } } diff --git a/src/Security/Authentication/JwtBearer/src/JwtBearerExtensions.cs b/src/Security/Authentication/JwtBearer/src/JwtBearerExtensions.cs index 334407c0da..c6a0d98ab7 100644 --- a/src/Security/Authentication/JwtBearer/src/JwtBearerExtensions.cs +++ b/src/Security/Authentication/JwtBearer/src/JwtBearerExtensions.cs @@ -9,17 +9,58 @@ using Microsoft.Extensions.Options; namespace Microsoft.Extensions.DependencyInjection { + /// + /// Extension methods to configure JWT bearer authentication. + /// public static class JwtBearerExtensions { + /// + /// Enables JWT-bearer authentication using the default scheme . + /// + /// JWT bearer authentication performs authentication by extracting and validating a JWT token from the Authorization request header. + /// + /// + /// The . + /// A reference to after the operation has completed. public static AuthenticationBuilder AddJwtBearer(this AuthenticationBuilder builder) => builder.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, _ => { }); + /// + /// Enables JWT-bearer authentication using the default scheme . + /// + /// JWT bearer authentication performs authentication by extracting and validating a JWT token from the Authorization request header. + /// + /// + /// The . + /// A delegate that allows configuring . + /// A reference to after the operation has completed. public static AuthenticationBuilder AddJwtBearer(this AuthenticationBuilder builder, Action configureOptions) => builder.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, configureOptions); + /// + /// Enables JWT-bearer authentication using the specified scheme. + /// + /// JWT bearer authentication performs authentication by extracting and validating a JWT token from the Authorization request header. + /// + /// + /// The . + /// The authentication scheme. + /// A delegate that allows configuring . + /// A reference to after the operation has completed. public static AuthenticationBuilder AddJwtBearer(this AuthenticationBuilder builder, string authenticationScheme, Action configureOptions) => builder.AddJwtBearer(authenticationScheme, displayName: null, configureOptions: configureOptions); + /// + /// Enables JWT-bearer authentication using the specified scheme. + /// + /// JWT bearer authentication performs authentication by extracting and validating a JWT token from the Authorization request header. + /// + /// + /// The . + /// The authentication scheme. + /// The display name for the authentication handler. + /// A delegate that allows configuring . + /// A reference to after the operation has completed. public static AuthenticationBuilder AddJwtBearer(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action configureOptions) { builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton, JwtBearerPostConfigureOptions>()); diff --git a/src/Security/Authentication/JwtBearer/src/JwtBearerHandler.cs b/src/Security/Authentication/JwtBearer/src/JwtBearerHandler.cs index f3c851e929..0ad6c8308e 100644 --- a/src/Security/Authentication/JwtBearer/src/JwtBearerHandler.cs +++ b/src/Security/Authentication/JwtBearer/src/JwtBearerHandler.cs @@ -9,7 +9,6 @@ using System.Security.Claims; using System.Text; using System.Text.Encodings.Web; using System.Threading.Tasks; -using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -19,10 +18,17 @@ using Microsoft.Net.Http.Headers; namespace Microsoft.AspNetCore.Authentication.JwtBearer { + /// + /// An that can perform JWT-bearer based authentication. + /// public class JwtBearerHandler : AuthenticationHandler { private OpenIdConnectConfiguration _configuration; + /// + /// Initializes a new instance of . + /// + /// public JwtBearerHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { } @@ -37,6 +43,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer set => base.Events = value; } + /// protected override Task CreateEventsAsync() => Task.FromResult(new JwtBearerEvents()); /// @@ -192,6 +199,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer } } + /// protected override async Task HandleChallengeAsync(AuthenticationProperties properties) { var authResult = await HandleAuthenticateOnceSafeAsync(); @@ -265,6 +273,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer } } + /// protected override Task HandleForbiddenAsync(AuthenticationProperties properties) { var forbiddenContext = new ForbiddenContext(Context, Scheme, Options); diff --git a/src/Security/Authentication/JwtBearer/src/JwtBearerOptions.cs b/src/Security/Authentication/JwtBearer/src/JwtBearerOptions.cs index dff6fc43a7..d3c3790b6a 100644 --- a/src/Security/Authentication/JwtBearer/src/JwtBearerOptions.cs +++ b/src/Security/Authentication/JwtBearer/src/JwtBearerOptions.cs @@ -17,7 +17,10 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer public class JwtBearerOptions : AuthenticationSchemeOptions { private JwtSecurityTokenHandler _defaultHandler = new JwtSecurityTokenHandler(); - + + /// + /// Initializes a new instance of . + /// public JwtBearerOptions() { SecurityTokenValidators = new List { _defaultHandler }; diff --git a/src/Security/Authentication/JwtBearer/src/MessageReceivedContext.cs b/src/Security/Authentication/JwtBearer/src/MessageReceivedContext.cs index 1850ad0492..6a66ab8be4 100644 --- a/src/Security/Authentication/JwtBearer/src/MessageReceivedContext.cs +++ b/src/Security/Authentication/JwtBearer/src/MessageReceivedContext.cs @@ -5,8 +5,15 @@ using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Authentication.JwtBearer { + /// + /// A context for . + /// public class MessageReceivedContext : ResultContext { + /// + /// Initializes a new instance of . + /// + /// public MessageReceivedContext( HttpContext context, AuthenticationScheme scheme, @@ -18,4 +25,4 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer /// public string Token { get; set; } } -} \ No newline at end of file +} diff --git a/src/Security/Authentication/JwtBearer/src/Microsoft.AspNetCore.Authentication.JwtBearer.csproj b/src/Security/Authentication/JwtBearer/src/Microsoft.AspNetCore.Authentication.JwtBearer.csproj index eedf3cb46b..cd06c11182 100644 --- a/src/Security/Authentication/JwtBearer/src/Microsoft.AspNetCore.Authentication.JwtBearer.csproj +++ b/src/Security/Authentication/JwtBearer/src/Microsoft.AspNetCore.Authentication.JwtBearer.csproj @@ -1,9 +1,9 @@ - + ASP.NET Core middleware that enables an application to receive an OpenID Connect bearer token. $(DefaultNetCoreTargetFramework) - $(NoWarn);CS1591 + $(NoWarn.Replace('1591', '')) true aspnetcore;authentication;security diff --git a/src/Security/Authentication/JwtBearer/src/TokenValidatedContext.cs b/src/Security/Authentication/JwtBearer/src/TokenValidatedContext.cs index 39b677b96d..d941de8d8c 100644 --- a/src/Security/Authentication/JwtBearer/src/TokenValidatedContext.cs +++ b/src/Security/Authentication/JwtBearer/src/TokenValidatedContext.cs @@ -6,14 +6,24 @@ using Microsoft.IdentityModel.Tokens; namespace Microsoft.AspNetCore.Authentication.JwtBearer { + /// + /// A context for . + /// public class TokenValidatedContext : ResultContext { + /// + /// Initializes a new instance of . + /// + /// public TokenValidatedContext( HttpContext context, AuthenticationScheme scheme, JwtBearerOptions options) : base(context, scheme, options) { } + /// + /// Gets or sets the validated security token. + /// public SecurityToken SecurityToken { get; set; } } } diff --git a/src/Shared/ChunkingCookieManager/ChunkingCookieManager.cs b/src/Shared/ChunkingCookieManager/ChunkingCookieManager.cs index 395e23d5cc..9511580b8a 100644 --- a/src/Shared/ChunkingCookieManager/ChunkingCookieManager.cs +++ b/src/Shared/ChunkingCookieManager/ChunkingCookieManager.cs @@ -40,6 +40,9 @@ namespace Microsoft.AspNetCore.Internal private const string ChunkKeySuffix = "C"; private const string ChunkCountPrefix = "chunks-"; + /// + /// Initializes a new instance of . + /// public ChunkingCookieManager() { // Lowest common denominator. Safari has the lowest known limit (4093), and we leave little extra just in case.