Add nullable annotations to Authenticator.Core & Authentication.Cookies (#24307)

Contributes to https://github.com/dotnet/aspnetcore/issues/5680
This commit is contained in:
Pranav K 2020-07-30 17:09:14 -07:00 committed by GitHub
parent 799014cfe7
commit 3e1e69ecce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 183 additions and 151 deletions

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Diagnostics.CodeAnalysis;
using System.Security.Claims; using System.Security.Claims;
namespace Microsoft.AspNetCore.Authentication namespace Microsoft.AspNetCore.Authentication
@ -19,6 +20,7 @@ namespace Microsoft.AspNetCore.Authentication
/// <summary> /// <summary>
/// If a ticket was produced, authenticate was successful. /// If a ticket was produced, authenticate was successful.
/// </summary> /// </summary>
[MemberNotNullWhen(true, nameof(Ticket))]
public bool Succeeded => Ticket != null; public bool Succeeded => Ticket != null;
/// <summary> /// <summary>

View File

@ -36,7 +36,7 @@ namespace Microsoft.AspNetCore.Authentication
/// <param name="context">The <see cref="HttpContext"/> context.</param> /// <param name="context">The <see cref="HttpContext"/> context.</param>
/// <param name="scheme">The name of the authentication scheme.</param> /// <param name="scheme">The name of the authentication scheme.</param>
/// <returns>The result.</returns> /// <returns>The result.</returns>
public static Task ChallengeAsync(this HttpContext context, string scheme) => public static Task ChallengeAsync(this HttpContext context, string? scheme) =>
context.ChallengeAsync(scheme, properties: null); context.ChallengeAsync(scheme, properties: null);
/// <summary> /// <summary>
@ -72,7 +72,7 @@ namespace Microsoft.AspNetCore.Authentication
/// <param name="context">The <see cref="HttpContext"/> context.</param> /// <param name="context">The <see cref="HttpContext"/> context.</param>
/// <param name="scheme">The name of the authentication scheme.</param> /// <param name="scheme">The name of the authentication scheme.</param>
/// <returns>The task.</returns> /// <returns>The task.</returns>
public static Task ForbidAsync(this HttpContext context, string scheme) => public static Task ForbidAsync(this HttpContext context, string? scheme) =>
context.ForbidAsync(scheme, properties: null); context.ForbidAsync(scheme, properties: null);
/// <summary> /// <summary>
@ -109,7 +109,7 @@ namespace Microsoft.AspNetCore.Authentication
/// <param name="scheme">The name of the authentication scheme.</param> /// <param name="scheme">The name of the authentication scheme.</param>
/// <param name="principal">The user.</param> /// <param name="principal">The user.</param>
/// <returns>The task.</returns> /// <returns>The task.</returns>
public static Task SignInAsync(this HttpContext context, string scheme, ClaimsPrincipal principal) => public static Task SignInAsync(this HttpContext context, string? scheme, ClaimsPrincipal principal) =>
context.SignInAsync(scheme, principal, properties: null); context.SignInAsync(scheme, principal, properties: null);
/// <summary> /// <summary>

View File

@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Authentication
/// <param name="principal">the <see cref="ClaimsPrincipal"/> that represents the authenticated user.</param> /// <param name="principal">the <see cref="ClaimsPrincipal"/> that represents the authenticated user.</param>
/// <param name="properties">additional properties that can be consumed by the user or runtime.</param> /// <param name="properties">additional properties that can be consumed by the user or runtime.</param>
/// <param name="authenticationScheme">the authentication middleware that was responsible for this ticket.</param> /// <param name="authenticationScheme">the authentication middleware that was responsible for this ticket.</param>
public AuthenticationTicket(ClaimsPrincipal principal, AuthenticationProperties? properties, string? authenticationScheme) public AuthenticationTicket(ClaimsPrincipal principal, AuthenticationProperties? properties, string authenticationScheme)
{ {
if (principal == null) if (principal == null)
{ {
@ -41,17 +41,17 @@ namespace Microsoft.AspNetCore.Authentication
/// <summary> /// <summary>
/// Gets the authentication type. /// Gets the authentication type.
/// </summary> /// </summary>
public string? AuthenticationScheme { get; private set; } public string AuthenticationScheme { get; }
/// <summary> /// <summary>
/// Gets the claims-principal with authenticated user identities. /// Gets the claims-principal with authenticated user identities.
/// </summary> /// </summary>
public ClaimsPrincipal Principal { get; private set; } public ClaimsPrincipal Principal { get; }
/// <summary> /// <summary>
/// Additional state values for the authentication session. /// Additional state values for the authentication session.
/// </summary> /// </summary>
public AuthenticationProperties Properties { get; private set; } public AuthenticationProperties Properties { get; }
/// <summary> /// <summary>
/// Returns a copy of the ticket. /// Returns a copy of the ticket.

View File

@ -424,7 +424,7 @@ namespace Microsoft.AspNetCore.Http
/// <param name="left">The left parameter</param> /// <param name="left">The left parameter</param>
/// <param name="right">The right parameter</param> /// <param name="right">The right parameter</param>
/// <returns>The ToString combination of both values</returns> /// <returns>The ToString combination of both values</returns>
public static string operator +(PathString left, string right) public static string operator +(PathString left, string? right)
{ {
// This overload exists to prevent the implicit string<->PathString converter from // This overload exists to prevent the implicit string<->PathString converter from
// trying to call the PathString+PathString operator for things that are not path strings. // trying to call the PathString+PathString operator for things that are not path strings.

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Security.Claims; using System.Security.Claims;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
@ -27,9 +28,9 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
private DateTimeOffset? _refreshIssuedUtc; private DateTimeOffset? _refreshIssuedUtc;
private DateTimeOffset? _refreshExpiresUtc; private DateTimeOffset? _refreshExpiresUtc;
private string _sessionKey; private string? _sessionKey;
private Task<AuthenticateResult> _readCookieTask; private Task<AuthenticateResult>? _readCookieTask;
private AuthenticationTicket _refreshTicket; private AuthenticationTicket? _refreshTicket;
public CookieAuthenticationHandler(IOptionsMonitor<CookieAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) public CookieAuthenticationHandler(IOptionsMonitor<CookieAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock) : base(options, logger, encoder, clock)
@ -41,7 +42,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// </summary> /// </summary>
protected new CookieAuthenticationEvents Events protected new CookieAuthenticationEvents Events
{ {
get { return (CookieAuthenticationEvents)base.Events; } get { return (CookieAuthenticationEvents)base.Events!; }
set { base.Events = value; } set { base.Events = value; }
} }
@ -86,7 +87,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
} }
} }
private void RequestRefresh(AuthenticationTicket ticket, ClaimsPrincipal replacedPrincipal = null) private void RequestRefresh(AuthenticationTicket ticket, ClaimsPrincipal? replacedPrincipal = null)
{ {
var issuedUtc = ticket.Properties.IssuedUtc; var issuedUtc = ticket.Properties.IssuedUtc;
var expiresUtc = ticket.Properties.ExpiresUtc; var expiresUtc = ticket.Properties.ExpiresUtc;
@ -102,7 +103,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
} }
} }
private AuthenticationTicket CloneTicket(AuthenticationTicket ticket, ClaimsPrincipal replacedPrincipal) private AuthenticationTicket CloneTicket(AuthenticationTicket ticket, ClaimsPrincipal? replacedPrincipal)
{ {
var principal = replacedPrincipal ?? ticket.Principal; var principal = replacedPrincipal ?? ticket.Principal;
var newPrincipal = new ClaimsPrincipal(); var newPrincipal = new ClaimsPrincipal();
@ -122,7 +123,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
private async Task<AuthenticateResult> ReadCookieTicket() private async Task<AuthenticateResult> ReadCookieTicket()
{ {
var cookie = Options.CookieManager.GetRequestCookie(Context, Options.Cookie.Name); var cookie = Options.CookieManager.GetRequestCookie(Context, Options.Cookie.Name!);
if (string.IsNullOrEmpty(cookie)) if (string.IsNullOrEmpty(cookie))
{ {
return AuthenticateResult.NoResult(); return AuthenticateResult.NoResult();
@ -157,7 +158,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
{ {
if (Options.SessionStore != null) if (Options.SessionStore != null)
{ {
await Options.SessionStore.RemoveAsync(_sessionKey); await Options.SessionStore.RemoveAsync(_sessionKey!);
} }
return AuthenticateResult.Fail("Ticket expired"); return AuthenticateResult.Fail("Ticket expired");
} }
@ -176,6 +177,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
return result; return result;
} }
Debug.Assert(result.Ticket != null);
var context = new CookieValidatePrincipalContext(Context, Scheme, Options, result.Ticket); var context = new CookieValidatePrincipalContext(Context, Scheme, Options, result.Ticket);
await Events.ValidatePrincipal(context); await Events.ValidatePrincipal(context);
@ -244,7 +246,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
Options.CookieManager.AppendResponseCookie( Options.CookieManager.AppendResponseCookie(
Context, Context,
Options.Cookie.Name, Options.Cookie.Name!,
cookieValue, cookieValue,
cookieOptions); cookieOptions);
@ -252,7 +254,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
} }
} }
protected async override Task HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties properties) protected async override Task HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties? properties)
{ {
if (user == null) if (user == null)
{ {
@ -299,7 +301,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
signInContext.CookieOptions.Expires = expiresUtc.ToUniversalTime(); signInContext.CookieOptions.Expires = expiresUtc.ToUniversalTime();
} }
var ticket = new AuthenticationTicket(signInContext.Principal, signInContext.Properties, signInContext.Scheme.Name); var ticket = new AuthenticationTicket(signInContext.Principal!, signInContext.Properties, signInContext.Scheme.Name);
if (Options.SessionStore != null) if (Options.SessionStore != null)
{ {
@ -324,14 +326,14 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
Options.CookieManager.AppendResponseCookie( Options.CookieManager.AppendResponseCookie(
Context, Context,
Options.Cookie.Name, Options.Cookie.Name!,
cookieValue, cookieValue,
signInContext.CookieOptions); signInContext.CookieOptions);
var signedInContext = new CookieSignedInContext( var signedInContext = new CookieSignedInContext(
Context, Context,
Scheme, Scheme,
signInContext.Principal, signInContext.Principal!,
signInContext.Properties, signInContext.Properties,
Options); Options);
@ -344,7 +346,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
Logger.AuthenticationSchemeSignedIn(Scheme.Name); Logger.AuthenticationSchemeSignedIn(Scheme.Name);
} }
protected async override Task HandleSignOutAsync(AuthenticationProperties properties) protected async override Task HandleSignOutAsync(AuthenticationProperties? properties)
{ {
properties = properties ?? new AuthenticationProperties(); properties = properties ?? new AuthenticationProperties();
@ -369,7 +371,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
Options.CookieManager.DeleteCookie( Options.CookieManager.DeleteCookie(
Context, Context,
Options.Cookie.Name, Options.Cookie.Name!,
context.CookieOptions); context.CookieOptions);
// Only redirect on the logout path // Only redirect on the logout path
@ -449,7 +451,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
await Events.RedirectToLogin(redirectContext); await Events.RedirectToLogin(redirectContext);
} }
private string GetTlsTokenBinding() private string? GetTlsTokenBinding()
{ {
var binding = Context.Features.Get<ITlsTokenBindingFeature>()?.GetProvidedTokenBindingId(); var binding = Context.Features.Get<ITlsTokenBindingFeature>()?.GetProvidedTokenBindingId();
return binding == null ? null : Convert.ToBase64String(binding); return binding == null ? null : Convert.ToBase64String(binding);

View File

@ -71,7 +71,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// <summary> /// <summary>
/// If set this will be used by the CookieAuthenticationHandler for data protection. /// If set this will be used by the CookieAuthenticationHandler for data protection.
/// </summary> /// </summary>
public IDataProtectionProvider DataProtectionProvider { get; set; } public IDataProtectionProvider? DataProtectionProvider { get; set; }
/// <summary> /// <summary>
/// The SlidingExpiration is set to true to instruct the handler to re-issue a new cookie with a new /// The SlidingExpiration is set to true to instruct the handler to re-issue a new cookie with a new
@ -111,7 +111,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// </summary> /// </summary>
public new CookieAuthenticationEvents Events public new CookieAuthenticationEvents Events
{ {
get => (CookieAuthenticationEvents)base.Events; get => (CookieAuthenticationEvents)base.Events!;
set => base.Events = value; set => base.Events = value;
} }
@ -119,20 +119,20 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// The TicketDataFormat is used to protect and unprotect the identity and other properties which are stored in the /// The TicketDataFormat is used to protect and unprotect the identity and other properties which are stored in the
/// cookie value. If not provided one will be created using <see cref="DataProtectionProvider"/>. /// cookie value. If not provided one will be created using <see cref="DataProtectionProvider"/>.
/// </summary> /// </summary>
public ISecureDataFormat<AuthenticationTicket> TicketDataFormat { get; set; } public ISecureDataFormat<AuthenticationTicket> TicketDataFormat { get; set; } = default!;
/// <summary> /// <summary>
/// The component used to get cookies from the request or set them on the response. /// The component used to get cookies from the request or set them on the response.
/// ///
/// ChunkingCookieManager will be used by default. /// ChunkingCookieManager will be used by default.
/// </summary> /// </summary>
public ICookieManager CookieManager { get; set; } public ICookieManager CookieManager { get; set; } = default!;
/// <summary> /// <summary>
/// An optional container in which to store the identity across requests. When used, only a session identifier is sent /// An optional container in which to store the identity across requests. When used, only a session identifier is sent
/// to the client. This can be used to mitigate potential problems with very large identities. /// to the client. This can be used to mitigate potential problems with very large identities.
/// </summary> /// </summary>
public ITicketStore SessionStore { get; set; } public ITicketStore? SessionStore { get; set; }
/// <summary> /// <summary>
/// <para> /// <para>

View File

@ -17,13 +17,13 @@ namespace Microsoft.Extensions.DependencyInjection
public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, string authenticationScheme) public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, string authenticationScheme)
=> builder.AddCookie(authenticationScheme, configureOptions: null); => builder.AddCookie(authenticationScheme, configureOptions: null);
public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, Action<CookieAuthenticationOptions> configureOptions) public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, Action<CookieAuthenticationOptions>? configureOptions)
=> builder.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, configureOptions); => builder.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, configureOptions);
public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, string authenticationScheme, Action<CookieAuthenticationOptions> configureOptions) public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, string authenticationScheme, Action<CookieAuthenticationOptions>? configureOptions)
=> builder.AddCookie(authenticationScheme, displayName: null, configureOptions: configureOptions); => builder.AddCookie(authenticationScheme, displayName: null, configureOptions: configureOptions);
public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<CookieAuthenticationOptions> configureOptions) public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, string authenticationScheme, string? displayName, Action<CookieAuthenticationOptions>? configureOptions)
{ {
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<CookieAuthenticationOptions>, PostConfigureCookieAuthenticationOptions>()); builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<CookieAuthenticationOptions>, PostConfigureCookieAuthenticationOptions>());
builder.Services.AddOptions<CookieAuthenticationOptions>(authenticationScheme).Validate(o => o.Cookie.Expiration == null, "Cookie.Expiration is ignored, use ExpireTimeSpan instead."); builder.Services.AddOptions<CookieAuthenticationOptions>(authenticationScheme).Validate(o => o.Cookie.Expiration == null, "Cookie.Expiration is ignored, use ExpireTimeSpan instead.");

