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 <HaoK@users.noreply.github.com> Co-authored-by: Chris Ross <Tratcher@Outlook.com> * 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 <HaoK@users.noreply.github.com> Co-authored-by: Chris Ross <Tratcher@Outlook.com>
This commit is contained in:
parent
acf1dc45c0
commit
e755f6017c
|
|
@ -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
|
|||
{
|
||||
/// <summary>
|
||||
/// Adds certificate authentication.
|
||||
/// <para>
|
||||
/// Certificate authentication uses a authentication handler that validates client certificate and
|
||||
/// raises an event where the certificate is resolved to a <see cref="ClaimsPrincipal"/>.
|
||||
/// See https://tools.ietf.org/html/rfc5246#section-7.4.4 to read more about certicate authentication.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
|
||||
/// <returns>The <see cref="AuthenticationBuilder"/>.</returns>
|
||||
|
|
@ -23,6 +29,11 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
|
||||
/// <summary>
|
||||
/// Adds certificate authentication.
|
||||
/// <para>
|
||||
/// Certificate authentication uses a authentication handler that validates client certificate and
|
||||
/// raises an event where the certificate is resolved to a <see cref="ClaimsPrincipal"/>.
|
||||
/// See https://tools.ietf.org/html/rfc5246#section-7.4.4 to read more about certicate authentication.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
|
||||
/// <param name="authenticationScheme"></param>
|
||||
|
|
@ -32,6 +43,11 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
|
||||
/// <summary>
|
||||
/// Adds certificate authentication.
|
||||
/// <para>
|
||||
/// Certificate authentication uses a authentication handler that validates client certificate and
|
||||
/// raises an event where the certificate is resolved to a <see cref="ClaimsPrincipal"/>.
|
||||
/// See https://tools.ietf.org/html/rfc5246#section-7.4.4 to read more about certicate authentication.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
|
||||
/// <param name="configureOptions"></param>
|
||||
|
|
@ -41,6 +57,11 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
|
||||
/// <summary>
|
||||
/// Adds certificate authentication.
|
||||
/// <para>
|
||||
/// Certificate authentication uses a authentication handler that validates client certificate and
|
||||
/// raises an event where the certificate is resolved to a <see cref="ClaimsPrincipal"/>.
|
||||
/// See https://tools.ietf.org/html/rfc5246#section-7.4.4 to read more about certicate authentication.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
|
||||
/// <param name="authenticationScheme"></param>
|
||||
|
|
@ -54,6 +75,11 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
|
||||
/// <summary>
|
||||
/// Adds certificate authentication.
|
||||
/// <para>
|
||||
/// Certificate authentication uses a authentication handler that validates client certificate and
|
||||
/// raises an event where the certificate is resolved to a <see cref="ClaimsPrincipal"/>.
|
||||
/// See https://tools.ietf.org/html/rfc5246#section-7.4.4 to read more about certicate authentication.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
|
||||
/// <param name="configureOptions"></param>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ namespace Microsoft.AspNetCore.Authentication.Certificate
|
|||
/// <summary>
|
||||
/// Value indicating the types of certificates accepted by the authentication middleware.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Defaults to <see cref="CertificateTypes.Chained"/>.
|
||||
/// </value>
|
||||
public CertificateTypes AllowedCertificateTypes { get; set; } = CertificateTypes.Chained;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -23,6 +26,9 @@ namespace Microsoft.AspNetCore.Authentication.Certificate
|
|||
/// <summary>
|
||||
/// Method used to validate certificate chains against <see cref="CustomTrustStore"/>.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Defaults to <see cref="X509ChainTrustMode.System"/>.
|
||||
/// </value>
|
||||
/// <remarks>This property must be set to <see cref="X509ChainTrustMode.CustomRootTrust"/> to enable <see cref="CustomTrustStore"/> to be used in certificate chain validation.</remarks>
|
||||
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.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Defaults to <see langword="true" />.
|
||||
/// </value>
|
||||
public bool ValidateCertificateUse { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Flag indicating whether the client certificate validity period should be checked.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Defaults to <see langword="true" />.
|
||||
/// </value>
|
||||
public bool ValidateValidityPeriod { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies which X509 certificates in the chain should be checked for revocation.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Defaults to <see cref="X509RevocationFlag.ExcludeRoot" />.
|
||||
/// </value>
|
||||
public X509RevocationFlag RevocationFlag { get; set; } = X509RevocationFlag.ExcludeRoot;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies conditions under which verification of certificates in the X509 chain should be conducted.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Defaults to <see cref="X509RevocationMode.Online" />.
|
||||
/// </value>
|
||||
public X509RevocationMode RevocationMode { get; set; } = X509RevocationMode.Online;
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -14,9 +14,13 @@ namespace Microsoft.AspNetCore.Authentication.Certificate
|
|||
/// </summary>
|
||||
public class CertificateValidationCache : ICertificateValidationCache
|
||||
{
|
||||
private MemoryCache _cache;
|
||||
private CertificateValidationCacheOptions _options;
|
||||
private readonly MemoryCache _cache;
|
||||
private readonly CertificateValidationCacheOptions _options;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="CertificateValidationCache"/>.
|
||||
/// </summary>
|
||||
/// <param name="options">An accessor to <see cref="CertificateValidationCacheOptions"/></param>
|
||||
public CertificateValidationCache(IOptions<CertificateValidationCacheOptions> options)
|
||||
{
|
||||
_options = options.Value;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 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).
|
||||
/// </summary>
|
||||
/// <value>Defaults to 2 minutes.</value>
|
||||
public TimeSpan CacheEntryExpiration { get; set; } = TimeSpan.FromMinutes(2);
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Defaults to 1024.
|
||||
/// </value>
|
||||
public int CacheSize { get; set; } = 1024;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core middleware that enables an application to support certificate authentication.</Description>
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
<DefineConstants>$(DefineConstants);SECURITY</DefineConstants>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;authentication;security;x509;certificate</PackageTags>
|
||||
<NoWarn>$(NoWarn.Replace('1591', ''))</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -9,34 +9,32 @@ using Microsoft.Net.Http.Headers;
|
|||
namespace Microsoft.AspNetCore.Authentication.Cookies
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public class CookieAuthenticationEvents
|
||||
{
|
||||
/// <summary>
|
||||
/// A delegate assigned to this property will be invoked when the related method is called.
|
||||
/// Invoked to validate the principal.
|
||||
/// </summary>
|
||||
public Func<CookieValidatePrincipalContext, Task> OnValidatePrincipal { get; set; } = context => Task.CompletedTask;
|
||||
|
||||
/// <summary>
|
||||
/// A delegate assigned to this property will be invoked when the related method is called.
|
||||
/// Invoked on signing in.
|
||||
/// </summary>
|
||||
public Func<CookieSigningInContext, Task> OnSigningIn { get; set; } = context => Task.CompletedTask;
|
||||
|
||||
/// <summary>
|
||||
/// A delegate assigned to this property will be invoked when the related method is called.
|
||||
/// Invoked after sign in has completed.
|
||||
/// </summary>
|
||||
public Func<CookieSignedInContext, Task> OnSignedIn { get; set; } = context => Task.CompletedTask;
|
||||
|
||||
/// <summary>
|
||||
/// A delegate assigned to this property will be invoked when the related method is called.
|
||||
/// Invoked on signing out.
|
||||
/// </summary>
|
||||
public Func<CookieSigningOutContext, Task> OnSigningOut { get; set; } = context => Task.CompletedTask;
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public Func<RedirectContext<CookieAuthenticationOptions>, Task> OnRedirectToLogin { get; set; } = context =>
|
||||
{
|
||||
|
|
@ -53,7 +51,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
|
|||
};
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public Func<RedirectContext<CookieAuthenticationOptions>, Task> OnRedirectToAccessDenied { get; set; } = context =>
|
||||
{
|
||||
|
|
@ -70,7 +68,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
|
|||
};
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public Func<RedirectContext<CookieAuthenticationOptions>, Task> OnRedirectToLogout { get; set; } = context =>
|
||||
{
|
||||
|
|
@ -86,7 +84,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
|
|||
};
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public Func<RedirectContext<CookieAuthenticationOptions>, Task> OnRedirectToReturnUrl { get; set; } = context =>
|
||||
{
|
||||
|
|
@ -108,52 +106,51 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements the interface method by invoking the related delegate method.
|
||||
/// Invoked to validate the prinicipal.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="context">The <see cref="CookieValidatePrincipalContext"/>.</param>
|
||||
public virtual Task ValidatePrincipal(CookieValidatePrincipalContext context) => OnValidatePrincipal(context);
|
||||
|
||||
/// <summary>
|
||||
/// Implements the interface method by invoking the related delegate method.
|
||||
/// Invoked during sign in.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="context">The <see cref="CookieSigningInContext"/>.</param>
|
||||
public virtual Task SigningIn(CookieSigningInContext context) => OnSigningIn(context);
|
||||
|
||||
/// <summary>
|
||||
/// Implements the interface method by invoking the related delegate method.
|
||||
/// Invoked after sign in has completed.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="context">The <see cref="CookieSignedInContext"/>.</param>
|
||||
public virtual Task SignedIn(CookieSignedInContext context) => OnSignedIn(context);
|
||||
|
||||
/// <summary>
|
||||
/// Implements the interface method by invoking the related delegate method.
|
||||
/// Invoked on sign out.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="context">The <see cref="CookieSigningOutContext"/>.</param>
|
||||
public virtual Task SigningOut(CookieSigningOutContext context) => OnSigningOut(context);
|
||||
|
||||
/// <summary>
|
||||
/// Implements the interface method by invoking the related delegate method.
|
||||
/// Invoked when the client is being redirected to the log out url.
|
||||
/// </summary>
|
||||
/// <param name="context">Contains information about the event</param>
|
||||
/// <param name="context">The <see cref="RedirectContext{TOptions}"/>.</param>
|
||||
public virtual Task RedirectToLogout(RedirectContext<CookieAuthenticationOptions> context) => OnRedirectToLogout(context);
|
||||
|
||||
/// <summary>
|
||||
/// Implements the interface method by invoking the related delegate method.
|
||||
/// Invoked when the client is being redirected to the log in url.
|
||||
/// </summary>
|
||||
/// <param name="context">Contains information about the event</param>
|
||||
/// <param name="context">The <see cref="RedirectContext{TOptions}"/>.</param>
|
||||
public virtual Task RedirectToLogin(RedirectContext<CookieAuthenticationOptions> context) => OnRedirectToLogin(context);
|
||||
|
||||
/// <summary>
|
||||
/// Implements the interface method by invoking the related delegate method.
|
||||
/// Invoked when the client is being redirected after log out.
|
||||
/// </summary>
|
||||
/// <param name="context">Contains information about the event</param>
|
||||
/// <param name="context">The <see cref="RedirectContext{TOptions}"/>.</param>
|
||||
public virtual Task RedirectToReturnUrl(RedirectContext<CookieAuthenticationOptions> context) => OnRedirectToReturnUrl(context);
|
||||
|
||||
/// <summary>
|
||||
/// Implements the interface method by invoking the related delegate method.
|
||||
/// Invoked when the client is being redirected to the access denied url.
|
||||
/// </summary>
|
||||
/// <param name="context">Contains information about the event</param>
|
||||
/// <param name="context">The <see cref="RedirectContext{TOptions}"/>.</param>
|
||||
public virtual Task RedirectToAccessDenied(RedirectContext<CookieAuthenticationOptions> context) => OnRedirectToAccessDenied(context);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ using Microsoft.Net.Http.Headers;
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication.Cookies
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation for the cookie-based authentication handler.
|
||||
/// </summary>
|
||||
public class CookieAuthenticationHandler : SignInAuthenticationHandler<CookieAuthenticationOptions>
|
||||
{
|
||||
private const string HeaderValueNoCache = "no-cache";
|
||||
|
|
@ -32,6 +35,13 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
|
|||
private Task<AuthenticateResult>? _readCookieTask;
|
||||
private AuthenticationTicket? _refreshTicket;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="CookieAuthenticationHandler"/>.
|
||||
/// </summary>
|
||||
/// <param name="options">Accessor to <see cref="CookieAuthenticationOptions"/>.</param>
|
||||
/// <param name="logger">The <see cref="ILoggerFactory"/>.</param>
|
||||
/// <param name="encoder">The <see cref="UrlEncoder"/>.</param>
|
||||
/// <param name="clock">The <see cref="ISystemClock"/>.</param>
|
||||
public CookieAuthenticationHandler(IOptionsMonitor<CookieAuthenticationOptions> 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; }
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Task InitializeHandlerAsync()
|
||||
{
|
||||
// Cookies needs to finish the response
|
||||
|
|
@ -169,6 +180,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
|
|||
return AuthenticateResult.Success(ticket);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
|
||||
{
|
||||
var result = await EnsureCookieTicket();
|
||||
|
|
@ -203,6 +215,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
|
|||
return cookieOptions;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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] != '\\';
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task HandleForbiddenAsync(AuthenticationProperties properties)
|
||||
{
|
||||
var returnUrl = properties.RedirectUri;
|
||||
|
|
@ -438,6 +454,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
|
|||
await Events.RedirectToAccessDenied(redirectContext);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
|
||||
{
|
||||
var redirectUri = properties.RedirectUri;
|
||||
|
|
|
|||
|
|
@ -9,20 +9,72 @@ using Microsoft.Extensions.Options;
|
|||
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods to configure cookie authentication.
|
||||
/// </summary>
|
||||
public static class CookieExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds cookie authentication to <see cref="AuthenticationBuilder"/> using the default scheme.
|
||||
/// The default scheme is specified by <see cref="CookieAuthenticationDefaults.AuthenticationScheme"/>.
|
||||
/// <para>
|
||||
/// Cookie authentication uses a HTTP cookie persisted in the client to perform authentication.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
|
||||
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
|
||||
public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder)
|
||||
=> builder.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
|
||||
/// <summary>
|
||||
/// Adds cookie authentication to <see cref="AuthenticationBuilder"/> using the specified scheme.
|
||||
/// <para>
|
||||
/// Cookie authentication uses a HTTP cookie persisted in the client to perform authentication.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
|
||||
/// <param name="authenticationScheme">The authentication scheme.</param>
|
||||
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
|
||||
public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, string authenticationScheme)
|
||||
=> builder.AddCookie(authenticationScheme, configureOptions: null!);
|
||||
|
||||
/// <summary>
|
||||
/// Adds cookie authentication to <see cref="AuthenticationBuilder"/> using the default scheme.
|
||||
/// The default scheme is specified by <see cref="CookieAuthenticationDefaults.AuthenticationScheme"/>.
|
||||
/// <para>
|
||||
/// Cookie authentication uses a HTTP cookie persisted in the client to perform authentication.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
|
||||
/// <param name="configureOptions">A delegate to configure <see cref="CookieAuthenticationOptions"/>.</param>
|
||||
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
|
||||
public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, Action<CookieAuthenticationOptions> configureOptions)
|
||||
=> builder.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, configureOptions);
|
||||
|
||||
/// <summary>
|
||||
/// Adds cookie authentication to <see cref="AuthenticationBuilder"/> using the specified scheme.
|
||||
/// <para>
|
||||
/// Cookie authentication uses a HTTP cookie persisted in the client to perform authentication.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
|
||||
/// <param name="authenticationScheme">The authentication scheme.</param>
|
||||
/// <param name="configureOptions">A delegate to configure <see cref="CookieAuthenticationOptions"/>.</param>
|
||||
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
|
||||
public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, string authenticationScheme, Action<CookieAuthenticationOptions> configureOptions)
|
||||
=> builder.AddCookie(authenticationScheme, displayName: null, configureOptions: configureOptions);
|
||||
|
||||
/// <summary>
|
||||
/// Adds cookie authentication to <see cref="AuthenticationBuilder"/> using the specified scheme.
|
||||
/// <para>
|
||||
/// Cookie authentication uses a HTTP cookie persisted in the client to perform authentication.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
|
||||
/// <param name="authenticationScheme">The authentication scheme.</param>
|
||||
/// <param name="displayName">A display name for the authentication handler.</param>
|
||||
/// <param name="configureOptions">A delegate to configure <see cref="CookieAuthenticationOptions"/>.</param>
|
||||
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
|
||||
public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, string authenticationScheme, string? displayName, Action<CookieAuthenticationOptions> configureOptions)
|
||||
{
|
||||
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<CookieAuthenticationOptions>, PostConfigureCookieAuthenticationOptions>());
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
<IsAspNetCoreApp>true</IsAspNetCoreApp>
|
||||
<DefineConstants>$(DefineConstants);SECURITY</DefineConstants>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<NoWarn>$(NoWarn.Replace('1591', ''))</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;authentication;security</PackageTags>
|
||||
<IsPackable>false</IsPackable>
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
|
|||
{
|
||||
private readonly IDataProtectionProvider _dp;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="PostConfigureCookieAuthenticationOptions"/>.
|
||||
/// </summary>
|
||||
/// <param name="dataProtection">The <see cref="IDataProtectionProvider"/>.</param>
|
||||
public PostConfigureCookieAuthenticationOptions(IDataProtectionProvider dataProtection)
|
||||
{
|
||||
_dp = dataProtection;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
public class AuthenticationBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// Initializes a new instance of <see cref="AuthenticationBuilder"/>.
|
||||
/// </summary>
|
||||
/// <param name="services">The services being configured.</param>
|
||||
public AuthenticationBuilder(IServiceCollection services)
|
||||
|
|
|
|||
|
|
@ -11,34 +11,73 @@ using Microsoft.Extensions.Options;
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// An opinionated abstraction for implementing <see cref="IAuthenticationHandler"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TOptions">The type for the options used to configure the authentication handler.</typeparam>
|
||||
public abstract class AuthenticationHandler<TOptions> : IAuthenticationHandler where TOptions : AuthenticationSchemeOptions, new()
|
||||
{
|
||||
private Task<AuthenticateResult>? _authenticateTask;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="AuthenticationScheme"/> asssociated with this authentication handler.
|
||||
/// </summary>
|
||||
public AuthenticationScheme Scheme { get; private set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the options associated with this authentication handler.
|
||||
/// </summary>
|
||||
public TOptions Options { get; private set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="HttpContext"/>.
|
||||
/// </summary>
|
||||
protected HttpContext Context { get; private set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="HttpRequest"/> associated with the current request.
|
||||
/// </summary>
|
||||
protected HttpRequest Request
|
||||
{
|
||||
get => Context.Request;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="HttpResponse" /> associated with the current request.
|
||||
/// </summary>
|
||||
protected HttpResponse Response
|
||||
{
|
||||
get => Context.Response;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path as seen by the authentication middleware.
|
||||
/// </summary>
|
||||
protected PathString OriginalPath => Context.Features.Get<IAuthenticationFeature>()?.OriginalPath ?? Request.Path;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path base as seen by the authentication middleware.
|
||||
/// </summary>
|
||||
protected PathString OriginalPathBase => Context.Features.Get<IAuthenticationFeature>()?.OriginalPathBase ?? Request.PathBase;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ILogger"/>.
|
||||
/// </summary>
|
||||
protected ILogger Logger { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="UrlEncoder"/>.
|
||||
/// </summary>
|
||||
protected UrlEncoder UrlEncoder { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ISystemClock"/>.
|
||||
/// </summary>
|
||||
protected ISystemClock Clock { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IOptionsMonitor{TOptions}"/> to detect changes to options.
|
||||
/// </summary>
|
||||
protected IOptionsMonitor<TOptions> OptionsMonitor { get; }
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -47,13 +86,29 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// </summary>
|
||||
protected virtual object? Events { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the issuer that should be used when any claims are issued.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The <c>ClaimsIssuer</c> configured in <typeparamref name="TOptions"/>, if configured, otherwise <see cref="AuthenticationScheme.Name"/>.
|
||||
/// </value>
|
||||
protected virtual string ClaimsIssuer => Options.ClaimsIssuer ?? Scheme.Name;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the absolute current url.
|
||||
/// </summary>
|
||||
protected string CurrentUri
|
||||
{
|
||||
get => Request.Scheme + "://" + Request.Host + Request.PathBase + Request.Path + Request.QueryString;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="AuthenticationHandler{TOptions}"/>.
|
||||
/// </summary>
|
||||
/// <param name="options">The monitor for the options instance.</param>
|
||||
/// <param name="logger">The <see cref="ILoggerFactory"/>.</param>
|
||||
/// <param name="encoder">The <see cref="System.Text.Encodings.Web.UrlEncoder"/>.</param>
|
||||
/// <param name="clock">The <see cref="ISystemClock"/>.</param>
|
||||
protected AuthenticationHandler(IOptionsMonitor<TOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
|
||||
{
|
||||
Logger = logger.CreateLogger(this.GetType().FullName);
|
||||
|
|
@ -113,9 +168,19 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// <returns>A task</returns>
|
||||
protected virtual Task InitializeHandlerAsync() => Task.CompletedTask;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an absolute url for the specified <paramref name="targetPath"/>.
|
||||
/// </summary>
|
||||
/// <param name="targetPath">The path.</param>
|
||||
/// <returns>The absolute url.</returns>
|
||||
protected string BuildRedirectUri(string targetPath)
|
||||
=> Request.Scheme + "://" + Request.Host + OriginalPathBase + targetPath;
|
||||
|
||||
/// <summary>
|
||||
/// Resolves the scheme that this authentication operation is forwarded to.
|
||||
/// </summary>
|
||||
/// <param name="scheme">The scheme to forward. One of ForwardAuthenticate, ForwardChallenge, ForwardForbid, ForwardSignIn, or ForwardSignOut.</param>
|
||||
/// <returns>The forwarded scheme or <see langword="null"/>.</returns>
|
||||
protected virtual string? ResolveTarget(string? scheme)
|
||||
{
|
||||
var target = scheme ?? Options.ForwardDefaultSelector?.Invoke(Context) ?? Options.ForwardDefault;
|
||||
|
|
@ -126,6 +191,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
: target;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<AuthenticateResult> AuthenticateAsync()
|
||||
{
|
||||
var target = ResolveTarget(Options.ForwardAuthenticate);
|
||||
|
|
@ -186,6 +252,10 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows derived types to handle authentication.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="AuthenticateResult"/>.</returns>
|
||||
protected abstract Task<AuthenticateResult> HandleAuthenticateAsync();
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -212,6 +282,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task ChallengeAsync(AuthenticationProperties? properties)
|
||||
{
|
||||
var target = ResolveTarget(Options.ForwardChallenge);
|
||||
|
|
@ -226,6 +297,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
Logger.AuthenticationSchemeChallenged(Scheme.Name);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task ForbidAsync(AuthenticationProperties? properties)
|
||||
{
|
||||
var target = ResolveTarget(Options.ForwardForbid);
|
||||
|
|
|
|||
|
|
@ -8,10 +8,18 @@ using Microsoft.Extensions.DependencyInjection;
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Middleware that performs authentication.
|
||||
/// </summary>
|
||||
public class AuthenticationMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="AuthenticationMiddleware"/>.
|
||||
/// </summary>
|
||||
/// <param name="next">The next item in the middleware pipeline.</param>
|
||||
/// <param name="schemes">The <see cref="IAuthenticationSchemeProvider"/>.</param>
|
||||
public AuthenticationMiddleware(RequestDelegate next, IAuthenticationSchemeProvider schemes)
|
||||
{
|
||||
if (next == null)
|
||||
|
|
@ -27,8 +35,15 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
Schemes = schemes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="IAuthenticationSchemeProvider"/>.
|
||||
/// </summary>
|
||||
public IAuthenticationSchemeProvider Schemes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the middleware performing authentication.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/>.</param>
|
||||
public async Task Invoke(HttpContext context)
|
||||
{
|
||||
context.Features.Set<IAuthenticationFeature>(new AuthenticationFeature
|
||||
|
|
@ -61,4 +76,4 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
await _next(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,11 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
/// </summary>
|
||||
public static class AuthenticationServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Registers services required by authentication services.
|
||||
/// </summary>
|
||||
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
|
||||
/// <returns>A <see cref="AuthenticationBuilder"/> that can be used to further configure authentication.</returns>
|
||||
public static AuthenticationBuilder AddAuthentication(this IServiceCollection services)
|
||||
{
|
||||
if (services == null)
|
||||
|
|
@ -27,10 +32,24 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
return new AuthenticationBuilder(services);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers services required by authentication services. <paramref name="defaultScheme"/> specifies the name of the
|
||||
/// scheme to use by default when a specific scheme isn't requested.
|
||||
/// </summary>
|
||||
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
|
||||
/// <param name="defaultScheme">The default scheme used as a fallback for all other schemes.</param>
|
||||
/// <returns>A <see cref="AuthenticationBuilder"/> that can be used to further configure authentication.</returns>
|
||||
public static AuthenticationBuilder AddAuthentication(this IServiceCollection services, string defaultScheme)
|
||||
=> services.AddAuthentication(o => o.DefaultScheme = defaultScheme);
|
||||
|
||||
public static AuthenticationBuilder AddAuthentication(this IServiceCollection services, Action<AuthenticationOptions> configureOptions) {
|
||||
/// <summary>
|
||||
/// Registers services required by authentication services and configures <see cref="AuthenticationOptions"/>.
|
||||
/// </summary>
|
||||
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
|
||||
/// <param name="configureOptions">A delegate to configure <see cref="AuthenticationOptions"/>.</param>
|
||||
/// <returns>A <see cref="AuthenticationBuilder"/> that can be used to further configure authentication.</returns>
|
||||
public static AuthenticationBuilder AddAuthentication(this IServiceCollection services, Action<AuthenticationOptions> configureOptions)
|
||||
{
|
||||
if (services == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(services));
|
||||
|
|
@ -61,6 +80,5 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
options.SignInScheme ??= _authOptions.DefaultSignInScheme;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,12 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// </summary>
|
||||
public class AccessDeniedContext : HandleRequestContext<RemoteAuthenticationOptions>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="AccessDeniedContext"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/>.</param>
|
||||
/// <param name="scheme">The <see cref="AuthenticationScheme"/>.</param>
|
||||
/// <param name="options">The <see cref="RemoteAuthenticationOptions"/>.</param>
|
||||
public AccessDeniedContext(
|
||||
HttpContext context,
|
||||
AuthenticationScheme scheme,
|
||||
|
|
|
|||
|
|
@ -5,8 +5,18 @@ using Microsoft.AspNetCore.Http;
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Base context type for handling authentication request.
|
||||
/// </summary>
|
||||
/// <typeparam name="TOptions"></typeparam>
|
||||
public class HandleRequestContext<TOptions> : BaseContext<TOptions> where TOptions : AuthenticationSchemeOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="HandleRequestContext{TOptions}"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/>.</param>
|
||||
/// <param name="scheme">The <see cref="AuthenticationScheme"/>.</param>
|
||||
/// <param name="options">The authentication scheme options.</param>
|
||||
protected HandleRequestContext(
|
||||
HttpContext context,
|
||||
AuthenticationScheme scheme,
|
||||
|
|
|
|||
|
|
@ -42,8 +42,16 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// </summary>
|
||||
public void Success() => Result = HandleRequestResult.Success(new AuthenticationTicket(Principal!, Properties, Scheme.Name));
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that authentication failed.
|
||||
/// </summary>
|
||||
/// <param name="failure">The exception associated with the failure.</param>
|
||||
public void Fail(Exception failure) => Result = HandleRequestResult.Fail(failure);
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that authentication failed.
|
||||
/// </summary>
|
||||
/// <param name="failureMessage">The exception associated with the failure.</param>
|
||||
public void Fail(string failureMessage) => Result = HandleRequestResult.Fail(failureMessage);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,24 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Allows subscribing to events raised during remote authentication.
|
||||
/// </summary>
|
||||
public class RemoteAuthenticationEvents
|
||||
{
|
||||
/// <summary>
|
||||
/// Invoked when an access denied error was returned by the remote server.
|
||||
/// </summary>
|
||||
public Func<AccessDeniedContext, Task> OnAccessDenied { get; set; } = context => Task.CompletedTask;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when there is a remote failure.
|
||||
/// </summary>
|
||||
public Func<RemoteFailureContext, Task> OnRemoteFailure { get; set; } = context => Task.CompletedTask;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked after the remote ticket has been received.
|
||||
/// </summary>
|
||||
public Func<TicketReceivedContext, Task> OnTicketReceived { get; set; } = context => Task.CompletedTask;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -28,4 +41,4 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// </summary>
|
||||
public virtual Task TicketReceived(TicketReceivedContext context) => OnTicketReceived(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,13 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// </summary>
|
||||
public class RemoteFailureContext : HandleRequestContext<RemoteAuthenticationOptions>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="RemoteFailureContext"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/>.</param>
|
||||
/// <param name="scheme">The <see cref="AuthenticationScheme"/>.</param>
|
||||
/// <param name="options">The <see cref="RemoteAuthenticationOptions"/>.</param>
|
||||
/// <param name="failure">User friendly error message for the error.</param>
|
||||
public RemoteFailureContext(
|
||||
HttpContext context,
|
||||
AuthenticationScheme scheme,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
private AuthenticationProperties? _properties;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// Initializes a new instance of <see cref="ResultContext{TOptions}"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The context.</param>
|
||||
/// <param name="scheme">The authentication scheme.</param>
|
||||
|
|
|
|||
|
|
@ -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
|
|||
/// </summary>
|
||||
public class TicketReceivedContext : RemoteAuthenticationContext<RemoteAuthenticationOptions>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="TicketReceivedContext"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/>.</param>
|
||||
/// <param name="scheme">The <see cref="AuthenticationScheme"/>.</param>
|
||||
/// <param name="options">The <see cref="RemoteAuthenticationOptions"/>.</param>
|
||||
/// <param name="ticket">The received ticket.</param>
|
||||
public TicketReceivedContext(
|
||||
HttpContext context,
|
||||
AuthenticationScheme scheme,
|
||||
|
|
@ -19,6 +25,9 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
: base(context, scheme, options, ticket?.Properties)
|
||||
=> Principal = ticket?.Principal;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the URL to redirect to after signin.
|
||||
/// </summary>
|
||||
public string? ReturnUri { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,6 +93,10 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
return new HandleRequestResult() { Skipped = true };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that there were no results produced during authentication.
|
||||
/// </summary>
|
||||
/// <returns>The result.</returns>
|
||||
public new static HandleRequestResult NoResult()
|
||||
{
|
||||
return new HandleRequestResult() { None = true };
|
||||
|
|
|
|||
|
|
@ -5,10 +5,24 @@ using System.Diagnostics.CodeAnalysis;
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Contract for serialzing authentication data.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model being serialized.</typeparam>
|
||||
public interface IDataSerializer<TModel>
|
||||
{
|
||||
/// <summary>
|
||||
/// Serializes the specified <paramref name="model"/>.
|
||||
/// </summary>
|
||||
/// <param name="model">The value to serialize.</param>
|
||||
/// <returns>The serialized data.</returns>
|
||||
byte[] Serialize(TModel model);
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes the specified <paramref name="data"/> as an instance of type <typeparamref name="TModel"/>.
|
||||
/// </summary>
|
||||
/// <param name="data">The bytes being deserialized.</param>
|
||||
/// <returns>The model.</returns>
|
||||
[return: MaybeNull]
|
||||
TModel Deserialize(byte[] data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,15 +5,41 @@ using System.Diagnostics.CodeAnalysis;
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// A contract for securing data.
|
||||
/// </summary>
|
||||
/// <typeparam name="TData">The type of the data to protect.</typeparam>
|
||||
public interface ISecureDataFormat<TData>
|
||||
{
|
||||
/// <summary>
|
||||
/// Protects the specified <paramref name="data"/>.
|
||||
/// </summary>
|
||||
/// <param name="data">The value to protect</param>
|
||||
/// <returns>The data protected value.</returns>
|
||||
string Protect(TData data);
|
||||
|
||||
/// <summary>
|
||||
/// Protects the specified <paramref name="data"/> for the specified <paramref name="purpose"/>.
|
||||
/// </summary>
|
||||
/// <param name="data">The value to protect</param>
|
||||
/// <param name="purpose">The purpose.</param>
|
||||
/// <returns>A data protected value.</returns>
|
||||
string Protect(TData data, string? purpose);
|
||||
|
||||
/// <summary>
|
||||
/// Unprotects the specified <paramref name="protectedText"/>.
|
||||
/// </summary>
|
||||
/// <param name="protectedText">The data protected value.</param>
|
||||
/// <returns>An instance of <typeparamref name="TData"/>.</returns>
|
||||
[return: MaybeNull]
|
||||
TData Unprotect(string protectedText);
|
||||
|
||||
/// <summary>
|
||||
/// Unprotects the specified <paramref name="protectedText"/> using the specified <paramref name="purpose"/>.
|
||||
/// </summary>
|
||||
/// <param name="protectedText">The data protected value.</param>
|
||||
/// <param name="purpose">The purpose.</param>
|
||||
/// <returns>An instance of <typeparamref name="TData"/>.</returns>
|
||||
[return: MaybeNull]
|
||||
TData Unprotect(string protectedText, string? purpose);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -5,8 +5,17 @@ using System.Text.Json;
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Authentication extensions to <see cref="JsonDocument"/>.
|
||||
/// </summary>
|
||||
public static class JsonDocumentAuthExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a string property value from the specified <see cref="JsonElement"/>.
|
||||
/// </summary>
|
||||
/// <param name="element">The <see cref="JsonElement"/>.</param>
|
||||
/// <param name="key">The property name.</param>
|
||||
/// <returns>The property value.</returns>
|
||||
public static string? GetString(this JsonElement element, string key)
|
||||
{
|
||||
if (element.TryGetProperty(key, out var property) && property.ValueKind != JsonValueKind.Null)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<Description>ASP.NET Core common types used by the various authentication middleware components.</Description>
|
||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
<IsAspNetCoreApp>true</IsAspNetCoreApp>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<NoWarn>$(NoWarn.Replace('1591', ''))</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;authentication;security</PackageTags>
|
||||
<IsPackable>false</IsPackable>
|
||||
|
|
|
|||
|
|
@ -15,21 +15,33 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// </summary>
|
||||
public class PolicySchemeHandler : SignInAuthenticationHandler<PolicySchemeOptions>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="PolicySchemeHandler"/>.
|
||||
/// </summary>
|
||||
/// <param name="options">The monitor for the options instance.</param>
|
||||
/// <param name="logger">The <see cref="ILoggerFactory"/>.</param>
|
||||
/// <param name="encoder">The <see cref="UrlEncoder"/>.</param>
|
||||
/// <param name="clock">The <see cref="ISystemClock"/>.</param>
|
||||
public PolicySchemeHandler(IOptionsMonitor<PolicySchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
|
||||
{ }
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Task HandleChallengeAsync(AuthenticationProperties? properties)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Task HandleForbiddenAsync(AuthenticationProperties? properties)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Task HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties? properties)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Task HandleSignOutAsync(AuthenticationProperties? properties)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
|
||||
=> throw new NotImplementedException();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,16 @@ using Microsoft.AspNetCore.DataProtection;
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="SecureDataFormat{TData}"/> instance to secure
|
||||
/// <see cref="AuthenticationProperties"/>.
|
||||
/// </summary>
|
||||
public class PropertiesDataFormat : SecureDataFormat<AuthenticationProperties>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="PropertiesDataFormat"/>.
|
||||
/// </summary>
|
||||
/// <param name="protector">The <see cref="IDataProtector"/>.</param>
|
||||
public PropertiesDataFormat(IDataProtector protector)
|
||||
: base(new PropertiesSerializer(), protector)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,12 +7,19 @@ using System.IO;
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="IDataSerializer{TModel}"/> for <see cref="AuthenticationProperties"/>.
|
||||
/// </summary>
|
||||
public class PropertiesSerializer : IDataSerializer<AuthenticationProperties>
|
||||
{
|
||||
private const int FormatVersion = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default instance of <see cref="PropertiesSerializer"/>.
|
||||
/// </summary>
|
||||
public static PropertiesSerializer Default { get; } = new PropertiesSerializer();
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual byte[] Serialize(AuthenticationProperties model)
|
||||
{
|
||||
using (var memory = new MemoryStream())
|
||||
|
|
@ -26,6 +33,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual AuthenticationProperties? Deserialize(byte[] data)
|
||||
{
|
||||
using (var memory = new MemoryStream(data))
|
||||
|
|
@ -37,6 +45,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void Write(BinaryWriter writer, AuthenticationProperties properties)
|
||||
{
|
||||
if (writer == null)
|
||||
|
|
@ -59,6 +68,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual AuthenticationProperties? Read(BinaryReader reader)
|
||||
{
|
||||
if (reader == null)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,12 @@ using Microsoft.Extensions.Options;
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// An opinionated abstraction for an <see cref="AuthenticationHandler{TOptions}"/> that performs authentication using a separately hosted
|
||||
/// provider.
|
||||
/// </summary>
|
||||
/// <typeparam name="TOptions">The type for the options used to configure the authentication handler.</typeparam>
|
||||
|
||||
public abstract class RemoteAuthenticationHandler<TOptions> : AuthenticationHandler<TOptions>, IAuthenticationRequestHandler
|
||||
where TOptions : RemoteAuthenticationOptions, new()
|
||||
{
|
||||
|
|
@ -19,6 +25,9 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
private const string CorrelationMarker = "N";
|
||||
private const string AuthSchemeKey = ".AuthScheme";
|
||||
|
||||
/// <summary>
|
||||
/// The authentication scheme used by default for signin.
|
||||
/// </summary>
|
||||
protected string? SignInScheme => Options.SignInScheme;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -31,15 +40,32 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
set { base.Events = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="RemoteAuthenticationHandler{TOptions}" />.
|
||||
/// </summary>
|
||||
/// <param name="options">The monitor for the options instance.</param>
|
||||
/// <param name="logger">The <see cref="ILoggerFactory"/>.</param>
|
||||
/// <param name="encoder">The <see cref="UrlEncoder"/>.</param>
|
||||
/// <param name="clock">The <see cref="ISystemClock"/>.</param>
|
||||
protected RemoteAuthenticationHandler(IOptionsMonitor<TOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
|
||||
: base(options, logger, encoder, clock) { }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Task<object> CreateEventsAsync()
|
||||
=> Task.FromResult<object>(new RemoteAuthenticationEvents());
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that determines if the current authentication request should be handled by <see cref="HandleRequestAsync" />.
|
||||
/// </summary>
|
||||
/// <returns><see langword="true"/> to handle the operation, otherwise <see langword="false"/>.</returns>
|
||||
public virtual Task<bool> ShouldHandleRequestAsync()
|
||||
=> Task.FromResult(Options.CallbackPath == Request.Path);
|
||||
|
||||
/// <summary>
|
||||
/// Handles the current authentication request.
|
||||
/// </summary>
|
||||
/// <returns><see langword="true"/> if authentication was handled, otherwise <see langword="false"/>.</returns>
|
||||
public virtual async Task<bool> HandleRequestAsync()
|
||||
{
|
||||
if (!await ShouldHandleRequestAsync())
|
||||
|
|
@ -156,6 +182,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// </summary>
|
||||
protected abstract Task<HandleRequestResult> HandleRemoteAuthenticateAsync();
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task<AuthenticateResult> 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");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Task HandleForbiddenAsync(AuthenticationProperties properties)
|
||||
=> Context.ForbidAsync(SignInScheme);
|
||||
|
||||
/// <summary>
|
||||
/// Produces a cookie containing a nonce used to correlate the current remote authentication request.
|
||||
/// </summary>
|
||||
/// <param name="properties"></param>
|
||||
protected virtual void GenerateCorrelationId(AuthenticationProperties properties)
|
||||
{
|
||||
if (properties == null)
|
||||
|
|
@ -205,6 +237,11 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
Response.Cookies.Append(cookieName, CorrelationMarker, cookieOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that the current request correlates wit hthe
|
||||
/// </summary>
|
||||
/// <param name="properties"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual bool ValidateCorrelationId(AuthenticationProperties properties)
|
||||
{
|
||||
if (properties == null)
|
||||
|
|
@ -242,6 +279,11 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Derived types may override this method to handle access denied errors.
|
||||
/// </summary>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
|
||||
/// <returns>The <see cref="HandleRequestResult"/>.</returns>
|
||||
protected virtual async Task<HandleRequestResult> HandleAccessDeniedErrorAsync(AuthenticationProperties properties)
|
||||
{
|
||||
Logger.AccessDeniedError();
|
||||
|
|
|
|||
|
|
@ -117,6 +117,9 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// </summary>
|
||||
public TimeSpan RemoteAuthenticationTimeout { get; set; } = TimeSpan.FromMinutes(15);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that allows subscribing to remote authentication events.
|
||||
/// </summary>
|
||||
public new RemoteAuthenticationEvents Events
|
||||
{
|
||||
get => (RemoteAuthenticationEvents)base.Events!;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// </summary>
|
||||
protected virtual string? AdditionalPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Configures <see cref="CookieOptions.Path"/> if not explicitly configured.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -6,22 +6,33 @@ using Microsoft.AspNetCore.DataProtection;
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// An implementation for <see cref="ISecureDataFormat{TData}"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TData"></typeparam>
|
||||
public class SecureDataFormat<TData> : ISecureDataFormat<TData>
|
||||
{
|
||||
private readonly IDataSerializer<TData> _serializer;
|
||||
private readonly IDataProtector _protector;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="SecureDataFormat{TData}"/>.
|
||||
/// </summary>
|
||||
/// <param name="serializer">The <see cref="IDataSerializer{TModel}"/>.</param>
|
||||
/// <param name="protector">The <see cref="IDataProtector"/>.</param>
|
||||
public SecureDataFormat(IDataSerializer<TData> serializer, IDataProtector protector)
|
||||
{
|
||||
_serializer = serializer;
|
||||
_protector = protector;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Protect(TData data)
|
||||
{
|
||||
return Protect(data, purpose: null);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Protect(TData data, string? purpose)
|
||||
{
|
||||
var userData = _serializer.Serialize(data);
|
||||
|
|
@ -36,12 +47,14 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
return Base64UrlTextEncoder.Encode(protectedData);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[return: MaybeNull]
|
||||
public TData Unprotect(string protectedText)
|
||||
{
|
||||
return Unprotect(protectedText, purpose: null);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[return: MaybeNull]
|
||||
public TData Unprotect(string protectedText, string? purpose)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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<TOptions> : SignOutAuthenticationHandler<TOptions>, IAuthenticationSignInHandler
|
||||
where TOptions : AuthenticationSchemeOptions, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="SignInAuthenticationHandler{TOptions}"/>.
|
||||
/// </summary>
|
||||
/// <param name="options">The monitor for the options instance.</param>
|
||||
/// <param name="logger">The <see cref="ILoggerFactory"/>.</param>
|
||||
/// <param name="encoder">The <see cref="UrlEncoder"/>.</param>
|
||||
/// <param name="clock">The <see cref="ISystemClock"/>.</param>
|
||||
public SignInAuthenticationHandler(IOptionsMonitor<TOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
|
||||
{ }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties? properties)
|
||||
{
|
||||
var target = ResolveTarget(Options.ForwardSignIn);
|
||||
|
|
|
|||
|
|
@ -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<TOptions> : AuthenticationHandler<TOptions>, IAuthenticationSignOutHandler
|
||||
where TOptions : AuthenticationSchemeOptions, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="SignOutAuthenticationHandler{TOptions}"/>.
|
||||
/// </summary>
|
||||
/// <param name="options">The monitor for the options instance.</param>
|
||||
/// <param name="logger">The <see cref="ILoggerFactory"/>.</param>
|
||||
/// <param name="encoder">The <see cref="UrlEncoder"/>.</param>
|
||||
/// <param name="clock">The <see cref="ISystemClock"/>.</param>
|
||||
public SignOutAuthenticationHandler(IOptionsMonitor<TOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
|
||||
{ }
|
||||
|
||||
/// <inheritdoc/>
|
||||
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.
|
||||
/// </summary>
|
||||
/// <param name="properties"></param>
|
||||
/// <returns>A Task.</returns>
|
||||
protected abstract Task HandleSignOutAsync(AuthenticationProperties? properties);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Allows encoding and decoding base-64 url encoded text.
|
||||
/// </summary>
|
||||
public static class Base64UrlTextEncoder
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -5,8 +5,16 @@ using Microsoft.AspNetCore.DataProtection;
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="SecureDataFormat{TData}"/> instance to secure
|
||||
/// <see cref="AuthenticationTicket"/>.
|
||||
/// </summary>
|
||||
public class TicketDataFormat : SecureDataFormat<AuthenticationTicket>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="TicketDataFormat"/>.
|
||||
/// </summary>
|
||||
/// <param name="protector">The <see cref="IDataProtector"/>.</param>
|
||||
public TicketDataFormat(IDataProtector protector)
|
||||
: base(TicketSerializer.Default, protector)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -9,13 +9,20 @@ using System.Security.Claims;
|
|||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
// This MUST be kept in sync with Microsoft.Owin.Security.Interop.AspNetTicketSerializer
|
||||
/// <summary>
|
||||
/// Serializes and deserializes <see cref="AuthenticationTicket"/> instances.
|
||||
/// </summary>
|
||||
public class TicketSerializer : IDataSerializer<AuthenticationTicket>
|
||||
{
|
||||
private const string DefaultStringPlaceholder = "\0";
|
||||
private const int FormatVersion = 5;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default implementation for <see cref="TicketSerializer"/>.
|
||||
/// </summary>
|
||||
public static TicketSerializer Default { get; } = new TicketSerializer();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual byte[] Serialize(AuthenticationTicket ticket)
|
||||
{
|
||||
using (var memory = new MemoryStream())
|
||||
|
|
@ -28,6 +35,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual AuthenticationTicket? Deserialize(byte[] data)
|
||||
{
|
||||
using (var memory = new MemoryStream(data))
|
||||
|
|
@ -39,6 +47,11 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the <paramref name="ticket"/> using the specified <paramref name="writer"/>.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="BinaryWriter"/>.</param>
|
||||
/// <param name="ticket">The <see cref="AuthenticationTicket"/>.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the specified <paramref name="identity" />.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="BinaryWriter" />.</param>
|
||||
/// <param name="identity">The <see cref="ClaimsIdentity" />.</param>
|
||||
protected virtual void WriteIdentity(BinaryWriter writer, ClaimsIdentity identity)
|
||||
{
|
||||
if (writer == null)
|
||||
|
|
@ -114,6 +132,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected virtual void WriteClaim(BinaryWriter writer, Claim claim)
|
||||
{
|
||||
if (writer == null)
|
||||
|
|
@ -142,6 +161,11 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an <see cref="AuthenticationTicket"/>.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="BinaryReader"/>.</param>
|
||||
/// <returns>The <see cref="AuthenticationTicket"/> if the format is supported, otherwise <see langword="null"/>.</returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a <see cref="ClaimsIdentity"/> from a <see cref="BinaryReader"/>.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="BinaryReader"/>.</param>
|
||||
/// <returns>The read <see cref="ClaimsIdentity"/>.</returns>
|
||||
protected virtual ClaimsIdentity ReadIdentity(BinaryReader reader)
|
||||
{
|
||||
if (reader == null)
|
||||
|
|
@ -216,6 +245,12 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
return identity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a <see cref="Claim"/> and adds it to the specified <paramref name="identity"/>.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="BinaryReader"/>.</param>
|
||||
/// <param name="identity">The <see cref="ClaimsIdentity"/> to add the claim to.</param>
|
||||
/// <returns>The read <see cref="Claim"/>.</returns>
|
||||
protected virtual Claim ReadClaim(BinaryReader reader, ClaimsIdentity identity)
|
||||
{
|
||||
if (reader == null)
|
||||
|
|
|
|||
|
|
@ -6,14 +6,24 @@ using Microsoft.AspNetCore.Http;
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication.JwtBearer
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="ResultContext{TOptions}"/> when authentication has failed.
|
||||
/// </summary>
|
||||
public class AuthenticationFailedContext : ResultContext<JwtBearerOptions>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="AuthenticationFailedContext"/>.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public AuthenticationFailedContext(
|
||||
HttpContext context,
|
||||
AuthenticationScheme scheme,
|
||||
JwtBearerOptions options)
|
||||
: base(context, scheme, options) { }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the exception associated with the authentication failure.
|
||||
/// </summary>
|
||||
public Exception Exception { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,15 @@ using Microsoft.AspNetCore.Http;
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication.JwtBearer
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="ResultContext{TOptions}"/> when access to a resource is forbidden.
|
||||
/// </summary>
|
||||
public class ForbiddenContext : ResultContext<JwtBearerOptions>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="ForbiddenContext"/>.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public ForbiddenContext(
|
||||
HttpContext context,
|
||||
AuthenticationScheme scheme,
|
||||
|
|
|
|||
|
|
@ -6,8 +6,15 @@ using Microsoft.AspNetCore.Http;
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication.JwtBearer
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="PropertiesContext{TOptions}"/> when access to a resource authenticated using JWT bearer is challenged.
|
||||
/// </summary>
|
||||
public class JwtBearerChallengeContext : PropertiesContext<JwtBearerOptions>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="JwtBearerChallengeContext"/>.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public JwtBearerChallengeContext(
|
||||
HttpContext context,
|
||||
AuthenticationScheme scheme,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
|
|||
public Func<AuthenticationFailedContext, Task> OnAuthenticationFailed { get; set; } = context => Task.CompletedTask;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked if Authorization fails and results in a Forbidden response
|
||||
/// Invoked if Authorization fails and results in a Forbidden response.
|
||||
/// </summary>
|
||||
public Func<ForbiddenContext, Task> OnForbidden { get; set; } = context => Task.CompletedTask;
|
||||
|
||||
|
|
@ -36,14 +36,29 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
|
|||
/// </summary>
|
||||
public Func<JwtBearerChallengeContext, Task> OnChallenge { get; set; } = context => Task.CompletedTask;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked if exceptions are thrown during request processing. The exceptions will be re-thrown after this event unless suppressed.
|
||||
/// </summary>
|
||||
public virtual Task AuthenticationFailed(AuthenticationFailedContext context) => OnAuthenticationFailed(context);
|
||||
|
||||
/// <summary>
|
||||
/// Invoked if Authorization fails and results in a Forbidden response
|
||||
/// </summary>
|
||||
public virtual Task Forbidden(ForbiddenContext context) => OnForbidden(context);
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when a protocol message is first received.
|
||||
/// </summary>
|
||||
public virtual Task MessageReceived(MessageReceivedContext context) => OnMessageReceived(context);
|
||||
|
||||
/// <summary>
|
||||
/// Invoked after the security token has passed validation and a ClaimsIdentity has been generated.
|
||||
/// </summary>
|
||||
public virtual Task TokenValidated(TokenValidatedContext context) => OnTokenValidated(context);
|
||||
|
||||
/// <summary>
|
||||
/// Invoked before a challenge is sent back to the caller.
|
||||
/// </summary>
|
||||
public virtual Task Challenge(JwtBearerChallengeContext context) => OnChallenge(context);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,17 +9,58 @@ using Microsoft.Extensions.Options;
|
|||
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods to configure JWT bearer authentication.
|
||||
/// </summary>
|
||||
public static class JwtBearerExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Enables JWT-bearer authentication using the default scheme <see cref="JwtBearerDefaults.AuthenticationScheme"/>.
|
||||
/// <para>
|
||||
/// JWT bearer authentication performs authentication by extracting and validating a JWT token from the <c>Authorization</c> request header.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
|
||||
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
|
||||
public static AuthenticationBuilder AddJwtBearer(this AuthenticationBuilder builder)
|
||||
=> builder.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, _ => { });
|
||||
|
||||
/// <summary>
|
||||
/// Enables JWT-bearer authentication using the default scheme <see cref="JwtBearerDefaults.AuthenticationScheme"/>.
|
||||
/// <para>
|
||||
/// JWT bearer authentication performs authentication by extracting and validating a JWT token from the <c>Authorization</c> request header.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
|
||||
/// <param name="configureOptions">A delegate that allows configuring <see cref="JwtBearerOptions"/>.</param>
|
||||
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
|
||||
public static AuthenticationBuilder AddJwtBearer(this AuthenticationBuilder builder, Action<JwtBearerOptions> configureOptions)
|
||||
=> builder.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, configureOptions);
|
||||
|
||||
/// <summary>
|
||||
/// Enables JWT-bearer authentication using the specified scheme.
|
||||
/// <para>
|
||||
/// JWT bearer authentication performs authentication by extracting and validating a JWT token from the <c>Authorization</c> request header.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
|
||||
/// <param name="authenticationScheme">The authentication scheme.</param>
|
||||
/// <param name="configureOptions">A delegate that allows configuring <see cref="JwtBearerOptions"/>.</param>
|
||||
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
|
||||
public static AuthenticationBuilder AddJwtBearer(this AuthenticationBuilder builder, string authenticationScheme, Action<JwtBearerOptions> configureOptions)
|
||||
=> builder.AddJwtBearer(authenticationScheme, displayName: null, configureOptions: configureOptions);
|
||||
|
||||
/// <summary>
|
||||
/// Enables JWT-bearer authentication using the specified scheme.
|
||||
/// <para>
|
||||
/// JWT bearer authentication performs authentication by extracting and validating a JWT token from the <c>Authorization</c> request header.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="AuthenticationBuilder"/>.</param>
|
||||
/// <param name="authenticationScheme">The authentication scheme.</param>
|
||||
/// <param name="displayName">The display name for the authentication handler.</param>
|
||||
/// <param name="configureOptions">A delegate that allows configuring <see cref="JwtBearerOptions"/>.</param>
|
||||
/// <returns>A reference to <paramref name="builder"/> after the operation has completed.</returns>
|
||||
public static AuthenticationBuilder AddJwtBearer(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<JwtBearerOptions> configureOptions)
|
||||
{
|
||||
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<JwtBearerOptions>, JwtBearerPostConfigureOptions>());
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="AuthenticationHandler{TOptions}"/> that can perform JWT-bearer based authentication.
|
||||
/// </summary>
|
||||
public class JwtBearerHandler : AuthenticationHandler<JwtBearerOptions>
|
||||
{
|
||||
private OpenIdConnectConfiguration _configuration;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="JwtBearerHandler"/>.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public JwtBearerHandler(IOptionsMonitor<JwtBearerOptions> 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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Task<object> CreateEventsAsync() => Task.FromResult<object>(new JwtBearerEvents());
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -192,6 +199,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
|
||||
{
|
||||
var authResult = await HandleAuthenticateOnceSafeAsync();
|
||||
|
|
@ -265,6 +273,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Task HandleForbiddenAsync(AuthenticationProperties properties)
|
||||
{
|
||||
var forbiddenContext = new ForbiddenContext(Context, Scheme, Options);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,10 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
|
|||
public class JwtBearerOptions : AuthenticationSchemeOptions
|
||||
{
|
||||
private JwtSecurityTokenHandler _defaultHandler = new JwtSecurityTokenHandler();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="JwtBearerOptions"/>.
|
||||
/// </summary>
|
||||
public JwtBearerOptions()
|
||||
{
|
||||
SecurityTokenValidators = new List<ISecurityTokenValidator> { _defaultHandler };
|
||||
|
|
|
|||
|
|
@ -5,8 +5,15 @@ using Microsoft.AspNetCore.Http;
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication.JwtBearer
|
||||
{
|
||||
/// <summary>
|
||||
/// A context for <see cref="JwtBearerEvents.OnMessageReceived"/>.
|
||||
/// </summary>
|
||||
public class MessageReceivedContext : ResultContext<JwtBearerOptions>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="MessageReceivedContext"/>.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public MessageReceivedContext(
|
||||
HttpContext context,
|
||||
AuthenticationScheme scheme,
|
||||
|
|
@ -18,4 +25,4 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
|
|||
/// </summary>
|
||||
public string Token { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core middleware that enables an application to receive an OpenID Connect bearer token.</Description>
|
||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||
<NoWarn>$(NoWarn.Replace('1591', ''))</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>aspnetcore;authentication;security</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -6,14 +6,24 @@ using Microsoft.IdentityModel.Tokens;
|
|||
|
||||
namespace Microsoft.AspNetCore.Authentication.JwtBearer
|
||||
{
|
||||
/// <summary>
|
||||
/// A context for <see cref="JwtBearerEvents.OnTokenValidated"/>.
|
||||
/// </summary>
|
||||
public class TokenValidatedContext : ResultContext<JwtBearerOptions>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="TokenValidatedContext"/>.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public TokenValidatedContext(
|
||||
HttpContext context,
|
||||
AuthenticationScheme scheme,
|
||||
JwtBearerOptions options)
|
||||
: base(context, scheme, options) { }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the validated security token.
|
||||
/// </summary>
|
||||
public SecurityToken SecurityToken { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,9 @@ namespace Microsoft.AspNetCore.Internal
|
|||
private const string ChunkKeySuffix = "C";
|
||||
private const string ChunkCountPrefix = "chunks-";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="ChunkingCookieManager"/>.
|
||||
/// </summary>
|
||||
public ChunkingCookieManager()
|
||||
{
|
||||
// Lowest common denominator. Safari has the lowest known limit (4093), and we leave little extra just in case.
|
||||
|
|
|
|||
Loading…
Reference in New Issue