AuthenticateResult->AuthenticationTicket->AuthenticationProperties->ClaimsPrincipal
using System; using System.Diagnostics.CodeAnalysis; using System.Security.Claims; namespace Microsoft.AspNetCore.Authentication { /// <summary> /// Contains the result of an Authenticate call /// </summary> public class AuthenticateResult { /// <summary> /// Creates a new <see cref="AuthenticateResult"/> instance. /// </summary> protected AuthenticateResult() { } /// <summary> /// If a ticket was produced, authenticate was successful. /// </summary> [MemberNotNullWhen(true, nameof(Ticket), nameof(Principal), nameof(Properties))] public bool Succeeded => Ticket != null; /// <summary> /// The authentication ticket. /// </summary> public AuthenticationTicket? Ticket { get; protected set; } /// <summary> /// Gets the claims-principal with authenticated user identities. /// </summary> public ClaimsPrincipal? Principal => Ticket?.Principal; /// <summary> /// Additional state values for the authentication session. /// </summary> public AuthenticationProperties? Properties { get; protected set; } /// <summary> /// Holds failure information from the authentication. /// </summary> public Exception? Failure { get; protected set; } /// <summary> /// Indicates that there was no information returned for this authentication scheme. /// </summary> public bool None { get; protected set; } /// <summary> /// Create a new deep copy of the result /// </summary> /// <returns>A copy of the result</returns> public AuthenticateResult Clone() { if (None) { return NoResult(); } if (Failure != null) { return Fail(Failure, Properties?.Clone()); } if (Succeeded) { return Success(Ticket!.Clone()); } // This shouldn't happen throw new NotImplementedException(); } /// <summary> /// Indicates that authentication was successful. /// </summary> /// <param name="ticket">The ticket representing the authentication result.</param> /// <returns>The result.</returns> public static AuthenticateResult Success(AuthenticationTicket ticket) { if (ticket == null) { throw new ArgumentNullException(nameof(ticket)); } return new AuthenticateResult() { Ticket = ticket, Properties = ticket.Properties }; } /// <summary> /// Indicates that there was no information returned for this authentication scheme. /// </summary> /// <returns>The result.</returns> public static AuthenticateResult NoResult() { return new AuthenticateResult() { None = true }; } /// <summary> /// Indicates that there was a failure during authentication. /// </summary> /// <param name="failure">The failure exception.</param> /// <returns>The result.</returns> public static AuthenticateResult Fail(Exception failure) { return new AuthenticateResult() { Failure = failure }; } /// <summary> /// Indicates that there was a failure during authentication. /// </summary> /// <param name="failure">The failure exception.</param> /// <param name="properties">Additional state values for the authentication session.</param> /// <returns>The result.</returns> public static AuthenticateResult Fail(Exception failure, AuthenticationProperties? properties) { return new AuthenticateResult() { Failure = failure, Properties = properties }; } /// <summary> /// Indicates that there was a failure during authentication. /// </summary> /// <param name="failureMessage">The failure message.</param> /// <returns>The result.</returns> public static AuthenticateResult Fail(string failureMessage) => Fail(new Exception(failureMessage)); /// <summary> /// Indicates that there was a failure during authentication. /// </summary> /// <param name="failureMessage">The failure message.</param> /// <param name="properties">Additional state values for the authentication session.</param> /// <returns>The result.</returns> public static AuthenticateResult Fail(string failureMessage, AuthenticationProperties? properties) => Fail(new Exception(failureMessage), properties); } }
using System; using System.Security.Claims; namespace Microsoft.AspNetCore.Authentication { /// <summary> /// Contains user identity information as well as additional authentication state. /// </summary> public class AuthenticationTicket { /// <summary> /// Initializes a new instance of the <see cref="AuthenticationTicket"/> class /// </summary> /// <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="authenticationScheme">the authentication scheme that was responsible for this ticket.</param> public AuthenticationTicket(ClaimsPrincipal principal, AuthenticationProperties? properties, string authenticationScheme) { if (principal == null) { throw new ArgumentNullException(nameof(principal)); } AuthenticationScheme = authenticationScheme; Principal = principal; Properties = properties ?? new AuthenticationProperties(); } /// <summary> /// Initializes a new instance of the <see cref="AuthenticationTicket"/> class /// </summary> /// <param name="principal">the <see cref="ClaimsPrincipal"/> that represents the authenticated user.</param> /// <param name="authenticationScheme">the authentication scheme that was responsible for this ticket.</param> public AuthenticationTicket(ClaimsPrincipal principal, string authenticationScheme) : this(principal, properties: null, authenticationScheme: authenticationScheme) { } /// <summary> /// Gets the authentication scheme that was responsible for this ticket. /// </summary> public string AuthenticationScheme { get; } /// <summary> /// Gets the claims-principal with authenticated user identities. /// </summary> public ClaimsPrincipal Principal { get; } /// <summary> /// Additional state values for the authentication session. /// </summary> public AuthenticationProperties Properties { get; } /// <summary> /// Returns a copy of the ticket. /// </summary> /// <remarks> /// The method clones the <see cref="Principal"/> by calling <see cref="ClaimsIdentity.Clone"/> on each of the <see cref="ClaimsPrincipal.Identities"/>. /// </remarks> /// <returns>A copy of the ticket</returns> public AuthenticationTicket Clone() { var principal = new ClaimsPrincipal(); foreach (var identity in Principal.Identities) { principal.AddIdentity(identity.Clone()); } return new AuthenticationTicket(principal, Properties.Clone(), AuthenticationScheme); } } }
using System; using System.Collections.Generic; using System.Globalization; using System.Text.Json.Serialization; namespace Microsoft.AspNetCore.Authentication { /// <summary> /// Dictionary used to store state values about the authentication session. /// </summary> public class AuthenticationProperties { internal const string IssuedUtcKey = ".issued"; internal const string ExpiresUtcKey = ".expires"; internal const string IsPersistentKey = ".persistent"; internal const string RedirectUriKey = ".redirect"; internal const string RefreshKey = ".refresh"; internal const string UtcDateTimeFormat = "r"; /// <summary> /// Initializes a new instance of the <see cref="AuthenticationProperties"/> class. /// </summary> public AuthenticationProperties() : this(items: null, parameters: null) { } /// <summary> /// Initializes a new instance of the <see cref="AuthenticationProperties"/> class. /// </summary> /// <param name="items">State values dictionary to use.</param> [JsonConstructor] public AuthenticationProperties(IDictionary<string, string?> items) : this(items, parameters: null) { } /// <summary> /// Initializes a new instance of the <see cref="AuthenticationProperties"/> class. /// </summary> /// <param name="items">State values dictionary to use.</param> /// <param name="parameters">Parameters dictionary to use.</param> public AuthenticationProperties(IDictionary<string, string?>? items, IDictionary<string, object?>? parameters) { Items = items ?? new Dictionary<string, string?>(StringComparer.Ordinal); Parameters = parameters ?? new Dictionary<string, object?>(StringComparer.Ordinal); } /// <summary> /// Return a copy. /// </summary> /// <returns>A copy.</returns> public AuthenticationProperties Clone() => new AuthenticationProperties( new Dictionary<string, string?>(Items, StringComparer.Ordinal), new Dictionary<string, object?>(Parameters, StringComparer.Ordinal)); /// <summary> /// State values about the authentication session. /// </summary> public IDictionary<string, string?> Items { get; } /// <summary> /// Collection of parameters that are passed to the authentication handler. These are not intended for /// serialization or persistence, only for flowing data between call sites. /// </summary> [JsonIgnore] public IDictionary<string, object?> Parameters { get; } /// <summary> /// Gets or sets whether the authentication session is persisted across multiple requests. /// </summary> [JsonIgnore] public bool IsPersistent { get => GetString(IsPersistentKey) != null; set => SetString(IsPersistentKey, value ? string.Empty : null); } /// <summary> /// Gets or sets the full path or absolute URI to be used as an http redirect response value. /// </summary> [JsonIgnore] public string? RedirectUri { get => GetString(RedirectUriKey); set => SetString(RedirectUriKey, value); } /// <summary> /// Gets or sets the time at which the authentication ticket was issued. /// </summary> [JsonIgnore] public DateTimeOffset? IssuedUtc { get => GetDateTimeOffset(IssuedUtcKey); set => SetDateTimeOffset(IssuedUtcKey, value); } /// <summary> /// Gets or sets the time at which the authentication ticket expires. /// </summary> [JsonIgnore] public DateTimeOffset? ExpiresUtc { get => GetDateTimeOffset(ExpiresUtcKey); set => SetDateTimeOffset(ExpiresUtcKey, value); } /// <summary> /// Gets or sets if refreshing the authentication session should be allowed. /// </summary> [JsonIgnore] public bool? AllowRefresh { get => GetBool(RefreshKey); set => SetBool(RefreshKey, value); } /// <summary> /// Get a string value from the <see cref="Items"/> collection. /// </summary> /// <param name="key">Property key.</param> /// <returns>Retrieved value or <c>null</c> if the property is not set.</returns> public string? GetString(string key) { return Items.TryGetValue(key, out var value) ? value : null; } /// <summary> /// Set or remove a string value from the <see cref="Items"/> collection. /// </summary> /// <param name="key">Property key.</param> /// <param name="value">Value to set or <see langword="null" /> to remove the property.</param> public void SetString(string key, string? value) { if (value != null) { Items[key] = value; } else { Items.Remove(key); } } /// <summary> /// Get a parameter from the <see cref="Parameters"/> collection. /// </summary> /// <typeparam name="T">Parameter type.</typeparam> /// <param name="key">Parameter key.</param> /// <returns>Retrieved value or the default value if the property is not set.</returns> public T? GetParameter<T>(string key) => Parameters.TryGetValue(key, out var obj) && obj is T value ? value : default; /// <summary> /// Set a parameter value in the <see cref="Parameters"/> collection. /// </summary> /// <typeparam name="T">Parameter type.</typeparam> /// <param name="key">Parameter key.</param> /// <param name="value">Value to set.</param> public void SetParameter<T>(string key, T value) => Parameters[key] = value; /// <summary> /// Get a nullable <see cref="bool"/> from the <see cref="Items"/> collection. /// </summary> /// <param name="key">Property key.</param> /// <returns>Retrieved value or <see langword="null" /> if the property is not set.</returns> protected bool? GetBool(string key) { if (Items.TryGetValue(key, out var value) && bool.TryParse(value, out var boolValue)) { return boolValue; } return null; } /// <summary> /// Set or remove a <see cref="bool"/> value in the <see cref="Items"/> collection. /// </summary> /// <param name="key">Property key.</param> /// <param name="value">Value to set or <see langword="null" /> to remove the property.</param> protected void SetBool(string key, bool? value) { if (value.HasValue) { Items[key] = value.GetValueOrDefault().ToString(); } else { Items.Remove(key); } } /// <summary> /// Get a nullable <see cref="DateTimeOffset"/> value from the <see cref="Items"/> collection. /// </summary> /// <param name="key">Property key.</param> /// <returns>Retrieved value or <see langword="null" /> if the property is not set.</returns> protected DateTimeOffset? GetDateTimeOffset(string key) { if (Items.TryGetValue(key, out var value) && DateTimeOffset.TryParseExact(value, UtcDateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var dateTimeOffset)) { return dateTimeOffset; } return null; } /// <summary> /// Sets or removes a <see cref="DateTimeOffset" /> value in the <see cref="Items"/> collection. /// </summary> /// <param name="key">Property key.</param> /// <param name="value">Value to set or <see langword="null" /> to remove the property.</param> protected void SetDateTimeOffset(string key, DateTimeOffset? value) { if (value.HasValue) { Items[key] = value.GetValueOrDefault().ToString(UtcDateTimeFormat, CultureInfo.InvariantCulture); } else { Items.Remove(key); } } } }