View File

@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
HttpContext context, HttpContext context,
AuthenticationScheme scheme, AuthenticationScheme scheme,
ClaimsPrincipal principal, ClaimsPrincipal principal,
AuthenticationProperties properties, AuthenticationProperties? properties,
CookieAuthenticationOptions options) CookieAuthenticationOptions options)
: base(context, scheme, options, properties) : base(context, scheme, options, properties)
{ {

View File

@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
AuthenticationScheme scheme, AuthenticationScheme scheme,
CookieAuthenticationOptions options, CookieAuthenticationOptions options,
ClaimsPrincipal principal, ClaimsPrincipal principal,
AuthenticationProperties properties, AuthenticationProperties? properties,
CookieOptions cookieOptions) CookieOptions cookieOptions)
: base(context, scheme, options, properties) : base(context, scheme, options, properties)
{ {

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
HttpContext context, HttpContext context,
AuthenticationScheme scheme, AuthenticationScheme scheme,
CookieAuthenticationOptions options, CookieAuthenticationOptions options,
AuthenticationProperties properties, AuthenticationProperties? properties,
CookieOptions cookieOptions) CookieOptions cookieOptions)
: base(context, scheme, options, properties) : base(context, scheme, options, properties)
=> CookieOptions = cookieOptions; => CookieOptions = cookieOptions;

View File

@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// <param name="context"></param> /// <param name="context"></param>
/// <param name="key"></param> /// <param name="key"></param>
/// <returns></returns> /// <returns></returns>
string GetRequestCookie(HttpContext context, string key); string? GetRequestCookie(HttpContext context, string key);
/// <summary> /// <summary>
/// Append the given cookie to the response. /// Append the given cookie to the response.
@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// <param name="key"></param> /// <param name="key"></param>
/// <param name="value"></param> /// <param name="value"></param>
/// <param name="options"></param> /// <param name="options"></param>
void AppendResponseCookie(HttpContext context, string key, string value, CookieOptions options); void AppendResponseCookie(HttpContext context, string key, string? value, CookieOptions options);
/// <summary> /// <summary>
/// Append a delete cookie to the response. /// Append a delete cookie to the response.

View File

@ -7,8 +7,8 @@ namespace Microsoft.Extensions.Logging
{ {
internal static class LoggingExtensions internal static class LoggingExtensions
{ {
private static Action<ILogger, string, Exception> _authenticationSchemeSignedIn; private static Action<ILogger, string, Exception?> _authenticationSchemeSignedIn;
private static Action<ILogger, string, Exception> _authenticationSchemeSignedOut; private static Action<ILogger, string, Exception?> _authenticationSchemeSignedOut;
static LoggingExtensions() static LoggingExtensions()
{ {

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Description>ASP.NET Core middleware that enables an application to use cookie based authentication.</Description> <Description>ASP.NET Core middleware that enables an application to use cookie based authentication.</Description>
@ -9,6 +9,7 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore;authentication;security</PackageTags> <PackageTags>aspnetcore;authentication;security</PackageTags>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// <param name="options">The options instance to configure.</param> /// <param name="options">The options instance to configure.</param>
public void PostConfigure(string name, CookieAuthenticationOptions options) public void PostConfigure(string name, CookieAuthenticationOptions options)
{ {
options.DataProtectionProvider = options.DataProtectionProvider ?? _dp; options.DataProtectionProvider ??= _dp;
if (string.IsNullOrEmpty(options.Cookie.Name)) if (string.IsNullOrEmpty(options.Cookie.Name))
{ {

View File

@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Authentication
/// </summary> /// </summary>
public virtual IServiceCollection Services { get; } public virtual IServiceCollection Services { get; }
private AuthenticationBuilder AddSchemeHelper<TOptions, THandler>(string authenticationScheme, string displayName, Action<TOptions> configureOptions) private AuthenticationBuilder AddSchemeHelper<TOptions, THandler>(string authenticationScheme, string? displayName, Action<TOptions>? configureOptions)
where TOptions : AuthenticationSchemeOptions, new() where TOptions : AuthenticationSchemeOptions, new()
where THandler : class, IAuthenticationHandler where THandler : class, IAuthenticationHandler
{ {
@ -57,7 +57,7 @@ namespace Microsoft.AspNetCore.Authentication
/// <param name="displayName">The display name of this scheme.</param> /// <param name="displayName">The display name of this scheme.</param>
/// <param name="configureOptions">Used to configure the scheme options.</param> /// <param name="configureOptions">Used to configure the scheme options.</param>
/// <returns>The builder.</returns> /// <returns>The builder.</returns>
public virtual AuthenticationBuilder AddScheme<TOptions, THandler>(string authenticationScheme, string displayName, Action<TOptions> configureOptions) public virtual AuthenticationBuilder AddScheme<TOptions, THandler>(string authenticationScheme, string? displayName, Action<TOptions>? configureOptions)
where TOptions : AuthenticationSchemeOptions, new() where TOptions : AuthenticationSchemeOptions, new()
where THandler : AuthenticationHandler<TOptions> where THandler : AuthenticationHandler<TOptions>
=> AddSchemeHelper<TOptions, THandler>(authenticationScheme, displayName, configureOptions); => AddSchemeHelper<TOptions, THandler>(authenticationScheme, displayName, configureOptions);
@ -70,7 +70,7 @@ namespace Microsoft.AspNetCore.Authentication
/// <param name="authenticationScheme">The name of this scheme.</param> /// <param name="authenticationScheme">The name of this scheme.</param>
/// <param name="configureOptions">Used to configure the scheme options.</param> /// <param name="configureOptions">Used to configure the scheme options.</param>
/// <returns>The builder.</returns> /// <returns>The builder.</returns>
public virtual AuthenticationBuilder AddScheme<TOptions, THandler>(string authenticationScheme, Action<TOptions> configureOptions) public virtual AuthenticationBuilder AddScheme<TOptions, THandler>(string authenticationScheme, Action<TOptions>? configureOptions)
where TOptions : AuthenticationSchemeOptions, new() where TOptions : AuthenticationSchemeOptions, new()
where THandler : AuthenticationHandler<TOptions> where THandler : AuthenticationHandler<TOptions>
=> AddScheme<TOptions, THandler>(authenticationScheme, displayName: null, configureOptions: configureOptions); => AddScheme<TOptions, THandler>(authenticationScheme, displayName: null, configureOptions: configureOptions);
@ -85,7 +85,7 @@ namespace Microsoft.AspNetCore.Authentication
/// <param name="displayName">The display name of this scheme.</param> /// <param name="displayName">The display name of this scheme.</param>
/// <param name="configureOptions">Used to configure the scheme options.</param> /// <param name="configureOptions">Used to configure the scheme options.</param>
/// <returns>The builder.</returns> /// <returns>The builder.</returns>
public virtual AuthenticationBuilder AddRemoteScheme<TOptions, THandler>(string authenticationScheme, string displayName, Action<TOptions> configureOptions) public virtual AuthenticationBuilder AddRemoteScheme<TOptions, THandler>(string authenticationScheme, string? displayName, Action<TOptions>? configureOptions)
where TOptions : RemoteAuthenticationOptions, new() where TOptions : RemoteAuthenticationOptions, new()
where THandler : RemoteAuthenticationHandler<TOptions> where THandler : RemoteAuthenticationHandler<TOptions>
{ {
@ -101,7 +101,7 @@ namespace Microsoft.AspNetCore.Authentication
/// <param name="displayName">The display name of this scheme.</param> /// <param name="displayName">The display name of this scheme.</param>
/// <param name="configureOptions">Used to configure the scheme options.</param> /// <param name="configureOptions">Used to configure the scheme options.</param>
/// <returns>The builder.</returns> /// <returns>The builder.</returns>
public virtual AuthenticationBuilder AddPolicyScheme(string authenticationScheme, string displayName, Action<PolicySchemeOptions> configureOptions) public virtual AuthenticationBuilder AddPolicyScheme(string authenticationScheme, string? displayName, Action<PolicySchemeOptions> configureOptions)
=> AddSchemeHelper<PolicySchemeOptions, PolicySchemeHandler>(authenticationScheme, displayName, configureOptions); => AddSchemeHelper<PolicySchemeOptions, PolicySchemeHandler>(authenticationScheme, displayName, configureOptions);
// Used to ensure that there's always a default sign in scheme that's not itself // Used to ensure that there's always a default sign in scheme that's not itself
@ -116,7 +116,7 @@ namespace Microsoft.AspNetCore.Authentication
public void PostConfigure(string name, TOptions options) public void PostConfigure(string name, TOptions options)
{ {
options.SignInScheme = options.SignInScheme ?? _authOptions.DefaultSignInScheme ?? _authOptions.DefaultScheme; options.SignInScheme ??= _authOptions.DefaultSignInScheme ?? _authOptions.DefaultScheme;
} }
} }
} }

View File

@ -13,11 +13,11 @@ namespace Microsoft.AspNetCore.Authentication
{ {
public abstract class AuthenticationHandler<TOptions> : IAuthenticationHandler where TOptions : AuthenticationSchemeOptions, new() public abstract class AuthenticationHandler<TOptions> : IAuthenticationHandler where TOptions : AuthenticationSchemeOptions, new()
{ {
private Task<AuthenticateResult> _authenticateTask; private Task<AuthenticateResult>? _authenticateTask;
public AuthenticationScheme Scheme { get; private set; } public AuthenticationScheme Scheme { get; private set; } = default!;
public TOptions Options { get; private set; } public TOptions Options { get; private set; } = default!;
protected HttpContext Context { get; private set; } protected HttpContext Context { get; private set; } = default!;
protected HttpRequest Request protected HttpRequest Request
{ {
@ -45,7 +45,7 @@ namespace Microsoft.AspNetCore.Authentication
/// The handler calls methods on the events which give the application control at certain points where processing is occurring. /// The handler calls methods on the events which give the application control at certain points where processing is occurring.
/// If it is not provided a default instance is supplied which does nothing when the methods are called. /// If it is not provided a default instance is supplied which does nothing when the methods are called.
/// </summary> /// </summary>
protected virtual object Events { get; set; } protected virtual object? Events { get; set; }
protected virtual string ClaimsIssuer => Options.ClaimsIssuer ?? Scheme.Name; protected virtual string ClaimsIssuer => Options.ClaimsIssuer ?? Scheme.Name;
@ -116,7 +116,7 @@ namespace Microsoft.AspNetCore.Authentication
protected string BuildRedirectUri(string targetPath) protected string BuildRedirectUri(string targetPath)
=> Request.Scheme + "://" + Request.Host + OriginalPathBase + targetPath; => Request.Scheme + "://" + Request.Host + OriginalPathBase + targetPath;
protected virtual string ResolveTarget(string scheme) protected virtual string? ResolveTarget(string? scheme)
{ {
var target = scheme ?? Options.ForwardDefaultSelector?.Invoke(Context) ?? Options.ForwardDefault; var target = scheme ?? Options.ForwardDefaultSelector?.Invoke(Context) ?? Options.ForwardDefault;
@ -135,10 +135,10 @@ namespace Microsoft.AspNetCore.Authentication
} }
// Calling Authenticate more than once should always return the original value. // Calling Authenticate more than once should always return the original value.
var result = await HandleAuthenticateOnceAsync(); var result = await HandleAuthenticateOnceAsync() ?? AuthenticateResult.NoResult();
if (result?.Failure == null) if (result.Failure == null)
{ {
var ticket = result?.Ticket; var ticket = result.Ticket;
if (ticket?.Principal != null) if (ticket?.Principal != null)
{ {
Logger.AuthenticationSchemeAuthenticated(Scheme.Name); Logger.AuthenticationSchemeAuthenticated(Scheme.Name);
@ -212,7 +212,7 @@ namespace Microsoft.AspNetCore.Authentication
return Task.CompletedTask; return Task.CompletedTask;
} }
public async Task ChallengeAsync(AuthenticationProperties properties) public async Task ChallengeAsync(AuthenticationProperties? properties)
{ {
var target = ResolveTarget(Options.ForwardChallenge); var target = ResolveTarget(Options.ForwardChallenge);
if (target != null) if (target != null)
@ -221,12 +221,12 @@ namespace Microsoft.AspNetCore.Authentication
return; return;
} }
properties = properties ?? new AuthenticationProperties(); properties ??= new AuthenticationProperties();
await HandleChallengeAsync(properties); await HandleChallengeAsync(properties);
Logger.AuthenticationSchemeChallenged(Scheme.Name); Logger.AuthenticationSchemeChallenged(Scheme.Name);
} }
public async Task ForbidAsync(AuthenticationProperties properties) public async Task ForbidAsync(AuthenticationProperties? properties)
{ {
var target = ResolveTarget(Options.ForwardForbid); var target = ResolveTarget(Options.ForwardForbid);
if (target != null) if (target != null)
@ -235,7 +235,7 @@ namespace Microsoft.AspNetCore.Authentication
return; return;
} }
properties = properties ?? new AuthenticationProperties(); properties ??= new AuthenticationProperties();
await HandleForbiddenAsync(properties); await HandleForbiddenAsync(properties);
Logger.AuthenticationSchemeForbidden(Scheme.Name); Logger.AuthenticationSchemeForbidden(Scheme.Name);
} }

View File

@ -26,17 +26,17 @@ namespace Microsoft.AspNetCore.Authentication
/// <summary> /// <summary>
/// Gets or sets the issuer that should be used for any claims that are created /// Gets or sets the issuer that should be used for any claims that are created
/// </summary> /// </summary>
public string ClaimsIssuer { get; set; } public string? ClaimsIssuer { get; set; }
/// <summary> /// <summary>
/// Instance used for events /// Instance used for events
/// </summary> /// </summary>
public object Events { get; set; } public object? Events { get; set; }
/// <summary> /// <summary>
/// If set, will be used as the service type to get the Events instance instead of the property. /// If set, will be used as the service type to get the Events instance instead of the property.
/// </summary> /// </summary>
public Type EventsType { get; set; } public Type? EventsType { get; set; }
/// <summary> /// <summary>
/// If set, this specifies a default scheme that authentication handlers should forward all authentication operations to /// If set, this specifies a default scheme that authentication handlers should forward all authentication operations to
@ -44,42 +44,42 @@ namespace Microsoft.AspNetCore.Authentication
/// setting first, followed by checking the ForwardDefaultSelector, followed by ForwardDefault. The first non null result /// setting first, followed by checking the ForwardDefaultSelector, followed by ForwardDefault. The first non null result
/// will be used as the target scheme to forward to. /// will be used as the target scheme to forward to.
/// </summary> /// </summary>
public string ForwardDefault { get; set; } public string? ForwardDefault { get; set; }
/// <summary> /// <summary>
/// If set, this specifies the target scheme that this scheme should forward AuthenticateAsync calls to. /// If set, this specifies the target scheme that this scheme should forward AuthenticateAsync calls to.
/// For example Context.AuthenticateAsync("ThisScheme") => Context.AuthenticateAsync("ForwardAuthenticateValue"); /// For example Context.AuthenticateAsync("ThisScheme") => Context.AuthenticateAsync("ForwardAuthenticateValue");
/// Set the target to the current scheme to disable forwarding and allow normal processing. /// Set the target to the current scheme to disable forwarding and allow normal processing.
/// </summary> /// </summary>
public string ForwardAuthenticate { get; set; } public string? ForwardAuthenticate { get; set; }
/// <summary> /// <summary>
/// If set, this specifies the target scheme that this scheme should forward ChallengeAsync calls to. /// If set, this specifies the target scheme that this scheme should forward ChallengeAsync calls to.
/// For example Context.ChallengeAsync("ThisScheme") => Context.ChallengeAsync("ForwardChallengeValue"); /// For example Context.ChallengeAsync("ThisScheme") => Context.ChallengeAsync("ForwardChallengeValue");
/// Set the target to the current scheme to disable forwarding and allow normal processing. /// Set the target to the current scheme to disable forwarding and allow normal processing.
/// </summary> /// </summary>
public string ForwardChallenge { get; set; } public string? ForwardChallenge { get; set; }
/// <summary> /// <summary>
/// If set, this specifies the target scheme that this scheme should forward ForbidAsync calls to. /// If set, this specifies the target scheme that this scheme should forward ForbidAsync calls to.
/// For example Context.ForbidAsync("ThisScheme") => Context.ForbidAsync("ForwardForbidValue"); /// For example Context.ForbidAsync("ThisScheme") => Context.ForbidAsync("ForwardForbidValue");
/// Set the target to the current scheme to disable forwarding and allow normal processing. /// Set the target to the current scheme to disable forwarding and allow normal processing.
/// </summary> /// </summary>
public string ForwardForbid { get; set; } public string? ForwardForbid { get; set; }
/// <summary> /// <summary>
/// If set, this specifies the target scheme that this scheme should forward SignInAsync calls to. /// If set, this specifies the target scheme that this scheme should forward SignInAsync calls to.
/// For example Context.SignInAsync("ThisScheme") => Context.SignInAsync("ForwardSignInValue"); /// For example Context.SignInAsync("ThisScheme") => Context.SignInAsync("ForwardSignInValue");
/// Set the target to the current scheme to disable forwarding and allow normal processing. /// Set the target to the current scheme to disable forwarding and allow normal processing.
/// </summary> /// </summary>
public string ForwardSignIn { get; set; } public string? ForwardSignIn { get; set; }
/// <summary> /// <summary>
/// If set, this specifies the target scheme that this scheme should forward SignOutAsync calls to. /// If set, this specifies the target scheme that this scheme should forward SignOutAsync calls to.
/// For example Context.SignOutAsync("ThisScheme") => Context.SignOutAsync("ForwardSignOutValue"); /// For example Context.SignOutAsync("ThisScheme") => Context.SignOutAsync("ForwardSignOutValue");
/// Set the target to the current scheme to disable forwarding and allow normal processing. /// Set the target to the current scheme to disable forwarding and allow normal processing.
/// </summary> /// </summary>
public string ForwardSignOut { get; set; } public string? ForwardSignOut { get; set; }
/// <summary> /// <summary>
/// Used to select a default scheme for the current request that authentication handlers should forward all authentication operations to /// Used to select a default scheme for the current request that authentication handlers should forward all authentication operations to
@ -87,7 +87,7 @@ namespace Microsoft.AspNetCore.Authentication
/// setting first, followed by checking the ForwardDefaultSelector, followed by ForwardDefault. The first non null result /// setting first, followed by checking the ForwardDefaultSelector, followed by ForwardDefault. The first non null result
/// will be used as the target scheme to forward to. /// will be used as the target scheme to forward to.
/// </summary> /// </summary>
public Func<HttpContext, string> ForwardDefaultSelector { get; set; } public Func<HttpContext, string>? ForwardDefaultSelector { get; set; }
} }
} }

View File

@ -58,7 +58,7 @@ namespace Microsoft.Extensions.DependencyInjection
public void PostConfigure(string name, TOptions options) public void PostConfigure(string name, TOptions options)
{ {
options.SignInScheme = options.SignInScheme ?? _authOptions.DefaultSignInScheme; options.SignInScheme ??= _authOptions.DefaultSignInScheme;
} }
} }

View File

@ -27,18 +27,18 @@ namespace Microsoft.AspNetCore.Authentication
/// <summary> /// <summary>
/// Additional state values for the authentication session. /// Additional state values for the authentication session.
/// </summary> /// </summary>
public AuthenticationProperties Properties { get; set; } public AuthenticationProperties? Properties { get; set; }
/// <summary> /// <summary>
/// Gets or sets the return URL that will be flowed up to the access denied page. /// Gets or sets the return URL that will be flowed up to the access denied page.
/// If <see cref="ReturnUrlParameter"/> is not set, this property is not used. /// If <see cref="ReturnUrlParameter"/> is not set, this property is not used.
/// </summary> /// </summary>
public string ReturnUrl { get; set; } public string? ReturnUrl { get; set; }
/// <summary> /// <summary>
/// Gets or sets the parameter name that will be used to flow the return URL. /// Gets or sets the parameter name that will be used to flow the return URL.
/// By default, this property is set to <see cref="RemoteAuthenticationOptions.ReturnUrlParameter"/>. /// By default, this property is set to <see cref="RemoteAuthenticationOptions.ReturnUrlParameter"/>.
/// </summary> /// </summary>
public string ReturnUrlParameter { get; set; } public string ReturnUrlParameter { get; set; } = default!;
} }
} }

View File

@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Authentication
/// <summary> /// <summary>
/// The <see cref="HandleRequestResult"/> which is used by the handler. /// The <see cref="HandleRequestResult"/> which is used by the handler.
/// </summary> /// </summary>
public HandleRequestResult Result { get; protected set; } public HandleRequestResult Result { get; protected set; } = default!;
/// <summary> /// <summary>
/// Discontinue all processing for this request and return to the client. /// Discontinue all processing for this request and return to the client.
@ -29,4 +29,4 @@ namespace Microsoft.AspNetCore.Authentication
/// </summary> /// </summary>
public void SkipHandler() => Result = HandleRequestResult.SkipHandler(); public void SkipHandler() => Result = HandleRequestResult.SkipHandler();
} }
} }

View File

@ -19,12 +19,12 @@ namespace Microsoft.AspNetCore.Authentication
/// <param name="scheme">The authentication scheme.</param> /// <param name="scheme">The authentication scheme.</param>
/// <param name="options">The authentication options associated with the scheme.</param> /// <param name="options">The authentication options associated with the scheme.</param>
/// <param name="properties">The authentication properties.</param> /// <param name="properties">The authentication properties.</param>
protected PrincipalContext(HttpContext context, AuthenticationScheme scheme, TOptions options, AuthenticationProperties properties) protected PrincipalContext(HttpContext context, AuthenticationScheme scheme, TOptions options, AuthenticationProperties? properties)
: base(context, scheme, options, properties) { } : base(context, scheme, options, properties) { }
/// <summary> /// <summary>
/// Gets the <see cref="ClaimsPrincipal"/> containing the user claims. /// Gets the <see cref="ClaimsPrincipal"/> containing the user claims.
/// </summary> /// </summary>
public virtual ClaimsPrincipal Principal { get; set; } public virtual ClaimsPrincipal? Principal { get; set; }
} }
} }

View File

@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Authentication
/// <param name="scheme">The authentication scheme.</param> /// <param name="scheme">The authentication scheme.</param>
/// <param name="options">The authentication options associated with the scheme.</param> /// <param name="options">The authentication options associated with the scheme.</param>
/// <param name="properties">The authentication properties.</param> /// <param name="properties">The authentication properties.</param>
protected PropertiesContext(HttpContext context, AuthenticationScheme scheme, TOptions options, AuthenticationProperties properties) protected PropertiesContext(HttpContext context, AuthenticationScheme scheme, TOptions options, AuthenticationProperties? properties)
: base(context, scheme, options) : base(context, scheme, options)
{ {
Properties = properties ?? new AuthenticationProperties(); Properties = properties ?? new AuthenticationProperties();

View File

@ -23,14 +23,14 @@ namespace Microsoft.AspNetCore.Authentication
HttpContext context, HttpContext context,
AuthenticationScheme scheme, AuthenticationScheme scheme,
TOptions options, TOptions options,
AuthenticationProperties properties) AuthenticationProperties? properties)
: base(context, scheme, options) : base(context, scheme, options)
=> Properties = properties ?? new AuthenticationProperties(); => Properties = properties ?? new AuthenticationProperties();
/// <summary> /// <summary>
/// Gets the <see cref="ClaimsPrincipal"/> containing the user claims. /// Gets the <see cref="ClaimsPrincipal"/> containing the user claims.
/// </summary> /// </summary>
public ClaimsPrincipal Principal { get; set; } public ClaimsPrincipal? Principal { get; set; }
/// <summary> /// <summary>
/// Gets or sets the <see cref="AuthenticationProperties"/>. /// Gets or sets the <see cref="AuthenticationProperties"/>.
@ -40,10 +40,10 @@ namespace Microsoft.AspNetCore.Authentication
/// <summary> /// <summary>
/// Calls success creating a ticket with the <see cref="Principal"/> and <see cref="Properties"/>. /// Calls success creating a ticket with the <see cref="Principal"/> and <see cref="Properties"/>.
/// </summary> /// </summary>
public void Success() => Result = HandleRequestResult.Success(new AuthenticationTicket(Principal, Properties, Scheme.Name)); public void Success() => Result = HandleRequestResult.Success(new AuthenticationTicket(Principal!, Properties, Scheme.Name));
public void Fail(Exception failure) => Result = HandleRequestResult.Fail(failure); public void Fail(Exception failure) => Result = HandleRequestResult.Fail(failure);
public void Fail(string failureMessage) => Result = HandleRequestResult.Fail(failureMessage); public void Fail(string failureMessage) => Result = HandleRequestResult.Fail(failureMessage);
} }
} }

View File

@ -24,11 +24,11 @@ namespace Microsoft.AspNetCore.Authentication
/// <summary> /// <summary>
/// User friendly error message for the error. /// User friendly error message for the error.
/// </summary> /// </summary>
public Exception Failure { get; set; } public Exception? Failure { get; set; }
/// <summary> /// <summary>
/// Additional state values for the authentication session. /// Additional state values for the authentication session.
/// </summary> /// </summary>
public AuthenticationProperties Properties { get; set; } public AuthenticationProperties? Properties { get; set; }
} }
} }

View File

@ -12,6 +12,8 @@ namespace Microsoft.AspNetCore.Authentication
/// </summary> /// </summary>
public abstract class ResultContext<TOptions> : BaseContext<TOptions> where TOptions : AuthenticationSchemeOptions public abstract class ResultContext<TOptions> : BaseContext<TOptions> where TOptions : AuthenticationSchemeOptions
{ {
private AuthenticationProperties? _properties;
/// <summary> /// <summary>
/// Constructor. /// Constructor.
/// </summary> /// </summary>
@ -24,26 +26,30 @@ namespace Microsoft.AspNetCore.Authentication
/// <summary> /// <summary>
/// Gets or sets the <see cref="ClaimsPrincipal"/> containing the user claims. /// Gets or sets the <see cref="ClaimsPrincipal"/> containing the user claims.
/// </summary> /// </summary>
public ClaimsPrincipal Principal { get; set; } public ClaimsPrincipal? Principal { get; set; }
private AuthenticationProperties _properties;
/// <summary> /// <summary>
/// Gets or sets the <see cref="AuthenticationProperties"/>. /// Gets or sets the <see cref="AuthenticationProperties"/>.
/// </summary> /// </summary>
public AuthenticationProperties Properties { public AuthenticationProperties Properties
get => _properties ?? (_properties = new AuthenticationProperties()); {
get
{
_properties ??= new AuthenticationProperties();
return _properties;
}
set => _properties = value; set => _properties = value;
} }
/// <summary> /// <summary>
/// Gets the <see cref="AuthenticateResult"/> result. /// Gets the <see cref="AuthenticateResult"/> result.
/// </summary> /// </summary>
public AuthenticateResult Result { get; private set; } public AuthenticateResult Result { get; private set; } = default!;
/// <summary> /// <summary>
/// Calls success creating a ticket with the <see cref="Principal"/> and <see cref="Properties"/>. /// Calls success creating a ticket with the <see cref="Principal"/> and <see cref="Properties"/>.
/// </summary> /// </summary>
public void Success() => Result = HandleRequestResult.Success(new AuthenticationTicket(Principal, Properties, Scheme.Name)); public void Success() => Result = HandleRequestResult.Success(new AuthenticationTicket(Principal!, Properties, Scheme.Name));
/// <summary> /// <summary>
/// Indicates that there was no information returned for this authentication scheme. /// Indicates that there was no information returned for this authentication scheme.

View File

@ -19,6 +19,6 @@ namespace Microsoft.AspNetCore.Authentication
: base(context, scheme, options, ticket?.Properties) : base(context, scheme, options, ticket?.Properties)
=> Principal = ticket?.Principal; => Principal = ticket?.Principal;
public string ReturnUri { get; set; } public string? ReturnUri { get; set; }
} }
} }

View File

@ -1,11 +1,15 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics.CodeAnalysis;
namespace Microsoft.AspNetCore.Authentication namespace Microsoft.AspNetCore.Authentication
{ {
public interface IDataSerializer<TModel> public interface IDataSerializer<TModel>
{ {
byte[] Serialize(TModel model); byte[] Serialize(TModel model);
[return: MaybeNull]
TModel Deserialize(byte[] data); TModel Deserialize(byte[] data);
} }
} }

View File

@ -1,13 +1,20 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics.CodeAnalysis;
namespace Microsoft.AspNetCore.Authentication namespace Microsoft.AspNetCore.Authentication
{ {
public interface ISecureDataFormat<TData> public interface ISecureDataFormat<TData>
{ {
string Protect(TData data); string Protect(TData data);
string Protect(TData data, string purpose);
string Protect(TData data, string? purpose);
[return: MaybeNull]
TData Unprotect(string protectedText); TData Unprotect(string protectedText);
TData Unprotect(string protectedText, string purpose);
[return: MaybeNull]
TData Unprotect(string protectedText, string? purpose);
} }
} }

View File

@ -7,7 +7,7 @@ namespace Microsoft.AspNetCore.Authentication
{ {
public static class JsonDocumentAuthExtensions public static class JsonDocumentAuthExtensions
{ {
public static string GetString(this JsonElement element, string key) public static string? GetString(this JsonElement element, string key)
{ {
if (element.TryGetProperty(key, out var property) && property.ValueKind != JsonValueKind.Null) if (element.TryGetProperty(key, out var property) && property.ValueKind != JsonValueKind.Null)
{ {

View File

@ -7,20 +7,20 @@ namespace Microsoft.Extensions.Logging
{ {
internal static class LoggingExtensions internal static class LoggingExtensions
{ {
private static readonly Action<ILogger, string, Exception> _authenticationSchemeAuthenticated; private static readonly Action<ILogger, string, Exception?> _authenticationSchemeAuthenticated;
private static readonly Action<ILogger, string, Exception> _authenticationSchemeNotAuthenticated; private static readonly Action<ILogger, string, Exception?> _authenticationSchemeNotAuthenticated;
private static readonly Action<ILogger, string, string, Exception> _authenticationSchemeNotAuthenticatedWithFailure; private static readonly Action<ILogger, string, string, Exception?> _authenticationSchemeNotAuthenticatedWithFailure;
private static readonly Action<ILogger, string, Exception> _authenticationSchemeChallenged; private static readonly Action<ILogger, string, Exception?> _authenticationSchemeChallenged;
private static readonly Action<ILogger, string, Exception> _authenticationSchemeForbidden; private static readonly Action<ILogger, string, Exception?> _authenticationSchemeForbidden;
private static readonly Action<ILogger, string, Exception> _remoteAuthenticationError; private static readonly Action<ILogger, string, Exception?> _remoteAuthenticationError;
private static readonly Action<ILogger, Exception> _signInHandled; private static readonly Action<ILogger, Exception?> _signInHandled;
private static readonly Action<ILogger, Exception> _signInSkipped; private static readonly Action<ILogger, Exception?> _signInSkipped;
private static readonly Action<ILogger, string, Exception> _correlationPropertyNotFound; private static readonly Action<ILogger, string, Exception?> _correlationPropertyNotFound;
private static readonly Action<ILogger, string, Exception> _correlationCookieNotFound; private static readonly Action<ILogger, string, Exception?> _correlationCookieNotFound;
private static readonly Action<ILogger, string, string, Exception> _unexpectedCorrelationCookieValue; private static readonly Action<ILogger, string, string, Exception?> _unexpectedCorrelationCookieValue;
private static readonly Action<ILogger, Exception> _accessDeniedError; private static readonly Action<ILogger, Exception?> _accessDeniedError;
private static readonly Action<ILogger, Exception> _accessDeniedContextHandled; private static readonly Action<ILogger, Exception?> _accessDeniedContextHandled;
private static readonly Action<ILogger, Exception> _accessDeniedContextSkipped; private static readonly Action<ILogger, Exception?> _accessDeniedContextSkipped;
static LoggingExtensions() static LoggingExtensions()
{ {

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Description>ASP.NET Core common types used by the various authentication middleware components.</Description> <Description>ASP.NET Core common types used by the various authentication middleware components.</Description>
@ -8,6 +8,7 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore;authentication;security</PackageTags> <PackageTags>aspnetcore;authentication;security</PackageTags>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -18,19 +18,19 @@ namespace Microsoft.AspNetCore.Authentication
public PolicySchemeHandler(IOptionsMonitor<PolicySchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) public PolicySchemeHandler(IOptionsMonitor<PolicySchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
{ } { }
protected override Task HandleChallengeAsync(AuthenticationProperties properties) protected override Task HandleChallengeAsync(AuthenticationProperties? properties)
=> throw new NotImplementedException(); => throw new NotImplementedException();
protected override Task HandleForbiddenAsync(AuthenticationProperties properties) protected override Task HandleForbiddenAsync(AuthenticationProperties? properties)
=> throw new NotImplementedException(); => throw new NotImplementedException();
protected override Task HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties properties) protected override Task HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties? properties)
=> throw new NotImplementedException(); => throw new NotImplementedException();
protected override Task HandleSignOutAsync(AuthenticationProperties properties) protected override Task HandleSignOutAsync(AuthenticationProperties? properties)
=> throw new NotImplementedException(); => throw new NotImplementedException();
protected override Task<AuthenticateResult> HandleAuthenticateAsync() protected override Task<AuthenticateResult> HandleAuthenticateAsync()
=> throw new NotImplementedException(); => throw new NotImplementedException();
} }
} }

View File

@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Authentication
} }
} }
public virtual AuthenticationProperties Deserialize(byte[] data) public virtual AuthenticationProperties? Deserialize(byte[] data)
{ {
using (var memory = new MemoryStream(data)) using (var memory = new MemoryStream(data))
{ {
@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Authentication
} }
} }
public virtual AuthenticationProperties Read(BinaryReader reader) public virtual AuthenticationProperties? Read(BinaryReader reader)
{ {
if (reader == null) if (reader == null)
{ {
@ -72,12 +72,12 @@ namespace Microsoft.AspNetCore.Authentication
} }
var count = reader.ReadInt32(); var count = reader.ReadInt32();
var extra = new Dictionary<string, string>(count); var extra = new Dictionary<string, string?>(count);
for (var index = 0; index != count; ++index) for (var index = 0; index != count; ++index)
{ {
string key = reader.ReadString(); var key = reader.ReadString();
string value = reader.ReadString(); var value = reader.ReadString();
extra.Add(key, value); extra.Add(key, value);
} }
return new AuthenticationProperties(extra); return new AuthenticationProperties(extra);

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Diagnostics;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -18,7 +19,7 @@ namespace Microsoft.AspNetCore.Authentication
private const string CorrelationMarker = "N"; private const string CorrelationMarker = "N";
private const string AuthSchemeKey = ".AuthScheme"; private const string AuthSchemeKey = ".AuthScheme";
protected string SignInScheme => Options.SignInScheme; protected string? SignInScheme => Options.SignInScheme;
/// <summary> /// <summary>
/// The handler calls methods on the events which give the application control at certain points where processing is occurring. /// The handler calls methods on the events which give the application control at certain points where processing is occurring.
@ -26,7 +27,7 @@ namespace Microsoft.AspNetCore.Authentication
/// </summary> /// </summary>
protected new RemoteAuthenticationEvents Events protected new RemoteAuthenticationEvents Events
{ {
get { return (RemoteAuthenticationEvents)base.Events; } get { return (RemoteAuthenticationEvents)base.Events!; }
set { base.Events = value; } set { base.Events = value; }
} }
@ -46,9 +47,9 @@ namespace Microsoft.AspNetCore.Authentication
return false; return false;
} }
AuthenticationTicket ticket = null; AuthenticationTicket? ticket = null;
Exception exception = null; Exception? exception = null;
AuthenticationProperties properties = null; AuthenticationProperties? properties = null;
try try
{ {
var authResult = await HandleRemoteAuthenticateAsync(); var authResult = await HandleRemoteAuthenticateAsync();
@ -109,6 +110,7 @@ namespace Microsoft.AspNetCore.Authentication
} }
// We have a ticket if we get here // We have a ticket if we get here
Debug.Assert(ticket != null);
var ticketContext = new TicketReceivedContext(Context, Scheme, Options, ticket) var ticketContext = new TicketReceivedContext(Context, Scheme, Options, ticket)
{ {
ReturnUri = ticket.Properties.RedirectUri ReturnUri = ticket.Properties.RedirectUri
@ -135,7 +137,7 @@ namespace Microsoft.AspNetCore.Authentication
} }
} }
await Context.SignInAsync(SignInScheme, ticketContext.Principal, ticketContext.Properties); await Context.SignInAsync(SignInScheme, ticketContext.Principal!, ticketContext.Properties);
// Default redirect path is the base path // Default redirect path is the base path
if (string.IsNullOrEmpty(ticketContext.ReturnUri)) if (string.IsNullOrEmpty(ticketContext.ReturnUri))
@ -165,10 +167,9 @@ namespace Microsoft.AspNetCore.Authentication
} }
// The SignInScheme may be shared with multiple providers, make sure this provider issued the identity. // The SignInScheme may be shared with multiple providers, make sure this provider issued the identity.
string authenticatedScheme;
var ticket = result.Ticket; var ticket = result.Ticket;
if (ticket != null && ticket.Principal != null && ticket.Properties != null if (ticket != null && ticket.Principal != null && ticket.Properties != null
&& ticket.Properties.Items.TryGetValue(AuthSchemeKey, out authenticatedScheme) && ticket.Properties.Items.TryGetValue(AuthSchemeKey, out var authenticatedScheme)
&& string.Equals(Scheme.Name, authenticatedScheme, StringComparison.Ordinal)) && string.Equals(Scheme.Name, authenticatedScheme, StringComparison.Ordinal))
{ {
return AuthenticateResult.Success(new AuthenticationTicket(ticket.Principal, return AuthenticateResult.Success(new AuthenticationTicket(ticket.Principal,
@ -211,9 +212,9 @@ namespace Microsoft.AspNetCore.Authentication
throw new ArgumentNullException(nameof(properties)); throw new ArgumentNullException(nameof(properties));
} }
if (!properties.Items.TryGetValue(CorrelationProperty, out string correlationId)) if (!properties.Items.TryGetValue(CorrelationProperty, out var correlationId))
{ {
Logger.CorrelationPropertyNotFound(Options.CorrelationCookie.Name); Logger.CorrelationPropertyNotFound(Options.CorrelationCookie.Name!);
return false; return false;
} }

View File

@ -70,17 +70,17 @@ namespace Microsoft.AspNetCore.Authentication
/// This cannot be set at the same time as BackchannelCertificateValidator unless the value /// This cannot be set at the same time as BackchannelCertificateValidator unless the value
/// can be downcast to a WebRequestHandler. /// can be downcast to a WebRequestHandler.
/// </summary> /// </summary>
public HttpMessageHandler BackchannelHttpHandler { get; set; } public HttpMessageHandler? BackchannelHttpHandler { get; set; }
/// <summary> /// <summary>
/// Used to communicate with the remote identity provider. /// Used to communicate with the remote identity provider.
/// </summary> /// </summary>
public HttpClient Backchannel { get; set; } public HttpClient Backchannel { get; set; } = default!;
/// <summary> /// <summary>
/// Gets or sets the type used to secure data. /// Gets or sets the type used to secure data.
/// </summary> /// </summary>
public IDataProtectionProvider DataProtectionProvider { get; set; } public IDataProtectionProvider? DataProtectionProvider { get; set; }
/// <summary> /// <summary>
/// The request path within the application's base path where the user-agent will be returned. /// The request path within the application's base path where the user-agent will be returned.
@ -110,7 +110,7 @@ namespace Microsoft.AspNetCore.Authentication
/// This value typically corresponds to a cookie middleware registered in the Startup class. /// This value typically corresponds to a cookie middleware registered in the Startup class.
/// When omitted, <see cref="AuthenticationOptions.DefaultSignInScheme"/> is used as a fallback value. /// When omitted, <see cref="AuthenticationOptions.DefaultSignInScheme"/> is used as a fallback value.
/// </summary> /// </summary>
public string SignInScheme { get; set; } public string? SignInScheme { get; set; }
/// <summary> /// <summary>
/// Gets or sets the time limit for completing the authentication flow (15 minutes by default). /// Gets or sets the time limit for completing the authentication flow (15 minutes by default).
@ -119,7 +119,7 @@ namespace Microsoft.AspNetCore.Authentication
public new RemoteAuthenticationEvents Events public new RemoteAuthenticationEvents Events
{ {
get => (RemoteAuthenticationEvents)base.Events; get => (RemoteAuthenticationEvents)base.Events!;
set => base.Events = value; set => base.Events = value;
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Authentication
/// <summary> /// <summary>
/// Gets an optional value that is appended to the request path base. /// Gets an optional value that is appended to the request path base.
/// </summary> /// </summary>
protected virtual string AdditionalPath { get; } protected virtual string? AdditionalPath { get; }
public override CookieOptions Build(HttpContext context, DateTimeOffset expiresFrom) public override CookieOptions Build(HttpContext context, DateTimeOffset expiresFrom)
{ {

View File

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.DataProtection;
namespace Microsoft.AspNetCore.Authentication namespace Microsoft.AspNetCore.Authentication
@ -21,7 +22,7 @@ namespace Microsoft.AspNetCore.Authentication
return Protect(data, purpose: null); return Protect(data, purpose: null);
} }
public string Protect(TData data, string purpose) public string Protect(TData data, string? purpose)
{ {
var userData = _serializer.Serialize(data); var userData = _serializer.Serialize(data);
@ -35,12 +36,14 @@ namespace Microsoft.AspNetCore.Authentication
return Base64UrlTextEncoder.Encode(protectedData); return Base64UrlTextEncoder.Encode(protectedData);
} }
[return: MaybeNull]
public TData Unprotect(string protectedText) public TData Unprotect(string protectedText)
{ {
return Unprotect(protectedText, purpose: null); return Unprotect(protectedText, purpose: null);
} }
public TData Unprotect(string protectedText, string purpose) [return: MaybeNull]
public TData Unprotect(string protectedText, string? purpose)
{ {
try try
{ {
@ -76,4 +79,4 @@ namespace Microsoft.AspNetCore.Authentication
} }
} }
} }
} }

View File

@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Authentication
public SignInAuthenticationHandler(IOptionsMonitor<TOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) public SignInAuthenticationHandler(IOptionsMonitor<TOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
{ } { }
public virtual Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties) public virtual Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties? properties)
{ {
var target = ResolveTarget(Options.ForwardSignIn); var target = ResolveTarget(Options.ForwardSignIn);
return (target != null) return (target != null)
@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.Authentication
/// <param name="user"></param> /// <param name="user"></param>
/// <param name="properties"></param> /// <param name="properties"></param>
/// <returns>A Task.</returns> /// <returns>A Task.</returns>
protected abstract Task HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties properties); protected abstract Task HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties? properties);
} }
} }

View File

@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Authentication
public SignOutAuthenticationHandler(IOptionsMonitor<TOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) public SignOutAuthenticationHandler(IOptionsMonitor<TOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
{ } { }
public virtual Task SignOutAsync(AuthenticationProperties properties) public virtual Task SignOutAsync(AuthenticationProperties? properties)
{ {
var target = ResolveTarget(Options.ForwardSignOut); var target = ResolveTarget(Options.ForwardSignOut);
return (target != null) return (target != null)
@ -31,6 +31,6 @@ namespace Microsoft.AspNetCore.Authentication
/// </summary> /// </summary>
/// <param name="properties"></param> /// <param name="properties"></param>
/// <returns>A Task.</returns> /// <returns>A Task.</returns>
protected abstract Task HandleSignOutAsync(AuthenticationProperties properties); protected abstract Task HandleSignOutAsync(AuthenticationProperties? properties);
} }
} }

View File

@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Authentication
} }
} }
public virtual AuthenticationTicket Deserialize(byte[] data) public virtual AuthenticationTicket? Deserialize(byte[] data)
{ {
using (var memory = new MemoryStream(data)) using (var memory = new MemoryStream(data))
{ {
@ -142,7 +142,7 @@ namespace Microsoft.AspNetCore.Authentication
} }
} }
public virtual AuthenticationTicket Read(BinaryReader reader) public virtual AuthenticationTicket? Read(BinaryReader reader)
{ {
if (reader == null) if (reader == null)
{ {

3
src/Security/build.cmd Normal file
View File

@ -0,0 +1,3 @@
@ECHO OFF
SET RepoRoot=%~dp0..\..
%RepoRoot%\build.cmd -projects %~dp0**\*.*proj %*

View File

@ -1,6 +1,8 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#nullable enable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
@ -61,7 +63,7 @@ namespace Microsoft.AspNetCore.Internal
public bool ThrowForPartialCookies { get; set; } public bool ThrowForPartialCookies { get; set; }
// Parse the "chunks-XX" to determine how many chunks there should be. // Parse the "chunks-XX" to determine how many chunks there should be.
private static int ParseChunksCount(string value) private static int ParseChunksCount(string? value)
{ {
if (value != null && value.StartsWith(ChunkCountPrefix, StringComparison.Ordinal)) if (value != null && value.StartsWith(ChunkCountPrefix, StringComparison.Ordinal))
{ {
@ -82,7 +84,7 @@ namespace Microsoft.AspNetCore.Internal
/// <param name="context"></param> /// <param name="context"></param>
/// <param name="key"></param> /// <param name="key"></param>
/// <returns>The reassembled cookie, if any, or null.</returns> /// <returns>The reassembled cookie, if any, or null.</returns>
public string GetRequestCookie(HttpContext context, string key) public string? GetRequestCookie(HttpContext context, string key)
{ {
if (context == null) if (context == null)
{ {
@ -144,7 +146,7 @@ namespace Microsoft.AspNetCore.Internal
/// <param name="key"></param> /// <param name="key"></param>
/// <param name="value"></param> /// <param name="value"></param>
/// <param name="options"></param> /// <param name="options"></param>
public void AppendResponseCookie(HttpContext context, string key, string value, CookieOptions options) public void AppendResponseCookie(HttpContext context, string key, string? value, CookieOptions options)
{ {
if (context == null) if (context == null)
{ {