Merge Barry's DocComments

(sorry barry, wasn't too hard to merge)
This commit is contained in:
Hao Kung 2015-06-08 11:09:25 -07:00
parent 6d206250b3
commit 715790c213
56 changed files with 2300 additions and 1245 deletions

View File

@ -13,7 +13,7 @@ namespace Microsoft.AspNet.Builder
public static class BuilderExtensions
{
/// <summary>
/// Enables the ASP.NET identity for the current application.
/// Enables ASP.NET identity for the current application.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/> instance this method extends.</param>
/// <returns>The <see cref="IApplicationBuilder"/> instance this method extends.</returns>

View File

@ -6,12 +6,12 @@ using System.Security.Claims;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Options for ClaimType names.
/// Options used to configure the claim types used for well known claims.
/// </summary>
public class ClaimsIdentityOptions
{
/// <summary>
/// Gets the ClaimType used for a Role claim.
/// Gets or sets the ClaimType used for a Role claim.
/// </summary>
/// <remarks>
/// This defaults to <see cref="ClaimTypes.Role"/>.
@ -19,7 +19,7 @@ namespace Microsoft.AspNet.Identity
public string RoleClaimType { get; set; } = ClaimTypes.Role;
/// <summary>
/// Gets the ClaimType used for the user name claim.
/// Gets or sets the ClaimType used for the user name claim.
/// </summary>
/// <remarks>
/// This defaults to <see cref="ClaimTypes.Name"/>.
@ -27,7 +27,7 @@ namespace Microsoft.AspNet.Identity
public string UserNameClaimType { get; set; } = ClaimTypes.Name;
/// <summary>
/// Gets the ClaimType used for the user identifier claim.
/// Gets or sets the ClaimType used for the user identifier claim.
/// </summary>
/// <remarks>
/// This defaults to <see cref="ClaimTypes.NameIdentifier"/>.
@ -35,7 +35,7 @@ namespace Microsoft.AspNet.Identity
public string UserIdClaimType { get; set; } = ClaimTypes.NameIdentifier;
/// <summary>
/// Gets the ClaimType used for the security stamp claim..
/// Gets or sets the ClaimType used for the security stamp claim..
/// </summary>
/// <remarks>
/// This defaults to "AspNet.Identity.SecurityStamp".

View File

@ -58,13 +58,12 @@ namespace Microsoft.AspNet.Identity
public string Name { get { return Options.Name; } }
/// <summary>
/// Generates a protected token for the specified <paramref name="User"/>.
/// Generates a protected token for the specified <paramref name="user"/> as an asynchronous operation.
/// </summary>
/// <param name="purpose">The purpose the token will be used for.</param>
/// <param name="manager">The <see cref="UserManager{TUser}"/> to retrieve user properties from.</param>
/// <param name="user">The <see cref="TUser"/> the token will be generated from.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe while waiting for the tasks to complete.</param>
/// <returns>A <see cref="Task{TResult}"/> that contains the protected token.</returns>
/// <returns>A <see cref="Task{TResult}"/> representing the generated token.</returns>
public virtual async Task<string> GenerateAsync(string purpose, UserManager<TUser> manager, TUser user)
{
if (user == null)
@ -90,13 +89,16 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Validates the protected <paramref name="token"/> for the specified <paramref name="user"/> and <paramref name="purpose"/>.
/// Validates the protected <paramref name="token"/> for the specified <paramref name="user"/> and <paramref name="purpose"/> as an asynchronous operation.
/// </summary>
/// <param name="purpose">The purpose the token was be used for.</param>
/// <param name="token">The token to validate.</param>
/// <param name="manager">The <see cref="UserManager{TUser}"/> to retrieve user properties from.</param>
/// <param name="user">The <see cref="TUser"/> the token was generated for.</param>
/// <returns>A <see cref="Task{TResult}"/> that is true if the token is valid, otherwise false.</returns>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the result of the asynchronous validation,
/// containing true if the token is valid, otherwise false.
/// </returns>
public virtual async Task<bool> ValidateAsync(string purpose, string token, UserManager<TUser> manager, TUser user)
{
try
@ -146,11 +148,14 @@ namespace Microsoft.AspNet.Identity
/// <summary>
/// Returns a <see cref="boolean"/> indicating whether a token generated by this instance
/// can be used as a Two Factor Authentication token.
/// can be used as a Two Factor Authentication token as an asynchronous operation.
/// </summary>
/// <param name="manager">The <see cref="UserManager{TUser}"/> to retrieve user properties from.</param>
/// <param name="user">The <see cref="TUser"/> the token was generated for.</param>
/// <returns>True if a token generated by this instance can be used as a Two Factor Authentication token, otherwise false.</returns>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the result of the asynchronous query,
/// containing true if a token generated by this instance can be used as a Two Factor Authentication token, otherwise false.
/// </returns>
/// <remarks>This method will always return false for instances of <see cref="DataProtectorTokenProvider{TUser}"/>.</remarks>
public virtual Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<TUser> manager, TUser user)
{
@ -158,12 +163,12 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Creates a notification task for A <paramref name="user"/> based on the supplied <paramref name="token"/>.
/// Creates a notification for the specified <paramref name="user"/> based on the supplied <paramref name="token"/> as an asynchronous operation.
/// </summary>
/// <param name="token">The token to generate notifications for..</param>
/// <param name="token">The token to generate notifications for.</param>
/// <param name="manager">The <see cref="UserManager{TUser}"/> to retrieve user properties from.</param>
/// <param name="user">The <see cref="TUser"/> the token was generated for.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the started task.</returns>
/// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous notification.</returns>
public virtual Task NotifyAsync(string token, UserManager<TUser> manager, TUser user)
{
return Task.FromResult(0);

View File

@ -4,18 +4,32 @@ using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Options for the <see cref="EmailTokenProvider{TUser}"/> class.
/// </summary>
public class EmailTokenProviderOptions
{
/// <summary>
/// Gets or sets the unique name used for an instance of <see cref="EmailTokenProvider{TUser}"/>.
/// </summary>
/// <value>
/// The unique name used for an instance of <see cref="EmailTokenProvider{TUser}"/>.
/// </value>
public string Name { get; set; } = "Email";
}
/// <summary>
/// TokenProvider that generates tokens from the user's security stamp and notifies a user via their email
/// TokenProvider that generates tokens from the user's security stamp and notifies a user via email.
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TUser">The type used to represent a user.</typeparam>
public class EmailTokenProvider<TUser> : TotpSecurityStampBasedTokenProvider<TUser>
where TUser : class
{
/// <summary>
/// Initializes a new instance of the <see cref="EmailTokenProvider{TUser}"/> class.
/// </summary>
/// <param name="options">The configured <see cref="DataProtectionTokenProviderOptions"/>.</param>
/// <param name="name">The unique name for this instance of <see cref="EmailTokenProvider{TUser}"/>.</param>
public EmailTokenProvider(IOptions<EmailTokenProviderOptions> options, string name = "")
{
if (options == null)
@ -25,16 +39,28 @@ namespace Microsoft.AspNet.Identity
Options = options.GetNamedOptions(name);
}
/// <summary>
/// Gets the options for this instance of <see cref="EmailTokenProvider{TUser}"/>.
/// </summary>
/// <value>
/// The options for this instance of <see cref="EmailTokenProvider{TUser}"/>.
/// </value>
public EmailTokenProviderOptions Options { get; private set; }
/// <summary>
/// Gets the unique name for this instance of <see cref="EmailTokenProvider{TUser}"/>.
/// </summary>
/// <value>
/// The unique name for this instance of <see cref="EmailTokenProvider{TUser}"/>.
/// </value>
public override string Name { get { return Options.Name; } }
/// <summary>
/// True if the user has an email set
/// Checks if a two factor authentication token can be generated for the specified <paramref name="user"/>.
/// </summary>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <returns></returns>
/// <param name="manager">The <see cref="UserManager{TUser}"/> to retrieve the <paramref name="user"/> from.</param>
/// <param name="user">The <see cref="TUser"/> to check for the possibility of generating a two factor authentication token.</param>
/// <returns>True if the user has an email address set, otherwise false.</returns>
public override async Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<TUser> manager, TUser user)
{
var email = await manager.GetEmailAsync(user);
@ -42,12 +68,12 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Returns the email of the user for entropy in the token
/// Returns the a value for the user used as entropy in the generated token.
/// </summary>
/// <param name="purpose"></param>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <returns></returns>
/// <param name="purpose">The purpose of the two factor authentication token.</param>
/// <param name="manager">The <see cref="UserManager{TUser}"/> to retrieve the <paramref name="user"/> from.</param>
/// <param name="user">The <see cref="TUser"/> to check for the possibility of generating a two factor authentication token.</param>
/// <returns>A string suitable for use as entropy in token generation.</returns>
public override async Task<string> GetUserModifierAsync(string purpose, UserManager<TUser> manager,
TUser user)
{

View File

@ -5,14 +5,28 @@ using System.Security.Claims;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Represents login information, source and externally source principal for a user record
/// </summary>
public class ExternalLoginInfo : UserLoginInfo
{
/// <summary>
/// Creates a new instance of <see cref="ExternalLoginInfo"/>
/// </summary>
/// <param name="externalPrincipal">The <see cref="ClaimsPrincipal"/> to associate with this login.</param>
/// <param name="loginProvider">The provider associated with this login information.</param>
/// <param name="providerKey">The unique identifier for this user provided by the login provider.</param>
/// <param name="displayName">The display name for this user provided by the login provider.</param>
public ExternalLoginInfo(ClaimsPrincipal externalPrincipal, string loginProvider, string providerKey,
string displayName) : base(loginProvider, providerKey, displayName)
{
ExternalPrincipal = externalPrincipal;
}
/// <summary>
/// Gets or sets the <see cref="ClaimsPrincipal"/> associated with this login.
/// </summary>
/// <value>The <see cref="ClaimsPrincipal"/> associated with this login.</value>
public ClaimsPrincipal ExternalPrincipal { get; set; }
}
}

View File

@ -4,15 +4,15 @@
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Used to normalize keys for consistent lookups
/// Provides an abstraction for normalizing keys for lookup purposes.
/// </summary>
public interface ILookupNormalizer
{
/// <summary>
/// Returns the normalized key
/// Returns a normalized representation of the specified <paramref name="key"/>.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
/// <param name="key">The key to normalize.</param>
/// <returns>A normalized representation of the specified <paramref name="key"/>.</returns>
string Normalize(string key);
}
}

View File

@ -4,25 +4,27 @@
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Abstraction for password hashing methods
/// Provides an abstraction for hashing passwords.
/// </summary>
/// <typeparam name="TUser">The type used to represent a user.</typeparam>
public interface IPasswordHasher<TUser> where TUser : class
{
/// <summary>
/// Hash a password
/// Returns a hashed representation of the supplied <paramref name="password"/> for the specified <paramref name="user"/>.
/// </summary>
/// <param name="user"></param>
/// <param name="password"></param>
/// <returns></returns>
/// <param name="user">The user whose password is to be hashed.</param>
/// <param name="password">The password to hash.</param>
/// <returns>A hashed representation of the supplied <paramref name="password"/> for the specified <paramref name="user"/>.</returns>
string HashPassword(TUser user, string password);
/// <summary>
/// Verify that a password matches the hashed password
/// Returns a <see cref="PasswordVerificationResult"/> indicating the result of a password hash comparison.
/// </summary>
/// <param name="user"></param>
/// <param name="hashedPassword"></param>
/// <param name="providedPassword"></param>
/// <returns></returns>
/// <param name="user">The user whose password should be verified.</param>
/// <param name="hashedPassword">The hash value for a user's stored password.</param>
/// <param name="providedPassword">The password supplied for comparison.</param>
/// <returns>A <see cref="PasswordVerificationResult"/> indicating the result of a password hash comparison.</returns>
/// <remarks>Implementations of this method should be time consistent.</remarks>
PasswordVerificationResult VerifyHashedPassword(TUser user, string hashedPassword, string providedPassword);
}
}

View File

@ -7,14 +7,18 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Used to validate passwords
/// Provides an abstraction for validating passwords.
/// </summary>
/// <typeparam name="TUser">The type that represents a user.</typeparam>
public interface IPasswordValidator<TUser> where TUser : class
{
/// <summary>
/// Validate the password for the user
/// Validates a password as an asynchronous operation.
/// </summary>
/// <returns></returns>
/// <param name="manager">The <see cref="UserManager{TUser}"/> to retrieve the <paramref name="user"/> properties from.</param>
/// <param name="user">The user whose password should be validated.</param>
/// <param name="password">The password supplied for validation</param>
/// <returns>The task object representing the asynchronous operation.</returns>
Task<IdentityResult> ValidateAsync(UserManager<TUser> manager, TUser user, string password);
}
}

View File

@ -6,14 +6,15 @@ using System.Linq;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Interface that exposes an IQueryable roles
/// Provides an abstraction for querying roles in a Role store.
/// </summary>
/// <typeparam name="TRole"></typeparam>
/// <typeparam name="TRole">The type encapsulating a role.</typeparam>
public interface IQueryableRoleStore<TRole> : IRoleStore<TRole> where TRole : class
{
/// <summary>
/// IQueryable roles
/// Returns an <see cref="IQueryable{T}"/> collection of roles.
/// </summary>
/// <value>An <see cref="IQueryable{T}"/> collection of roles.</value>
IQueryable<TRole> Roles { get; }
}
}

View File

@ -6,14 +6,15 @@ using System.Linq;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Interface that exposes an IQueryable users
/// Provides an abstraction for querying roles in a User store.
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TUser">The type encapsulating a user.</typeparam>
public interface IQueryableUserStore<TUser> : IUserStore<TUser> where TUser : class
{
/// <summary>
/// IQueryable users
/// Returns an <see cref="IQueryable{T}"/> collection of users.
/// </summary>
/// <value>An <see cref="IQueryable{T}"/> collection of users.</value>
IQueryable<TUser> Users { get; }
}
}

View File

@ -9,37 +9,37 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Stores role specific claims
/// Provides an abstraction for a store of role specific claims.
/// </summary>
/// <typeparam name="TRole"></typeparam>
/// <typeparam name="TRole">The type encapsulating a role.</typeparam>
public interface IRoleClaimStore<TRole> : IRoleStore<TRole> where TRole : class
{
/// <summary>
/// Returns the claims for the role
/// Gets a list of <see cref="Claim"/>s to be belonging to the specified <paramref name="role"/> as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IList<Claim>> GetClaimsAsync(TRole role,
CancellationToken cancellationToken = default(CancellationToken));
/// <param name="role">The role whose claims to retrieve.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the result of the asynchronous query, a list of <see cref="Claim"/>s.
/// </returns>
Task<IList<Claim>> GetClaimsAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Add a new role claim
/// Add a new claim to a role as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <param name="claim"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="role">The role to add a claim to.</param>
/// <param name="claim">The <see cref="Claim"/> to add.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The task object representing the asynchronous operation.</returns>
Task AddClaimAsync(TRole role, Claim claim, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Remove a role claim
/// Remove a claim from a role as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <param name="claim"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task RemoveClaimAsync(TRole role, Claim claim,
CancellationToken cancellationToken = default(CancellationToken));
/// <param name="role">The role to remove the claim from.</param>
/// <param name="claim">The <see cref="Claim"/> to remove.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The task object representing the asynchronous operation.</returns>
Task RemoveClaimAsync(TRole role, Claim claim, CancellationToken cancellationToken = default(CancellationToken));
}
}

View File

@ -8,92 +8,92 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Interface that exposes basic role management
/// Provides an abstraction for a storage and management of roles.
/// </summary>
/// <typeparam name="TRole"></typeparam>
/// <typeparam name="TRole">The type that represents a role.</typeparam>
public interface IRoleStore<TRole> : IDisposable where TRole : class
{
/// <summary>
/// Insert a new role
/// Creates a new role in a store as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="role">The role to create in the store.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the <see cref="IdentityResult"/> of the asynchronous query.</returns>
Task<IdentityResult> CreateAsync(TRole role, CancellationToken cancellationToken);
/// <summary>
/// Update a role
/// Updates a role in a store as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="role">The role to update in the store.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the <see cref="IdentityResult"/> of the asynchronous query.</returns>
Task<IdentityResult> UpdateAsync(TRole role, CancellationToken cancellationToken);
/// <summary>
/// DeleteAsync a role
/// Deletes a role from the store as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="role">The role to delete from the store.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the <see cref="IdentityResult"/> of the asynchronous query.</returns>
Task<IdentityResult> DeleteAsync(TRole role, CancellationToken cancellationToken);
/// <summary>
/// Returns a role's id
/// Gets the ID for a role from the store as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="role">The role whose ID should be returned.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that contains the ID of the role.</returns>
Task<string> GetRoleIdAsync(TRole role, CancellationToken cancellationToken);
/// <summary>
/// Returns a role's name
/// Gets the name of a role from the store as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="role">The role whose name should be returned.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that contains the name of the role.</returns>
Task<string> GetRoleNameAsync(TRole role, CancellationToken cancellationToken);
/// <summary>
/// Set a role's name
/// Sets the name of a role in the store as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <param name="roleName"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="role">The role whose name should be set.</param>
/// <param name="roleName">The name of the role.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
Task SetRoleNameAsync(TRole role, string roleName, CancellationToken cancellationToken);
/// <summary>
/// Get a role's normalized name
/// Get a role's normalized name as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="role">The role whose normalized name should be retrieved.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that contains the name of the role.</returns>
Task<string> GetNormalizedRoleNameAsync(TRole role, CancellationToken cancellationToken);
/// <summary>
/// Set a role's normalized name
/// Set a role's normalized name as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <param name="normalizedName"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="role">The role whose normalized name should be set.</param>
/// <param name="normalizedName">The normalized name to set</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
Task SetNormalizedRoleNameAsync(TRole role, string normalizedName, CancellationToken cancellationToken);
/// <summary>
/// Finds a role by id
/// Finds the role who has the specified ID as an asynchronous operation.
/// </summary>
/// <param name="roleId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="roleId">The role ID to look for.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that result of the look up.</returns>
Task<TRole> FindByIdAsync(string roleId, CancellationToken cancellationToken);
/// <summary>
/// Find a role by normalized name
/// Finds the role who has the specified normalized name as an asynchronous operation.
/// </summary>
/// <param name="normalizedRoleName"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="normalizedRoleName">The normalized role name to look for.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that result of the look up.</returns>
Task<TRole> FindByNameAsync(string normalizedRoleName, CancellationToken cancellationToken);
}
}

View File

@ -1,23 +1,22 @@
// 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.Threading;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Used to validate a role
/// Provides an abstraction for a validating a role.
/// </summary>
/// <typeparam name="TRole"></typeparam>
/// <typeparam name="TRole">The type encapsulating a role.</typeparam>
public interface IRoleValidator<TRole> where TRole : class
{
/// <summary>
/// ValidateAsync the user
/// Validates a role as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <param name="manager"></param>
/// <returns></returns>
/// <param name="manager">The <see cref="RoleManager{TRole}"/> managing the role store.</param>
/// <param name="role">The role to validate.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the <see cref="IdentityResult"/> of the asynchronous validation.</returns>
Task<IdentityResult> ValidateAsync(RoleManager<TRole> manager, TRole role);
}
}

View File

@ -6,8 +6,19 @@ using Microsoft.AspNet.Authentication.Cookies;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Provides an abstraction for a validating a security stamp of an incoming identity, and regenerating or rejecting the
/// identity based on the validation result.
/// </summary>
public interface ISecurityStampValidator
{
/// <summary>
/// Validates a security stamp of an identity as an asynchronous operation, and rebuilds the identity if the validation succeeds, otherwise rejects
/// the identity.
/// </summary>
/// <param name="context">The context containing the <see cref="ClaimsPrincipal"/>and <see cref="AuthenticationProperties"/> to validate.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous validation operation.</returns>
Task ValidateAsync(CookieValidatePrincipalContext context);
}
}
}

View File

@ -9,53 +9,58 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Stores user specific claims
/// Provides an abstraction for a store of claims for a user.
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TUser">The type encapsulating a user.</typeparam>
public interface IUserClaimStore<TUser> : IUserStore<TUser> where TUser : class
{
/// <summary>
/// Returns the claims for the user
/// Gets a list of <see cref="Claim"/>s to be belonging to the specified <paramref name="user"/> as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The role whose claims to retrieve.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the result of the asynchronous query, a list of <see cref="Claim"/>s.
/// </returns>
Task<IList<Claim>> GetClaimsAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// Add a new user claim
/// Add claims to a user as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="claims"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user to add the claim to.</param>
/// <param name="claims">The collection of <see cref="Claim"/>s to add.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The task object representing the asynchronous operation.</returns>
Task AddClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken);
/// <summary>
/// Updates the give claim information with the given new claim information
/// Replaces the given <paramref name="claim"/> on the specified <paramref name="user"/> with the <paramref name="newClaim"/>
/// </summary>
/// <param name="user"></param>
/// <param name="claim"></param>
/// <param name="newClaim"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user to replace the claim on.</param>
/// <param name="claim">The claim to replace.</param>
/// <param name="newClaim">The new claim to replace the existing <paramref name="claim"/> with.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The task object representing the asynchronous operation.</returns>
Task ReplaceClaimAsync(TUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken);
/// <summary>
/// Remove a user claim
/// Removes the specified <paramref name="claims"/> from the given <paramref name="user"/>.
/// </summary>
/// <param name="user"></param>
/// <param name="claims"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user to remove the specified <paramref name="claims"/> from.</param>
/// <param name="claims">A collection of <see cref="Claim"/>s to remove.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The task object representing the asynchronous operation.</returns>
Task RemoveClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken);
/// <summary>
/// Get users having a specific claim
/// Returns a list of users who contain the specified <see cref="Claim"/>.
/// </summary>
/// <param name="claim">Claim to look up</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="claim">The claim to look for.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the result of the asynchronous query, a list of <typeparamref name="TUser"/> who
/// contain the specified claim.
/// </returns>
Task<IList<TUser>> GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken);
}
}

View File

@ -7,18 +7,18 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Interface for creating a ClaimsPrincipal from an user
/// Provides an abstraction for a factory to create a <see cref="ClaimsPrincipal"/> from a user.
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TRole">The type encapsulating a user.</typeparam>
public interface IUserClaimsPrincipalFactory<TUser>
where TUser : class
{
/// <summary>
/// Create a ClaimsPrincipal from an user
/// Creates a <see cref="ClaimsPrincipal"/> from an user asynchronously.
/// </summary>
/// <param name="user"></param>
/// <param name="authenticationType"></param>
/// <returns></returns>
/// <param name="user">The user to create a <see cref="ClaimsPrincipal"/> from.</param>
/// <param name="authenticationType">The name of the authentication method the <paramref name="user"/> was sourced from.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous creation operation, containing the created <see cref="ClaimsPrincipal"/>.</returns>
Task<ClaimsPrincipal> CreateAsync(TUser user);
}
}

View File

@ -7,68 +7,76 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Stores a user's email
/// Provides an abstraction for the storage and management of user email addresses.
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TUser">The type encapsulating a user.</typeparam>
public interface IUserEmailStore<TUser> : IUserStore<TUser> where TUser : class
{
/// <summary>
/// Set the user email
/// Sets the <paramref name="email"/> address for a <paramref name="user"/>, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="email"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose email should be set.</param>
/// <param name="email">The email to set.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The task object representing the asynchronous operation.</returns>
Task SetEmailAsync(TUser user, string email, CancellationToken cancellationToken);
/// <summary>
/// Get the user email
/// Gets the email address for the specified <paramref name="user"/>, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose email should be returned.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The task object containing the results of the asynchronous operation, the email address for the specified <paramref name="user"/>.</returns>
Task<string> GetEmailAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// Returns true if the user email is confirmed
/// Gets a flag indicating whether the email address for the specified <paramref name="user"/> has been verified, true if the email address is verified otherwise
/// false, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose email confirmation status should be returned.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>
/// The task object containing the results of the asynchronous operation, a flag indicating whether the email address for the specified <paramref name="user"/>
/// has been confirmed or not.
/// </returns>
Task<bool> GetEmailConfirmedAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// Sets whether the user email is confirmed
/// Sets the flag indicating whether the specified <paramref name="user"/>'s email address has been confirmed or not, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="confirmed"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose email confirmation status should be set.</param>
/// <param name="confirmed">A flag indicating if the email address has been confirmed, true if the address is confirmed otherwise false.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The task object representing the asynchronous operation.</returns>
Task SetEmailConfirmedAsync(TUser user, bool confirmed, CancellationToken cancellationToken);
/// <summary>
/// Returns the user associated with this email
/// Gets the user, if any, associated with the specified, normalized email address, as an asynchronous operation.
/// </summary>
/// <param name="normalizedEmail"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="normalizedEmail">The normalized email address to return the user for.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>
/// The task object containing the results of the asynchronous lookup operation, the user if any associated with the specified normalized email address.
/// </returns>
Task<TUser> FindByEmailAsync(string normalizedEmail, CancellationToken cancellationToken);
/// <summary>
/// Returns the normalized email
/// Returns the normalized email for the specified <paramref name="user"/>, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose email address to retrieve.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>
/// The task object containing the results of the asynchronous lookup operation, the normalized email address if any associated with the specified user.
/// </returns>
Task<string> GetNormalizedEmailAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// Set the normalized email
/// Sets the normalized email for the specified <paramref name="user"/>, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="normalizedEmail"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose email address to set.</param>
/// <param name="normalizedEmail">The normalized email to set for the specified <paramref name="user"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The task object representing the asynchronous operation.</returns>
Task SetNormalizedEmailAsync(TUser user, string normalizedEmail, CancellationToken cancellationToken);
}
}

View File

@ -8,69 +8,75 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Stores information which can be used to implement account lockout, including access failures and lockout status
/// Provides an abstraction for a storing information which can be used to implement account lockout,
/// including access failures and lockout status
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TUser">The type that represents a user.</typeparam>
public interface IUserLockoutStore<TUser> : IUserStore<TUser> where TUser : class
{
/// <summary>
/// Returns the DateTimeOffset that represents the end of a user's lockout, any time in the past should be
/// considered not locked out.
/// Gets the last <see cref="DateTimeOffset"/> a user's last lockout expired, if any, as an asynchronous operation.
/// Any time in the past should be indicates a user is not locked out.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose lockout date should be retrieved.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that represents the result of the asynchronous query, a <see cref="DateTimeOffset"/> containing the last time
/// a user's lockout expired, if any.
/// </returns>
Task<DateTimeOffset?> GetLockoutEndDateAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// Locks a user out until the specified end date (set to a past date, to unlock a user)
/// Locks out a user until the specified end date has passed, as an asynchronous operation. Setting a end date in the past immediately unlocks a user.
/// </summary>
/// <param name="user"></param>
/// <param name="lockoutEnd"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose lockout date should be set.</param>
/// <param name="lockoutEnd">The <see cref="DateTimeOffset"/> after which the <paramref name="user"/>'s lockout should end.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
Task SetLockoutEndDateAsync(TUser user, DateTimeOffset? lockoutEnd, CancellationToken cancellationToken);
/// <summary>
/// Used to record when an attempt to access the user has failed
/// Records that a failed access has occurred, incrementing the failed access count, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose cancellation count should be incremented.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the incremented failed access count.</returns>
Task<int> IncrementAccessFailedCountAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// Used to reset the account access count, typically after the account is successfully accessed
/// Resets a user's failed access count, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose failed access count should be reset.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
/// <remarks>This is typically called after the account is successfully accessed.</remarks>
Task ResetAccessFailedCountAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// Returns the current number of failed access attempts. This number usually will be reset whenever the
/// password is verified or the account is locked out.
/// Retrieves the current failed access count for the specified <paramref name="user"/>, as an asynchronous operation..
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose failed access count should be retrieved.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the failed access count.</returns>
Task<int> GetAccessFailedCountAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// Returns whether the user can be locked out.
/// Retrieves a flag indicating whether user lockout can enabled for the specified user, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose ability to be locked out should be returned.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, true if a user can be locked out, otherwise false.
/// </returns>
Task<bool> GetLockoutEnabledAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// Sets whether the user can be locked out.
/// Set the flag indicating if the specified <paramref name="user"/> can be locked out, as an asynchronous operation..
/// </summary>
/// <param name="user"></param>
/// <param name="enabled"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose ability to be locked out should be set.</param>
/// <param name="enabled">A flag indicating if lock out can be enabled for the specified <paramref name="user"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
Task SetLockoutEnabledAsync(TUser user, bool enabled, CancellationToken cancellationToken);
}
}

View File

@ -8,45 +8,54 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Interface that maps users to login providers, i.e. Google, Facebook, Twitter, Microsoft
/// Provides an abstraction for storing information that maps external login information provided
/// by Microsoft Account, Facebook etc. to a user account.
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TUser">The type that represents a user.</typeparam>
public interface IUserLoginStore<TUser> : IUserStore<TUser> where TUser : class
{
/// <summary>
/// Adds a user login with the specified provider and key
/// Adds an external <see cref="UserLoginInfo"/> to the specified <paramref name="user"/>, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="login"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user to add the login to.</param>
/// <param name="login">The external <see cref="UserLoginInfo"/> to add to the specified <paramref name="user"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
Task AddLoginAsync(TUser user, UserLoginInfo login, CancellationToken cancellationToken);
/// <summary>
/// Removes the user login with the specified combination if it exists, returns true if found and removed
/// Attempts to remove the provided login information from the specified <paramref name="user"/>, as an asynchronous operation.
/// and returns a flag indicating whether the removal succeed or not.
/// </summary>
/// <param name="user"></param>
/// <param name="loginProvider"></param>
/// <param name="providerKey"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user to remove the login information from.</param>
/// <param name="loginProvider">The login provide whose information should be removed.</param>
/// <param name="providerKey">The key given by the external login provider for the specified user.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>
/// The <see cref="Task"/> that contains a flag the result of the asynchronous removing operation. The flag will be true if
/// the login information was existed and removed, otherwise false.
/// </returns>
Task RemoveLoginAsync(TUser user, string loginProvider, string providerKey, CancellationToken cancellationToken);
/// <summary>
/// Returns the linked accounts for this user
/// Retrieves the associated logins for the specified <param ref="user"/>, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose associated logins to retrieve.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>
/// The <see cref="Task"/> for the asynchronous operation, containing a list of <see cref="UserLoginInfo"/> for the specified <paramref name="user"/>, if any.
/// </returns>
Task<IList<UserLoginInfo>> GetLoginsAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// Returns the user associated with this login
/// Retrieves the user associated with the specified login provider and login provider key, as an asynchronous operation..
/// </summary>
/// <param name="loginProvider"></param>
/// <param name="providerKey"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="loginProvider">The login provider who provided the <paramref name="providerKey"/>.</param>
/// <param name="providerKey">The key provided by the <paramref name="loginProvider"/> to identify a user.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>
/// The <see cref="Task"/> for the asynchronous operation, containing the user, if any which matched the specified login provider and key.
/// </returns>
Task<TUser> FindByLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken);
}
}

View File

@ -7,34 +7,37 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Stores a user's password hash
/// Provides an abstraction for a store containing users' password hashes..
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TUser">The type encapsulating a user.</typeparam>
public interface IUserPasswordStore<TUser> : IUserStore<TUser> where TUser : class
{
/// <summary>
/// Set the user password hash
/// Sets the password hash for the specified <paramref name="user"/>, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="passwordHash"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose password hash to set.</param>
/// <param name="passwordHash">The password hash to set.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
Task SetPasswordHashAsync(TUser user, string passwordHash, CancellationToken cancellationToken);
/// <summary>
/// Get the user password hash
/// Gets the password hash for the specified <paramref name="user"/>, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose password hash to retrieve.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, returning the password hash for the specified <paramref name="user"/>.</returns>
Task<string> GetPasswordHashAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// Returns true if a user has a password set
/// Gets a flag indicating whether the specified <paramref name="user"/> has a password, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user to return a flag for, indicating whether they have a password or not.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, returning true if the specified <paramref name="user"/> has a password
/// otherwise false.
/// </returns>
Task<bool> HasPasswordAsync(TUser user, CancellationToken cancellationToken);
}
}

View File

@ -7,43 +7,46 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Stores a user's phoneNumber
/// Provides an abstraction for a store containing users' telephone numbers.
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TUser">The type encapsulating a user.</typeparam>
public interface IUserPhoneNumberStore<TUser> : IUserStore<TUser> where TUser : class
{
/// <summary>
/// Set the user PhoneNumber
/// Sets the telephone number for the specified <paramref name="user"/>, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="phoneNumber"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose telephone number should be set.</param>
/// <param name="phoneNumber">The telephone number to set.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
Task SetPhoneNumberAsync(TUser user, string phoneNumber, CancellationToken cancellationToken);
/// <summary>
/// Get the user phoneNumber
/// Gets the telephone number, if any, for the specified <paramref name="user"/>, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose telephone number should be retrieved.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the user's telephone number, if any.</returns>
Task<string> GetPhoneNumberAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// Returns true if the user phone number is confirmed
/// Gets a flag indicating whether the specified <paramref name="user"/>'s telephone number has been confirmed, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user to return a flag for, indicating whether their telephone number is confirmed.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, returning true if the specified <paramref name="user"/> has a confirmed
/// telephone number otherwise false.
/// </returns>
Task<bool> GetPhoneNumberConfirmedAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// Sets whether the user phone number is confirmed
/// Sets a flag indicating if the specified <paramref name="user"/>'s phone number has been confirmed, as an asynchronous operation..
/// </summary>
/// <param name="user"></param>
/// <param name="confirmed"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose telephone number confirmation status should be set.</param>
/// <param name="confirmed">A flag indicating whether the user's telephone number has been confirmed.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
Task SetPhoneNumberConfirmedAsync(TUser user, bool confirmed, CancellationToken cancellationToken);
}
}

View File

@ -8,52 +8,57 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Interface that maps users to their roles
/// Provides an abstraction for a store which maps users to roles.
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TUser">The type encapsulating a user.</typeparam>
public interface IUserRoleStore<TUser> : IUserStore<TUser> where TUser : class
{
/// <summary>
/// Adds a user to role
/// Add a the specified <paramref name="user"/> to the named role, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="roleName"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user to add to the named role.</param>
/// <param name="roleName">The name of the role to add the user to.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
Task AddToRoleAsync(TUser user, string roleName, CancellationToken cancellationToken);
/// <summary>
/// Removes the role for the user
/// Add a the specified <paramref name="user"/> from the named role, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="roleName"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user to remove the named role from.</param>
/// <param name="roleName">The name of the role to remove.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
Task RemoveFromRoleAsync(TUser user, string roleName, CancellationToken cancellationToken);
/// <summary>
/// Returns the roles for this user
/// Gets a list of role names the specified <paramref name="user"/> belongs to, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose role names to retrieve.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing a list of role names.</returns>
Task<IList<string>> GetRolesAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// Returns true if a user is in a role
/// Returns a flag indicating whether the specified <paramref name="user"/> is a member of the give named role, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="roleName"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose role membership should be checked.</param>
/// <param name="roleName">The name of the role to be checked.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing a flag indicating whether the specified <see cref="user"/> is
/// a member of the named role.
/// </returns>
Task<bool> IsInRoleAsync(TUser user, string roleName, CancellationToken cancellationToken);
/// <summary>
/// Returns all users in given role
/// Returns a list of Users who are members of the named role.
/// </summary>
/// <param name="roleName"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="roleName">The name of the role whose membership should be returned.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing a list of users who are in the named role.
/// </returns>
Task<IList<TUser>> GetUsersInRoleAsync(string roleName, CancellationToken cancellationToken);
}
}

View File

@ -7,26 +7,26 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Stores a user's security stamp
/// Provides an abstraction for a store which stores a user's security stamp.
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TUser">The type encapsulating a user.</typeparam>
public interface IUserSecurityStampStore<TUser> : IUserStore<TUser> where TUser : class
{
/// <summary>
/// Set the security stamp for the user
/// Sets the provided security <paramref name="stamp"/> for the specified <paramref name="user"/>, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="stamp"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose security stamp should be set.</param>
/// <param name="stamp">The security stamp to set.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
Task SetSecurityStampAsync(TUser user, string stamp, CancellationToken cancellationToken);
/// <summary>
/// Get the user security stamp
/// Get the security stamp for the specified <paramref name="user" />, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose security stamp should be set.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the security stamp for the specified <paramref name="user"/>.</returns>
Task<string> GetSecurityStampAsync(TUser user, CancellationToken cancellationToken);
}
}

View File

@ -8,93 +8,95 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Interface that exposes basic user management apis
/// Provides an abstraction for a store which manages user accounts.
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TUser">The type encapsulating a user.</typeparam>
public interface IUserStore<TUser> : IDisposable where TUser : class
{
/// <summary>
/// Returns the user id for a user
/// Gets the user identifier for the specified <paramref name="user"/>, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose identifier should be retrieved.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the identifier for the specified <paramref name="user"/>.</returns>
Task<string> GetUserIdAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// Returns the user's name
/// Gets the user name for the specified <paramref name="user"/>, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose name should be retrieved.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the name for the specified <paramref name="user"/>.</returns>
Task<string> GetUserNameAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// Set the user name
/// Sets the given <paramref name="userName" /> for the specified <paramref name="user"/>, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="userName"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task SetUserNameAsync(TUser user, string userName,
CancellationToken cancellationToken);
/// <param name="user">The user whose name should be set.</param>
/// <param name="userName">The user name to set.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
Task SetUserNameAsync(TUser user, string userName, CancellationToken cancellationToken);
/// <summary>
/// Returns the normalized user name
/// Gets the normalized user name for the specified <paramref name="user"/>, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose normalized name should be retrieved.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the normalized user name for the specified <paramref name="user"/>.</returns>
Task<string> GetNormalizedUserNameAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// Set the normalized user name
/// Sets the given normalized name for the specified <paramref name="user"/>, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="normalizedName"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task SetNormalizedUserNameAsync(TUser user, string normalizedName,
CancellationToken cancellationToken);
/// <param name="user">The user whose name should be set.</param>
/// <param name="userName">The normalized name to set.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
Task SetNormalizedUserNameAsync(TUser user, string normalizedName, CancellationToken cancellationToken);
/// <summary>
/// Insert a new user
/// Creates the specified <paramref name="user"/> in the user store, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user to create.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/> of the creation operation.</returns>
Task<IdentityResult> CreateAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// UpdateAsync a user
/// Updates the specified <paramref name="user"/> in the user store, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user to update.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/> of the update operation.</returns>
Task<IdentityResult> UpdateAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// DeleteAsync a user
/// Deletes the specified <paramref name="user"/> from the user store, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user to delete.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/> of the update operation.</returns>
Task<IdentityResult> DeleteAsync(TUser user, CancellationToken cancellationToken);
/// <summary>
/// Finds a user
/// Finds and returns a user, if any, who has the specified <paramref name="userId"/>.
/// </summary>
/// <param name="userId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="userId">The user ID to search for.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the user matching the specified <paramref name="userID"/> if it exists.
/// </returns>
Task<TUser> FindByIdAsync(string userId, CancellationToken cancellationToken);
/// <summary>
/// Returns the user associated with this normalized user name
/// Finds and returns a user, if any, who has the specified normalized user name.
/// </summary>
/// <param name="normalizedUserName"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="normalizedUserName">The normalized user name to search for.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the user matching the specified <paramref name="userID"/> if it exists.
/// </returns>
Task<TUser> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken);
}
}

View File

@ -6,40 +6,64 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Interface to generate user tokens
/// Provides an abstraction for token generators.
/// </summary>
/// <typeparam name="TUser">The type encapsulating a user.</typeparam>
public interface IUserTokenProvider<TUser> where TUser : class
{
/// <summary>
/// Name of the token provider
/// Gets the name of the token provider.
/// </summary>
/// <value>The name of the token provider.</value>
string Name { get; }
/// <summary>
/// Generate a token for a user
/// Generates a token for the specified <paramref name="ref"/> and <paramref name="purpose"/>, as an asynchronous operation.
/// </summary>
/// <param name="purpose"></param>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <returns></returns>
/// <param name="purpose">The purpose the token will be used for.</param>
/// <param name="manager">The <see cref="UserManager{TUser}"/> that can be used to retrieve user properties.</param>
/// <param name="user">The user a token should be generated for.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the token for the specified
/// <paramref name="user"/> and <paramref name="purpose"/>.
/// </returns>
/// <remarks>
/// The <paramref name="purpose"/> parameter allows a token generator to be used for multiple types of token whilst
/// insuring a token for one purpose cannot be used for another. For example if you specified a purpose of "Email"
/// and validated it with the same purpose a token with the purpose of TOTP would not pass the heck even if it was
/// for the same user.
///
/// Implementations of <see cref="IUserTokenProvider{TUser}"/> should validate that purpose is not null or empty to
/// help with token separation.
/// </remarks>
Task<string> GenerateAsync(string purpose, UserManager<TUser> manager, TUser user);
/// <summary>
/// ValidateAsync and unprotect a token, returns null if invalid
/// Returns a flag indicating whether the specified <paramref name="token"/> is valid for the given
/// <paramref name="user"/> and <paramref name="purpose"/>, as an asynchronous operation.
/// </summary>
/// <param name="purpose"></param>
/// <param name="token"></param>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <returns></returns>
/// <param name="purpose">The purpose the token will be used for.</param>
/// <param name="token">The token to validate.</param>
/// <param name="manager">The <see cref="UserManager{TUser}"/> that can be used to retrieve user properties.</param>
/// <param name="user">The user a token should be validated for.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the a flag indicating the result
/// of validating the <paramref name="token"> for the specified </paramref><paramref name="user"/> and <paramref name="purpose"/>.
/// The task will return true if the token is valid, otherwise false.
/// </returns>
Task<bool> ValidateAsync(string purpose, string token, UserManager<TUser> manager, TUser user);
/// <summary>
/// Returns true if provider can be used for this user to generate two factor tokens, i.e. could require a user to have an email
/// Returns a flag indicating whether the token provider can generate a token suitable for two factor authentication token for
/// the specified <paramref name="ref"/>.
/// </summary>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <returns></returns>
/// <param name="manager">The <see cref="UserManager{TUser}"/> that can be used to retrieve user properties.</param>
/// <param name="user">The user a token could be generated for.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the a flag indicating if a two
/// factor token could be generated by this provider for the specified <paramref name="user"/> and <paramref name="purpose"/>.
/// The task will return true if a two factor authentication token could be generated, otherwise false.
/// </returns>
Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<TUser> manager, TUser user);
}
}

View File

@ -7,26 +7,31 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Stores whether two factor is enabled for a user
/// Provides an abstraction to store a flag indicating whether a user has two factor authentication enabled.
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TUser">The type encapsulating a user.</typeparam>
public interface IUserTwoFactorStore<TUser> : IUserStore<TUser> where TUser : class
{
/// <summary>
/// Sets whether two factor is enabled for the user
/// Sets a flag indicating whether the specified <paramref name="user "/>has two factor authentication enabled or not,
/// as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="enabled"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose two factor authentication enabled status should be set.</param>
/// <param name="enabled">A flag indicating whether the specified <paramref name="user"/> has two factor authentication enabled.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
Task SetTwoFactorEnabledAsync(TUser user, bool enabled, CancellationToken cancellationToken);
/// <summary>
/// Returns whether two factor is enabled for the user
/// Returns a flag indicating whether the specified <paramref name="user "/>has two factor authentication enabled or not,
/// as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="user">The user whose two factor authentication enabled status should be set.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing a flag indicating whether the specified
/// <paramref name="user "/>has two factor authentication enabled or not.
/// </returns>
Task<bool> GetTwoFactorEnabledAsync(TUser user, CancellationToken cancellationToken);
}
}

View File

@ -7,18 +7,17 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Used to validate a user
/// Provides an abstraction for user validation.
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TUser">The type encapsulating a user.</typeparam>
public interface IUserValidator<TUser> where TUser : class
{
/// <summary>
/// ValidateAsync the user
/// Validates the specified <paramref name="user"/> as an asynchronous operation.
/// </summary>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="manager">The <see cref="UserManager{TUser}"/> that can be used to retrieve user properties.</param>
/// <param name="user">The user to validate.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/> of the validation operation.</returns>
Task<IdentityResult> ValidateAsync(UserManager<TUser> manager, TUser user);
}
}

View File

@ -6,8 +6,17 @@ using Microsoft.Framework.DependencyInjection;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Helper functions for configuring identity services.
/// </summary>
public class IdentityBuilder
{
/// <summary>
/// Creates a new instance of <see cref="IdentityBuilder"/>.
/// </summary>
/// <param name="user">The <see cref="Type"/> to use for the users.</param>
/// <param name="role">The <see cref="Type"/> to use for the roles.</param>
/// <param name="services">The <see cref="IServiceCollection"/> to attach to.</param>
public IdentityBuilder(Type user, Type role, IServiceCollection services)
{
UserType = user;
@ -15,8 +24,29 @@ namespace Microsoft.AspNet.Identity
Services = services;
}
/// <summary>
/// Gets the <see cref="Type"/> used for users.
/// </summary>
/// <value>
/// The <see cref="Type"/> used for users.
/// </value>
public Type UserType { get; private set; }
/// <summary>
/// Gets the <see cref="Type"/> used for roles.
/// </summary>
/// <value>
/// The <see cref="Type"/> used for roles.
/// </value>
public Type RoleType { get; private set; }
/// <summary>
/// Gets the <see cref="IServiceCollection"/> services are attached to.
/// </summary>
/// <value>
/// The <see cref="IServiceCollection"/> services are attached to.
/// </value>
public IServiceCollection Services { get; private set; }
private IdentityBuilder AddScoped(Type serviceType, Type concreteType)
@ -25,47 +55,91 @@ namespace Microsoft.AspNet.Identity
return this;
}
/// <summary>
/// Adds an <see cref="IUserValidator"/> for the <seealso cref="UserType"/>.
/// </summary>
/// <typeparam name="T">The user type to validate.</typeparam>
/// <returns>The <see cref="IdentityBuilder"/>.</returns>
public virtual IdentityBuilder AddUserValidator<T>() where T : class
{
return AddScoped(typeof(IUserValidator<>).MakeGenericType(UserType), typeof(T));
}
/// <summary>
/// Adds an <see cref="IRoleValidator{TRole}"/> for the <seealso cref="RoleType"/>.
/// </summary>
/// <typeparam name="T">The role type to validate.</typeparam>
/// <returns>The <see cref="IdentityBuilder"/>.</returns>
public virtual IdentityBuilder AddRoleValidator<T>() where T : class
{
return AddScoped(typeof(IRoleValidator<>).MakeGenericType(RoleType), typeof(T));
}
/// <summary>
/// Adds an <see cref="IdentityErrorDescriber"/>.
/// </summary>
/// <typeparam name="T">The type of the error describer.</typeparam>
/// <returns>The <see cref="IdentityBuilder"/>.</returns>
public virtual IdentityBuilder AddErrorDescriber<TDescriber>() where TDescriber : IdentityErrorDescriber
{
Services.AddScoped<IdentityErrorDescriber, TDescriber>();
return this;
}
/// <summary>
/// Adds an <see cref="IPasswordValidator{TUser}"/> for the <seealso cref="UserType"/>.
/// </summary>
/// <typeparam name="T">The user type whose password will be validated.</typeparam>
/// <returns>The <see cref="IdentityBuilder"/>.</returns>
public virtual IdentityBuilder AddPasswordValidator<T>() where T : class
{
return AddScoped(typeof(IPasswordValidator<>).MakeGenericType(UserType), typeof(T));
}
/// <summary>
/// Adds an <see cref="IUserStore{TUser}"/> for the <seealso cref="UserType"/>.
/// </summary>
/// <typeparam name="T">The user type whose password will be validated.</typeparam>
/// <returns>The <see cref="IdentityBuilder"/>.</returns>
public virtual IdentityBuilder AddUserStore<T>() where T : class
{
return AddScoped(typeof(IUserStore<>).MakeGenericType(UserType), typeof(T));
}
/// <summary>
/// Adds a <see cref="IRoleStore{TRole}"/> for the <seealso cref="RoleType"/>.
/// </summary>
/// <typeparam name="T">The role type held in the store.</typeparam>
/// <returns>The <see cref="IdentityBuilder"/>.</returns>
public virtual IdentityBuilder AddRoleStore<T>() where T : class
{
return AddScoped(typeof(IRoleStore<>).MakeGenericType(RoleType), typeof(T));
}
/// <summary>
/// Adds a token provider.
/// </summary>
/// <typeparam name="TProvider">The type of the token provider to add.</typeparam>
/// <returns>The <see cref="IdentityBuilder"/>.</returns>
public virtual IdentityBuilder AddTokenProvider<TProvider>() where TProvider : class
{
return AddTokenProvider(typeof(TProvider));
}
/// <summary>
/// Adds a token provider for the <seealso cref="UserType"/>.
/// </summary>
/// <param name="provider">The type of the <see cref="IUserTokenProvider{TUser}"/> to add.</param>
/// <returns>The <see cref="IdentityBuilder"/>.</returns>
public virtual IdentityBuilder AddTokenProvider(Type provider)
{
return AddScoped(typeof(IUserTokenProvider<>).MakeGenericType(UserType), provider);
}
/// <summary>
/// Adds the default token providers.
/// </summary>
/// <returns>The <see cref="IdentityBuilder"/>.</returns>
public virtual IdentityBuilder AddDefaultTokenProviders()
{
Services.Configure<DataProtectionTokenProviderOptions>(options =>
@ -78,11 +152,21 @@ namespace Microsoft.AspNet.Identity
.AddTokenProvider(typeof(EmailTokenProvider<>).MakeGenericType(UserType));
}
/// <summary>
/// Adds a <see cref="UserManager{TUser}"/> for the <seealso cref="UserType"/>.
/// </summary>
/// <typeparam name="TUserManager">The type of the user manager to add.</typeparam>
/// <returns>The <see cref="IdentityBuilder"/>.</returns>
public virtual IdentityBuilder AddUserManager<TUserManager>() where TUserManager : class
{
return AddScoped(typeof(UserManager<>).MakeGenericType(UserType), typeof(TUserManager));
}
/// <summary>
/// Adds a <see cref="RoleManager{TRole}"/> for the <seealso cref="RoleType"/>.
/// </summary>
/// <typeparam name="TRoleManager">The type of the role manager to add.</typeparam>
/// <returns>The <see cref="IdentityBuilder"/>.</returns>
public virtual IdentityBuilder AddRoleManager<TRoleManager>() where TRoleManager : class
{
return AddScoped(typeof(RoleManager<>).MakeGenericType(RoleType), typeof(TRoleManager));

View File

@ -3,9 +3,25 @@
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Encapsulates an error from the identity subsystem.
/// </summary>
public class IdentityError
{
/// <summary>
/// Gets or sets the code for this error.
/// </summary>
/// <value>
/// The code for this error.
/// </value>
public string Code { get; set; }
/// <summary>
/// Gets or sets the description for this error.
/// </summary>
/// <value>
/// The description for this error.
/// </value>
public string Description { get; set; }
}
}

View File

@ -3,8 +3,18 @@
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Service to enable localization for application facing identity errors.
/// </summary>
/// <remarks>
/// These errors are returned to controllers and are generally used as display messages to end users.
/// </remarks>
public class IdentityErrorDescriber
{
/// <summary>
/// Returns the default <see cref="IdentityError"/>.
/// </summary>
/// <returns>The default <see cref="IdentityError"/>,</returns>
public virtual IdentityError DefaultError()
{
return new IdentityError
@ -13,6 +23,11 @@ namespace Microsoft.AspNet.Identity
Description = Resources.DefaultError
};
}
/// <summary>
/// Returns an <see cref="IdentityError"/> indicating a concurrency failure.
/// </summary>
/// <returns>An <see cref="IdentityError"/> indicating a concurrency failure.</returns>
public virtual IdentityError ConcurrencyFailure()
{
return new IdentityError
@ -22,6 +37,10 @@ namespace Microsoft.AspNet.Identity
};
}
/// <summary>
/// Returns an <see cref="IdentityError"/> indicating a password mismatch.
/// </summary>
/// <returns>An <see cref="IdentityError"/> indicating a password mismatch.</returns>
public virtual IdentityError PasswordMismatch()
{
return new IdentityError
@ -31,6 +50,10 @@ namespace Microsoft.AspNet.Identity
};
}
/// <summary>
/// Returns an <see cref="IdentityError"/> indicating an invalid token.
/// </summary>
/// <returns>An <see cref="IdentityError"/> indicating an invalid token.</returns>
public virtual IdentityError InvalidToken()
{
return new IdentityError
@ -40,6 +63,10 @@ namespace Microsoft.AspNet.Identity
};
}
/// <summary>
/// Returns an <see cref="IdentityError"/> indicating an external login is already associated with an account.
/// </summary>
/// <returns>An <see cref="IdentityError"/> indicating an external login is already associated with an account.</returns>
public virtual IdentityError LoginAlreadyAssociated()
{
return new IdentityError
@ -49,15 +76,25 @@ namespace Microsoft.AspNet.Identity
};
}
public virtual IdentityError InvalidUserName(string name)
/// <summary>
/// Returns an <see cref="IdentityError"/> indicating the specified user <paramref name="userName"/> is invalid.
/// </summary>
/// <param name="userName">The user name that is invalid.</param>
/// <returns>An <see cref="IdentityError"/> indicating the specified user <paramref name="userName"/> is invalid.</returns>
public virtual IdentityError InvalidUserName(string userName)
{
return new IdentityError
{
Code = nameof(InvalidUserName),
Description = Resources.FormatInvalidUserName(name)
Description = Resources.FormatInvalidUserName(userName)
};
}
/// <summary>
/// Returns an <see cref="IdentityError"/> indicating the specified <paramref name="email"/> is invalid.
/// </summary>
/// <param name="email">The email that is invalid.</param>
/// <returns>An <see cref="IdentityError"/> indicating the specified <paramref name="email"/> is invalid.</returns>
public virtual IdentityError InvalidEmail(string email)
{
return new IdentityError
@ -67,15 +104,25 @@ namespace Microsoft.AspNet.Identity
};
}
public virtual IdentityError DuplicateUserName(string name)
/// <summary>
/// Returns an <see cref="IdentityError"/> indicating the specified <paramref name="userName"/> already exists.
/// </summary>
/// <param name="userName">The user name that already exists.</param>
/// <returns>An <see cref="IdentityError"/> indicating the specified <paramref name="userName"/> already exists.</returns>
public virtual IdentityError DuplicateUserName(string userName)
{
return new IdentityError
{
Code = nameof(DuplicateUserName),
Description = Resources.FormatDuplicateUserName(name)
Description = Resources.FormatDuplicateUserName(userName)
};
}
/// <summary>
/// Returns an <see cref="IdentityError"/> indicating the specified <paramref name="email"/> is already associated with an account.
/// </summary>
/// <param name="email">The email that is already associated with an account.</param>
/// <returns>An <see cref="IdentityError"/> indicating the specified <paramref name="email"/> is already associated with an account.</returns>
public virtual IdentityError DuplicateEmail(string email)
{
return new IdentityError
@ -85,24 +132,38 @@ namespace Microsoft.AspNet.Identity
};
}
public virtual IdentityError InvalidRoleName(string name)
/// <summary>
/// Returns an <see cref="IdentityError"/> indicating the specified <paramref name="role"/> name is invalid.
/// </summary>
/// <param name="role">The invalid role.</param>
/// <returns>An <see cref="IdentityError"/> indicating the specific role <paramref name="role"/> name is invalid.</returns>
public virtual IdentityError InvalidRoleName(string role)
{
return new IdentityError
{
Code = nameof(InvalidRoleName),
Description = Resources.FormatInvalidRoleName(name)
Description = Resources.FormatInvalidRoleName(role)
};
}
public virtual IdentityError DuplicateRoleName(string name)
/// <summary>
/// Returns an <see cref="IdentityError"/> indicating the specified <paramref name="role"/> name already exists.
/// </summary>
/// <param name="role">The duplicate role.</param>
/// <returns>An <see cref="IdentityError"/> indicating the specific role <paramref name="role"/> name already exists.</returns>
public virtual IdentityError DuplicateRoleName(string role)
{
return new IdentityError
{
Code = nameof(DuplicateRoleName),
Description = Resources.FormatDuplicateRoleName(name)
Description = Resources.FormatDuplicateRoleName(role)
};
}
/// <summary>
/// Returns an <see cref="IdentityError"/> indicating a user already has a password.
/// </summary>
/// <returns>An <see cref="IdentityError"/> indicating a user already has a password.</returns>
public virtual IdentityError UserAlreadyHasPassword()
{
return new IdentityError
@ -112,6 +173,10 @@ namespace Microsoft.AspNet.Identity
};
}
/// <summary>
/// Returns an <see cref="IdentityError"/> indicating user lockout is not enabled.
/// </summary>
/// <returns>An <see cref="IdentityError"/> indicating user lockout is not enabled..</returns>
public virtual IdentityError UserLockoutNotEnabled()
{
return new IdentityError
@ -121,6 +186,11 @@ namespace Microsoft.AspNet.Identity
};
}
/// <summary>
/// Returns an <see cref="IdentityError"/> indicating a user is already in the specified <paramref name="role"/>.
/// </summary>
/// <param name="role">The duplicate role.</param>
/// <returns>An <see cref="IdentityError"/> indicating a user is already in the specified <paramref name="role"/>.</returns>
public virtual IdentityError UserAlreadyInRole(string role)
{
return new IdentityError
@ -130,6 +200,11 @@ namespace Microsoft.AspNet.Identity
};
}
/// <summary>
/// Returns an <see cref="IdentityError"/> indicating a user is not in the specified <paramref name="role"/>.
/// </summary>
/// <param name="role">The duplicate role.</param>
/// <returns>An <see cref="IdentityError"/> indicating a user is not in the specified <paramref name="role"/>.</returns>
public virtual IdentityError UserNotInRole(string role)
{
return new IdentityError
@ -139,6 +214,11 @@ namespace Microsoft.AspNet.Identity
};
}
/// <summary>
/// Returns an <see cref="IdentityError"/> indicating a password of the specified <paramref name="length"/> does not meet the minimum length requirements.
/// </summary>
/// <param name="length">The length that is not long enough.</param>
/// <returns>An <see cref="IdentityError"/> indicating a password of the specified <paramref name="length"/> does not meet the minimum length requirements.</returns>
public virtual IdentityError PasswordTooShort(int length)
{
return new IdentityError
@ -148,6 +228,11 @@ namespace Microsoft.AspNet.Identity
};
}
/// <summary>
/// Returns an <see cref="IdentityError"/> indicating a password entered does not contain a non-alphanumeric character, which is required by the password policy.
/// </summary>
/// <param name="length">The length that is not long enough.</param>
/// <returns>An <see cref="IdentityError"/> indicating a password entered does not contain a non-alphanumeric character.</returns>
public virtual IdentityError PasswordRequiresNonLetterAndDigit()
{
return new IdentityError
@ -157,6 +242,11 @@ namespace Microsoft.AspNet.Identity
};
}
/// <summary>
/// Returns an <see cref="IdentityError"/> indicating a password entered does not contain a numeric character, which is required by the password policy.
/// </summary>
/// <param name="length">The length that is not long enough.</param>
/// <returns>An <see cref="IdentityError"/> indicating a password entered does not contain a numeric character.</returns>
public virtual IdentityError PasswordRequiresDigit()
{
return new IdentityError
@ -166,6 +256,11 @@ namespace Microsoft.AspNet.Identity
};
}
/// <summary>
/// Returns an <see cref="IdentityError"/> indicating a password entered does not contain a lower case letter, which is required by the password policy.
/// </summary>
/// <param name="length">The length that is not long enough.</param>
/// <returns>An <see cref="IdentityError"/> indicating a password entered does not contain a lower case letter.</returns>
public virtual IdentityError PasswordRequiresLower()
{
return new IdentityError
@ -175,6 +270,11 @@ namespace Microsoft.AspNet.Identity
};
}
/// <summary>
/// Returns an <see cref="IdentityError"/> indicating a password entered does not contain an upper case letter, which is required by the password policy.
/// </summary>
/// <param name="length">The length that is not long enough.</param>
/// <returns>An <see cref="IdentityError"/> indicating a password entered does not contain an upper case letter.</returns>
public virtual IdentityError PasswordRequiresUpper()
{
return new IdentityError

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.
using System;
@ -7,6 +7,12 @@ using Microsoft.Framework.Logging;
namespace Microsoft.AspNet.Identity.Logging
{
/// <summary>
/// Extensions to make logging easier.
/// </summary>
/// <remarks>
/// To be deleted before RTM.
/// </remarks>
public static class IdentityLoggerExtensions
{
private static TResult Log<TResult>(this ILogger logger, TResult result, Func<TResult, LogLevel> getLevel,

View File

@ -6,37 +6,129 @@ using System;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Configuration for identity
/// Represents all the options you can used to configure the identity system.
/// </summary>
public class IdentityOptions
{
/// <summary>
/// Gets or sets the <see cref="ClaimsIdentityOptions"/> for the identity system.
/// </summary>
/// <value>
/// The <see cref="ClaimsIdentityOptions"/> for the identity system.
/// </value>
public ClaimsIdentityOptions ClaimsIdentity { get; set; } = new ClaimsIdentityOptions();
/// <summary>
/// Gets or sets the <see cref="UserOptions"/> for the identity system.
/// </summary>
/// <value>
/// The <see cref="UserOptions"/> for the identity system.
/// </value>
public UserOptions User { get; set; } = new UserOptions();
/// <summary>
/// Gets or sets the <see cref="PasswordOptions"/> for the identity system.
/// </summary>
/// <value>
/// The <see cref="PasswordOptions"/> for the identity system.
/// </value>
public PasswordOptions Password { get; set; } = new PasswordOptions();
/// <summary>
/// Gets or sets the <see cref="LockoutOptions"/> for the identity system.
/// </summary>
/// <value>
/// The <see cref="LockoutOptions"/> for the identity system.
/// </value>
public LockoutOptions Lockout { get; set; } = new LockoutOptions();
/// <summary>
/// Gets or sets the <see cref="SignInOptions"/> for the identity system.
/// </summary>
/// <value>
/// The <see cref="SignInOptions"/> for the identity system.
/// </value>
public SignInOptions SignIn { get; set; } = new SignInOptions();
/// <summary>
/// Gets or sets the <see cref="TimeSpan"/> after which security stamps are re-validated.
/// </summary>
/// <value>
/// The <see cref="TimeSpan"/> after which security stamps are re-validated.
/// </value>
public TimeSpan SecurityStampValidationInterval { get; set; } = TimeSpan.FromMinutes(30);
/// <summary>
/// Gets or sets the <see cref="EmailConfirmationTokenProvider"/> used to generate tokens used in account confirmation emails.
/// </summary>
/// <value>
/// The <see cref="EmailConfirmationTokenProvider"/> used to generate tokens used in account confirmation emails.
/// </value>
public string EmailConfirmationTokenProvider { get; set; } = Resources.DefaultTokenProvider;
/// <summary>
/// Gets or sets the <see cref="PasswordResetTokenProvider"/> used to generate tokens used in password reset emails.
/// </summary>
/// <value>
/// The <see cref="PasswordResetTokenProvider"/> used to generate tokens used in password reset emails.
/// </value>
public string PasswordResetTokenProvider { get; set; } = Resources.DefaultTokenProvider;
/// <summary>
/// Gets or sets the <see cref="ChangeEmailTokenProvider"/> used to generate tokens used in email change confirmation emails.
/// </summary>
/// <value>
/// The <see cref="ChangeEmailTokenProvider"/> used to generate tokens used in email change confirmation emails.
/// </value>
public string ChangeEmailTokenProvider { get; set; } = Resources.DefaultTokenProvider;
/// <summary>
/// Gets or sets the scheme used to identify application authentication cookies.
/// </summary>
/// <value>The scheme used to identify application authentication cookies.</value>
public static string ApplicationCookieAuthenticationScheme { get; set; } = typeof(IdentityOptions).Namespace + ".Application";
/// <summary>
/// Gets or sets the scheme used to identify external authentication cookies.
/// </summary>
/// <value>The scheme used to identify external authentication cookies.</value>
public static string ExternalCookieAuthenticationScheme { get; set; } = typeof(IdentityOptions).Namespace + ".External";
/// <summary>
/// Gets or sets the scheme used to identify Two Factor authentication cookies for round tripping user identities.
/// </summary>
/// <value>The scheme used to identify user identity 2fa authentication cookies.</value>
public static string TwoFactorUserIdCookieAuthenticationScheme { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorUserId";
public static string TwoFactorRememberMeCookieAuthenticationScheme { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorRemeberMe";
/// <summary>
/// Gets or sets the scheme used to identify Two Factor authentication cookies for saving the Remember Me state.
/// </summary>
/// <value>The scheme used to identify remember me application authentication cookies.</value>
public static string TwoFactorRememberMeCookieAuthenticationScheme { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorRememberMe";
/// <summary>
/// Gets or sets the authentication type used when constructing an <see cref="ClaimsIdentity"/> from an application cookie.
/// </summary>
/// <value>The authentication type used when constructing an <see cref="ClaimsIdentity"/> from an application cookie.</value>
public static string ApplicationCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".Application.AuthType";
public static string ExternalCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".External.AuthType";
public static string TwoFactorUserIdCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorUserId.AuthType";
public static string TwoFactorRememberMeCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorRemeberMe.AuthType";
/// <summary>
/// Gets or sets the authentication type used when constructing an <see cref="ClaimsIdentity"/> from an external identity cookie.
/// </summary>
/// <value>The authentication type used when constructing an <see cref="ClaimsIdentity"/> from an external identity cookie.</value>
public static string ExternalCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".External.AuthType";
/// <summary>
/// Gets or sets the authentication type used when constructing an <see cref="ClaimsIdentity"/> from an two factor authentication cookie.
/// </summary>
/// <value>The authentication type used when constructing an <see cref="ClaimsIdentity"/> from an two factor authentication cookie.</value>
public static string TwoFactorUserIdCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorUserId.AuthType";
/// <summary>
/// Gets or sets the authentication type used when constructing an <see cref="ClaimsIdentity"/> from an two factor remember me authentication cookie.
/// </summary>
/// <value>The authentication type used when constructing an <see cref="ClaimsIdentity"/> from an two factor remember me authentication cookie.</value>
public static string TwoFactorRememberMeCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorRemeberMe.AuthType";
}
}

View File

@ -8,33 +8,37 @@ using Microsoft.Framework.Logging;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Represents the result of an identity operation
/// Represents the result of an identity operation.
/// </summary>
public class IdentityResult
{
private static readonly IdentityResult _success = new IdentityResult { Succeeded = true };
private List<IdentityError> _errors = new List<IdentityError>();
/// <summary>
/// True if the operation was successful
/// Flag indicating whether if the operation succeeded or not.
/// </summary>
/// <value>True if the operation succeeded, otherwise false.</value>
public bool Succeeded { get; protected set; }
/// <summary>
/// List of errors
/// An <see cref="IEnumerable{T}"/> of <see cref="IdentityError"/>s containing an errors
/// that occurred during the identity operation.
/// </summary>
/// <value>An <see cref="IEnumerable{T}"/> of <see cref="IdentityError"/>s.</value>
public IEnumerable<IdentityError> Errors => _errors;
/// <summary>
/// Static success result
/// Returns an <see cref="IdentityResult"/> indicating a successful identity operation.
/// </summary>
/// <returns></returns>
/// <returns>An <see cref="IdentityResult"/> indicating a successful operation.</returns>
public static IdentityResult Success => _success;
/// <summary>
/// Failed helper method
/// Creates an <see cref="IdentityResult"/> indicating a failed identity operation, with a list of <paramref name="errors"/> if applicable.
/// </summary>
/// <param name="errors"></param>
/// <returns></returns>
/// <param name="errors">An optional array of <see cref="IdentityError"/>s which caused the operation to fail.</param>
/// <returns>An <see cref="IdentityResult"/> indicating a failed identity operation, with a list of <paramref name="errors"/> if applicable.</returns>
public static IdentityResult Failed(params IdentityError[] errors)
{
var result = new IdentityResult { Succeeded = false };
@ -46,9 +50,13 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Return string representation of IdentityResult
/// Converts the value of the current <see cref="IdentityResult"/> object to its equivalent string representation.
/// </summary>
/// <returns>"Succedded", if result is suceeded else "Failed:error codes"</returns>
/// <returns>A string representation of the current <see cref="IdentityResult"/> object.</returns>
/// <remarks>
/// If the operation was successful the ToString() will return "Succeeded" otherwise it returned
/// "Failed : " followed by a comma delimited list of error codes from its <see cref="Errors"/> collection, if any.
/// </remarks>
public override string ToString()
{
return Succeeded ?
@ -57,9 +65,9 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Get the level to log this result
/// Gets the <see cref="LogLevel"/> for use with any <see cref="ILogger"/> instance.
/// </summary>
/// <returns>LogLevel to log</returns>
/// <returns>The <see cref="LogLevel"/> for this result.</returns>
public virtual LogLevel GetLogLevel()
{
return Succeeded ? LogLevel.Verbose : LogLevel.Warning;

View File

@ -11,34 +11,70 @@ using Microsoft.Framework.Configuration;
namespace Microsoft.Framework.DependencyInjection
{
/// <summary>
/// Contains extension methods to <see cref="IServiceCollection"/> for configuring identity services.
/// </summary>
public static class IdentityServiceCollectionExtensions
{
public static IServiceCollection ConfigureIdentity(this IServiceCollection services, Action<IdentityOptions> configure)
/// <summary>
/// Configures a set of <see cref="IdentityOptions"/> for the application
/// </summary>
/// <param name="services">The services available in the application.</param>
/// <param name="setupAction">An action to configure the <see cref="IdentityOptions"/>.</param>
/// <returns>The <see cref="IServiceCollection"/> instance this method extends.</returns>
public static IServiceCollection ConfigureIdentity(this IServiceCollection services, Action<IdentityOptions> setupAction)
{
return services.Configure(configure);
return services.Configure(setupAction);
}
/// <summary>
/// Configures a set of <see cref="IdentityOptions"/> for the application
/// </summary>
/// <param name="services">The services available in the application.</param>
/// <param name="config">The configuration for the <see cref="IdentityOptions>"/>.</param>
/// <returns>The <see cref="IServiceCollection"/> instance this method extends.</returns>
public static IServiceCollection ConfigureIdentity(this IServiceCollection services, IConfiguration config)
{
return services.Configure<IdentityOptions>(config);
}
public static IServiceCollection ConfigureIdentityApplicationCookie(this IServiceCollection services, Action<CookieAuthenticationOptions> configureOptions)
/// <summary>
/// Configures a set of <see cref="CookieAuthenticationOptions"/> for the application
/// </summary>
/// <param name="services">The services available in the application.</param>
/// <param name="setupAction">An action to configure the <see cref="CookieAuthenticationOptions"/>.</param>
/// <returns>The <see cref="IServiceCollection"/> instance this method extends.</returns>
public static IServiceCollection ConfigureIdentityApplicationCookie(this IServiceCollection services, Action<CookieAuthenticationOptions> setupAction)
{
return services.ConfigureCookieAuthentication(configureOptions, IdentityOptions.ApplicationCookieAuthenticationScheme);
return services.ConfigureCookieAuthentication(setupAction, IdentityOptions.ApplicationCookieAuthenticationScheme);
}
/// <summary>
/// Adds the default identity system configuration for the specified User and Role types.
/// </summary>
/// <typeparam name="TUser">The type representing a User in the system.</typeparam>
/// <typeparam name="TRole">The type representing a Role in the system.</typeparam>
/// <param name="services">The services available in the application.</param>
/// <returns>An <see cref="IdentityBuilder"/> for creating and configuring the identity system.</returns>
public static IdentityBuilder AddIdentity<TUser, TRole>(
this IServiceCollection services)
where TUser : class
where TRole : class
{
return services.AddIdentity<TUser, TRole>(configureOptions: null);
return services.AddIdentity<TUser, TRole>(setupAction: null);
}
/// <summary>
/// Adds and configures the identity system for the specified User and Role types.
/// </summary>
/// <typeparam name="TUser">The type representing a User in the system.</typeparam>
/// <typeparam name="TRole">The type representing a Role in the system.</typeparam>
/// <param name="services">The services available in the application.</param>
/// <param name="setupAction">An action to configure the <see cref="IdentityOptions"/>.</param>
/// <returns>An <see cref="IdentityBuilder"/> for creating and configuring the identity system.</returns>
public static IdentityBuilder AddIdentity<TUser, TRole>(
this IServiceCollection services,
Action<IdentityOptions> configureOptions)
Action<IdentityOptions> setupAction)
where TUser : class
where TRole : class
{
@ -60,9 +96,9 @@ namespace Microsoft.Framework.DependencyInjection
services.TryAdd(ServiceDescriptor.Scoped<SignInManager<TUser>, SignInManager<TUser>>());
services.TryAdd(ServiceDescriptor.Scoped<RoleManager<TRole>, RoleManager<TRole>>());
if (configureOptions != null)
if (setupAction != null)
{
services.ConfigureIdentity(configureOptions);
services.ConfigureIdentity(setupAction);
}
services.Configure<ExternalAuthenticationOptions>(options =>
{

View File

@ -5,21 +5,37 @@ using System;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Options for configuring user lockout.
/// </summary>
public class LockoutOptions
{
/// <summary>
/// If true, will enable user lockout when users are created
/// Gets or sets a flag indicating whether users are locked out upon creation.
/// </summary>
/// <value>
/// True if a newly created user is locked out, otherwise false.
/// </value>
/// <remarks>
/// Defaults to false.
/// </remarks>
public bool EnabledByDefault { get; set; } = false;
/// <summary>
/// Number of access attempts allowed for a user before lockout (if enabled)
/// Gets or sets the number of failed access attempts allowed before a user is locked out,
/// assuming lock out is enabled.
/// </summary>
/// <value>
/// The number of failed access attempts allowed before a user is locked out, if lockout is enabled.
/// </value>
/// <remarks>Defaults to 5 failed attempts before an account is locked out.</remarks>
public int MaxFailedAccessAttempts { get; set; } = 5;
/// <summary>
/// Default amount of time an user is locked out for after MaxFailedAccessAttempsBeforeLockout is reached
/// Gets or sets the <see cref="TimeSpan"/> a user is locked out for when a lockout occurs.
/// </summary>
/// <value>The <see cref="TimeSpan"/> a user is locked out for when a lockout occurs.</value>
/// <remarks>Defaults to 5 minutes.</remarks>
public TimeSpan DefaultLockoutTimeSpan { get; set; } = TimeSpan.FromMinutes(5);
}
}

View File

@ -10,8 +10,9 @@ using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Implements password hashing methods
/// Implements the standard Identity password hashing.
/// </summary>
/// <typeparam name="TUser">The type used to represent a user.</typeparam>
public class PasswordHasher<TUser> : IPasswordHasher<TUser> where TUser : class
{
/* =======================
@ -34,9 +35,9 @@ namespace Microsoft.AspNet.Identity
private readonly RandomNumberGenerator _rng;
/// <summary>
/// Constructs a PasswordHasher using the specified options
/// Creates a new instance of <see cref="PasswordHasher{TUser}"/>.
/// </summary>
/// <param name="options"></param>
/// <param name="options">The options for this instance.</param>
public PasswordHasher(IOptions<PasswordHasherOptions> optionsAccessor = null)
{
var options = optionsAccessor?.Options ?? new PasswordHasherOptions();
@ -84,11 +85,11 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Hash a password
/// Returns a hashed representation of the supplied <paramref name="password"/> for the specified <paramref name="user"/>.
/// </summary>
/// <param name="user"></param>
/// <param name="password"></param>
/// <returns></returns>
/// <param name="user">The user whose password is to be hashed.</param>
/// <param name="password">The password to hash.</param>
/// <returns>A hashed representation of the supplied <paramref name="password"/> for the specified <paramref name="user"/>.</returns>
public virtual string HashPassword(TUser user, string password)
{
if (password == null)
@ -160,12 +161,13 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Verify that a password matches the hashedPassword
/// Returns a <see cref="PasswordVerificationResult"/> indicating the result of a password hash comparison.
/// </summary>
/// <param name="user"></param>
/// <param name="hashedPassword"></param>
/// <param name="providedPassword"></param>
/// <returns></returns>
/// <param name="user">The user whose password should be verified.</param>
/// <param name="hashedPassword">The hash value for a user's stored password.</param>
/// <param name="providedPassword">The password supplied for comparison.</param>
/// <returns>A <see cref="PasswordVerificationResult"/> indicating the result of a password hash comparison.</returns>
/// <remarks>Implementations of this method should be time consistent.</remarks>
public virtual PasswordVerificationResult VerifyHashedPassword(TUser user, string hashedPassword, string providedPassword)
{
if (hashedPassword == null)

View File

@ -4,17 +4,17 @@
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// An enum that describes the format used for hashing passwords.
/// Specifies the format used for hashing passwords.
/// </summary>
public enum PasswordHasherCompatibilityMode
{
/// <summary>
/// Hashes passwords in a way that is compatible with ASP.NET Identity versions 1 and 2.
/// Indicates hashing passwords in a way that is compatible with ASP.NET Identity versions 1 and 2.
/// </summary>
IdentityV2,
/// <summary>
/// Hashes passwords in a way that is compatible with ASP.NET Identity version 3.
/// Indicates hashing passwords in a way that is compatible with ASP.NET Identity version 3.
/// </summary>
IdentityV3
}

View File

@ -6,25 +6,31 @@ using System.Security.Cryptography;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Allows configuring how passwords are hashed.
/// Specifies options for password hashing.
/// </summary>
public class PasswordHasherOptions
{
private static readonly RandomNumberGenerator _defaultRng = RandomNumberGenerator.Create(); // secure PRNG
/// <summary>
/// Specifies the compatibility mode to use when hashing passwords.
/// Gets or sets the compatibility mode used when hashing passwords.
/// </summary>
/// <value>
/// The compatibility mode used when hashing passwords.
/// </value>
/// <remarks>
/// The default compatibility mode is 'ASP.NET Identity version 3'.
/// </remarks>
public PasswordHasherCompatibilityMode CompatibilityMode { get; set; } = PasswordHasherCompatibilityMode.IdentityV3;
/// <summary>
/// Specifies the number of iterations to use when hashing passwords using PBKDF2.
/// Gets or sets the number of iterations used when hashing passwords using PBKDF2.
/// </summary>
/// <value>
/// The number of iterations used when hashing passwords using PBKDF2.
/// </value>
/// <remarks>
/// This value is only used when the compatibiliy mode is set to 'V3'.
/// This value is only used when the compatibility mode is set to 'V3'.
/// The value must be a positive integer. The default value is 10,000.
/// </remarks>
public int IterationCount { get; set; } = 10000;

View File

@ -3,31 +3,53 @@
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Specifies options for password requirements.
/// </summary>
public class PasswordOptions
{
/// <summary>
/// Minimum required length
/// Gets or sets the minimum length a password must be.
/// </summary>
/// <remarks>
/// This defaults to 6.
/// </remarks>
public int RequiredLength { get; set; } = 6;
/// <summary>
/// Require a non letter or digit character
/// Gets or sets a flag indicating if passwords must contain a digit or other non-alphabetical character.
/// </summary>
/// <value>True if passwords must contain a digit or other non-alphabetical character, otherwise false.</value>
/// <remarks>
/// This defaults to true.
/// </remarks>
public bool RequireNonLetterOrDigit { get; set; } = true;
/// <summary>
/// Require a lower case letter ('a' - 'z')
/// Gets or sets a flag indicating if passwords must contain a lower case ASCII character.
/// </summary>
/// <value>True if passwords must contain a lower case ASCII character.</value>
/// <remarks>
/// This defaults to true.
/// </remarks>
public bool RequireLowercase { get; set; } = true;
/// <summary>
/// Require an upper case letter ('A' - 'Z')
/// Gets or sets a flag indicating if passwords must contain a upper case ASCII character.
/// </summary>
/// <value>True if passwords must contain a upper case ASCII character.</value>
/// <remarks>
/// This defaults to true.
/// </remarks>
public bool RequireUppercase { get; set; } = true;
/// <summary>
/// Require a digit ('0' - '9')
/// Gets or sets a flag indicating if passwords must contain a digit.
/// </summary>
/// <value>True if passwords must contain a digit.</value>
/// <remarks>
/// This defaults to true.
/// </remarks>
public bool RequireDigit { get; set; } = true;
}
}

View File

@ -4,30 +4,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Used to validate some basic password policy like length and number of non alphanumerics
/// Provides the default password policy for Identity.
/// </summary>
/// <typeparam name="TUser">The type that represents a user.</typeparam>
public class PasswordValidator<TUser> : IPasswordValidator<TUser> where TUser : class
{
/// <summary>
/// Constructions a new instance of <see cref="PasswordValidator{TUser}"/>.
/// </summary>
/// <param name="errors">The <see cref="IdentityErrorDescriber"/> to retrieve error text from.</param>
public PasswordValidator(IdentityErrorDescriber errors = null)
{
Describer = errors ?? new IdentityErrorDescriber();
}
/// <summary>
/// Gets the <see cref="IdentityErrorDescriber"/> used to supply error text.
/// </summary>
/// <value>The <see cref="IdentityErrorDescriber"/> used to supply error text.</value>
public IdentityErrorDescriber Describer { get; private set; }
/// <summary>
/// Ensures that the password is of the required length and meets the configured requirements
/// Validates a password as an asynchronous operation.
/// </summary>
/// <param name="password"></param>
/// <param name="manager"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="manager">The <see cref="UserManager{TUser}"/> to retrieve the <paramref name="user"/> properties from.</param>
/// <param name="user">The user whose password should be validated.</param>
/// <param name="password">The password supplied for validation</param>
/// <returns>The task object representing the asynchronous operation.</returns>
public virtual Task<IdentityResult> ValidateAsync(UserManager<TUser> manager, TUser user, string password)
{
if (password == null)
@ -67,40 +75,40 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Returns true if the character is a digit between '0' and '9'
/// Returns a flag indicting whether the supplied character is a digit.
/// </summary>
/// <param name="c"></param>
/// <returns></returns>
/// <param name="c">The character to check if it is a digit.</param>
/// <returns>True if the character is a digit, otherwise false.</returns>
public virtual bool IsDigit(char c)
{
return c >= '0' && c <= '9';
}
/// <summary>
/// Returns true if the character is between 'a' and 'z'
/// Returns a flag indicting whether the supplied character is a lower case ASCII letter.
/// </summary>
/// <param name="c"></param>
/// <returns></returns>
/// <param name="c">The character to check if it is a lower case ASCII letter.</param>
/// <returns>True if the character is a lower case ASCII letter, otherwise false.</returns>
public virtual bool IsLower(char c)
{
return c >= 'a' && c <= 'z';
}
/// <summary>
/// Returns true if the character is between 'A' and 'Z'
/// Returns a flag indicting whether the supplied character is an upper case ASCII letter.
/// </summary>
/// <param name="c"></param>
/// <returns></returns>
/// <param name="c">The character to check if it is an upper case ASCII letter.</param>
/// <returns>True if the character is an upper case ASCII letter, otherwise false.</returns>
public virtual bool IsUpper(char c)
{
return c >= 'A' && c <= 'Z';
}
/// <summary>
/// Returns true if the character is upper, lower, or a digit
/// Returns a flag indicting whether the supplied character is an ASCII letter or digit.
/// </summary>
/// <param name="c"></param>
/// <returns></returns>
/// <param name="c">The character to check if it is an ASCII letter or digit.</param>
/// <returns>True if the character is an ASCII letter or digit, otherwise false.</returns>
public virtual bool IsLetterOrDigit(char c)
{
return IsUpper(c) || IsLower(c) || IsDigit(c);

View File

@ -4,22 +4,23 @@
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Return result for IPasswordHasher
/// Specifies the results for password verification.
/// </summary>
public enum PasswordVerificationResult
{
/// <summary>
/// Password verification failed
/// Indicates password verification failed.
/// </summary>
Failed = 0,
/// <summary>
/// Success
/// Indicates password verification was successful.
/// </summary>
Success = 1,
/// <summary>
/// Success but should update and rehash the password
/// Indicates password verification was successful however the password was encoded using a deprecated algorithm
/// and should be rehashed and updated.
/// </summary>
SuccessRehashNeeded = 2
}

View File

@ -1,22 +1,35 @@
using System;
using System.Globalization;
using System.Threading.Tasks;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Encapsulations options for a <see cref="PhoneNumberTokenProvider{TUser}"/>.
/// </summary>
public class PhoneNumberTokenProviderOptions
{
/// <summary>
/// Gets or sets the name for the <see cref="PhoneNumberTokenProvider{TUser}"/>.
/// </summary>
/// <value>
/// The name for the <see cref="PhoneNumberTokenProvider{TUser}"/>.
/// </value>
public string Name { get; set; } = "Phone";
}
/// <summary>
/// TokenProvider that generates tokens from the user's security stamp and notifies a user via their phone number
/// Represents a token provider that generates tokens from a user's security stamp and
/// sends them to the user via their phone number.
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TUser">The type encapsulating a user.</typeparam>
public class PhoneNumberTokenProvider<TUser> : TotpSecurityStampBasedTokenProvider<TUser>
where TUser : class
{
/// <summary>
/// Creates a new instance of <see cref="PhoneNumberTokenProvider{TUser}"/> with the specified <paramref name="options"/>.
/// </summary>
/// <param name="options">The options to use for the created instance of a <see cref="PhoneNumberTokenProvider{TUser}"/>.</param>
public PhoneNumberTokenProvider(IOptions<PhoneNumberTokenProviderOptions> options)
{
if (options == null || options.Options == null)
@ -26,16 +39,30 @@ namespace Microsoft.AspNet.Identity
Options = options.Options;
}
/// <summary>
/// Gets the options for this instance of <see cref="PhoneNumberTokenProvider{TUser}"/>.
/// </summary>
/// <value>The options for this instance of <see cref="PhoneNumberTokenProvider{TUser}"/>.</value>
public PhoneNumberTokenProviderOptions Options { get; private set; }
/// <summary>
/// Gets the name for this instance of <see cref="PhoneNumberTokenProvider{TUser}"/>.
/// </summary>
/// <value>The name for this instance of <see cref="PhoneNumberTokenProvider{TUser}"/>.</value>
public override string Name { get { return Options.Name; } }
/// <summary>
/// Returns true if the user has a phone number set
/// Returns a flag indicating whether the token provider can generate a token suitable for two factor authentication token for
/// the specified <paramref name="ref"/>.
/// </summary>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <returns></returns>
/// <param name="manager">The <see cref="UserManager{TUser}"/> that can be used to retrieve user properties.</param>
/// <param name="user">The user a token could be generated for.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the a flag indicating if a two
/// factor token could be generated by this provider for the specified <paramref name="user"/> and <paramref name="purpose"/>.
/// The task will return true if a two factor authentication token could be generated as the user has
/// a telephone number, otherwise false.
/// </returns>
public override async Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<TUser> manager, TUser user)
{
if (manager == null)
@ -47,12 +74,15 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Returns the phone number of the user for entropy in the token
/// Returns a constant, provider and user unique modifier used for entropy in generated tokens from user information, as an asynchronous operation.
/// </summary>
/// <param name="purpose"></param>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <returns></returns>
/// <param name="purpose">The purpose the token will be generated for.</param>
/// <param name="manager">The <see cref="UserManager{TUser}"/> that can be used to retrieve user properties.</param>
/// <param name="user">The user a token should be generated for.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing a constant modifier for the specified
/// <paramref name="user"/> and <paramref name="purpose"/>.
/// </returns>
public override async Task<string> GetUserModifierAsync(string purpose, UserManager<TUser> manager, TUser user)
{
if (manager == null)

View File

@ -16,7 +16,7 @@ namespace System.Security.Claims
/// </summary>
/// <param name="principal">The <see cref="ClaimsPrincipal"/> instance this method extends.</param>
/// <returns>The Name claim value, or null if the claim is not present.</returns>
/// <remarks>The name claim is identified by <see cref="ClaimsIdentity.DefaultNameClaimType"/>.</remarks>
/// <remarks>The Name claim is identified by <see cref="ClaimsIdentity.DefaultNameClaimType"/>.</remarks>
public static string GetUserName(this ClaimsPrincipal principal)
{
if (principal == null)
@ -31,7 +31,7 @@ namespace System.Security.Claims
/// </summary>
/// <param name="principal">The <see cref="ClaimsPrincipal"/> instance this method extends.</param>
/// <returns>The User ID claim value, or null if the claim is not present.</returns>
/// <remarks>The name claim is identified by <see cref="ClaimTypes.NameIdentifier"/>.</remarks>
/// <remarks>The User ID claim is identified by <see cref="ClaimTypes.NameIdentifier"/>.</remarks>
public static string GetUserId(this ClaimsPrincipal principal)
{
if (principal == null)
@ -59,9 +59,9 @@ namespace System.Security.Claims
/// <summary>
/// Returns the value for the first claim of the specified type otherwise null the claim is not present.
/// </summary>
/// <param name="identity">The <see cref="IIdentity"/> instance this method extends.</param>
/// <param name="principal">The <see cref="ClaimsPrincipal"/> instance this method extends.</param>
/// <param name="claimType">The claim type whose first value should be returned.</param>
/// <returns>The value of the first instance of the specifed claim type, or null if the claim is not present.</returns>
/// <returns>The value of the first instance of the specified claim type, or null if the claim is not present.</returns>
public static string FindFirstValue(this ClaimsPrincipal principal, string claimType)
{
if (principal == null)

View File

@ -16,23 +16,24 @@ using Microsoft.Framework.Logging;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Exposes role related api which will automatically save changes to the RoleStore
/// Provides the APIs for managing roles in a persistence store.
/// </summary>
/// <typeparam name="TRole"></typeparam>
/// <typeparam name="TUser">The type encapsulating a role.</typeparam>
public class RoleManager<TRole> : IDisposable where TRole : class
{
private bool _disposed;
private readonly HttpContext _context;
private CancellationToken CancellationToken => _context?.RequestAborted ?? CancellationToken.None;
/// <summary>
/// Constructor
/// Constructs a new instance of <see cref="RoleManager{TRole}"/>.
/// </summary>
/// <param name="store">The IRoleStore commits changes via the UpdateAsync/CreateAsync methods</param>
/// <param name="roleValidators">IEnumerable of role validators</param>
/// <param name="keyNormalizer">user property normalizers</param>
/// <param name="errors">IdentityErrorDescribers</param>
/// <param name="logger">Logger for RoleManager</param>
/// <param name="contextAccessor">HttpContext accessor object</param>
/// <param name="store">The persistence store the manager will operate over.</param>
/// <param name="roleValidators">A collection of validators for roles.</param>
/// <param name="keyNormalizer">The normalizer to use when normalizing role names to keys.</param>
/// <param name="errors">The <see cref="IdentityErrorDescriber"/> used to provider error messages.</param>
/// <param name="logger">The logger used to log messages, warnings and errors.</param>
/// <param name="contextAccessor">The accessor used to access the <see cref="HttpContext"/>.</param>
public RoleManager(IRoleStore<TRole> store,
IEnumerable<IRoleValidator<TRole>> roleValidators,
ILookupNormalizer keyNormalizer,
@ -60,33 +61,51 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Persistence abstraction that the Manager operates against
/// Gets the persistence store this instance operates over.
/// </summary>
/// <value>The persistence store this instance operates over.</value>
protected IRoleStore<TRole> Store { get; private set; }
/// <summary>
/// Used for logging results
/// Gets the <see cref="ILogger"/> used to log messages from the manager.
/// </summary>
/// <value>
/// The <see cref="ILogger"/> used to log messages from the manager.
/// </value>
protected internal virtual ILogger Logger { get; set; }
/// <summary>
/// Used to validate roles before persisting changes
/// Gets a list of validators for roles to call before persistence.
/// </summary>
/// <value>A list of validators for roles to call before persistence.</value>
internal IList<IRoleValidator<TRole>> RoleValidators { get; } = new List<IRoleValidator<TRole>>();
/// <summary>
/// Used to generate public API error messages
/// Gets the <see cref="IdentityErrorDescriber"/> used to provider error messages.
/// </summary>
/// <value>
/// The <see cref="IdentityErrorDescriber"/> used to provider error messages.
/// </value>
internal IdentityErrorDescriber ErrorDescriber { get; set; }
/// <summary>
/// Used to normalize user names, role names, emails for uniqueness
/// Gets the normalizer to use when normalizing role names to keys.
/// </summary>
/// <value>
/// The normalizer to use when normalizing role names to keys.
/// </value>
internal ILookupNormalizer KeyNormalizer { get; set; }
/// <summary>
/// Returns an IQueryable of roles if the store is an IQueryableRoleStore
/// Gets an IQueryable collection of Roles if the persistence store is an <see cref="IQueryableRoleStore"/>,
/// otherwise throws a <see cref="NotSupportedException"/>.
/// </summary>
/// <value>An IQueryable collection of Roles if the persistence store is an <see cref="IQueryableRoleStore"/>.</value>
/// <exception cref="NotSupportedException">Thrown if the persistence store is not an <see cref="IQueryableRoleStore"/>.</exception>
/// <remarks>
/// Callers to this property should use <see cref="SupportsQueryableRoles"/> to ensure the backing role store supports
/// returning an IQueryable list of roles.
/// </remarks>
public virtual IQueryable<TRole> Roles
{
get
@ -101,8 +120,11 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Returns true if the store is an IQueryableRoleStore
/// Gets a flag indicating whether the underlying persistence store supports returning an <see cref="IQueryable"/> collection of roles.
/// </summary>
/// <value>
/// true if the underlying persistence store supports returning an <see cref="IQueryable"/> collection of roles, otherwise false.
/// </value>
public virtual bool SupportsQueryableRoles
{
get
@ -113,8 +135,11 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Returns true if the store is an IUserClaimStore
/// Gets a flag indicating whether the underlying persistence store supports <see cref="Claim"/>s for roles.
/// </summary>
/// <value>
/// true if the underlying persistence store supports <see cref="Claim"/>s for roles, otherwise false.
/// </value>
public virtual bool SupportsRoleClaims
{
get
@ -124,36 +149,13 @@ namespace Microsoft.AspNet.Identity
}
}
private CancellationToken CancellationToken => _context?.RequestAborted ?? CancellationToken.None;
/// <summary>
/// Dispose this object
/// Creates the specified <paramref name="role"/> in the persistence store, as an asynchronous operation.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private async Task<IdentityResult> ValidateRoleInternal(TRole role)
{
var errors = new List<IdentityError>();
foreach (var v in RoleValidators)
{
var result = await v.ValidateAsync(this, role);
if (!result.Succeeded)
{
errors.AddRange(result.Errors);
}
}
return errors.Count > 0 ? IdentityResult.Failed(errors.ToArray()) : IdentityResult.Success;
}
/// <summary>
/// Create a role
/// </summary>
/// <param name="role"></param>
/// <returns></returns>
/// <param name="role">The role to create.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation.
/// </returns>
public virtual async Task<IdentityResult> CreateAsync(TRole role)
{
ThrowIfDisposed();
@ -175,22 +177,25 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Update the user's normalized user name
/// Updates the normalized name for the specified <paramref name="role"/>, as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <returns></returns>
/// <param name="role">The role whose normalized name needs to be updated.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation.
/// </returns>
public virtual async Task UpdateNormalizedRoleNameAsync(TRole role)
{
var name = await GetRoleNameAsync(role);
await Store.SetNormalizedRoleNameAsync(role, NormalizeKey(name), CancellationToken);
}
/// <summary>
/// Update an existing role
/// Updates the specified <paramref name="role"/>, as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <returns></returns>
/// <param name="role">The role to updated.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/> for the update.
/// </returns>
public virtual async Task<IdentityResult> UpdateAsync(TRole role)
{
ThrowIfDisposed();
@ -205,22 +210,13 @@ namespace Microsoft.AspNet.Identity
}
}
private async Task<IdentityResult> UpdateRoleAsync(TRole role)
{
var result = await ValidateRoleInternal(role);
if (!result.Succeeded)
{
return result;
}
await UpdateNormalizedRoleNameAsync(role);
return await Store.UpdateAsync(role, CancellationToken);
}
/// <summary>
/// Delete a role
/// Deletes the specified <paramref name="role"/>, as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <returns></returns>
/// <param name="role">The role to delete.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/> for the delete.
/// </returns>
public virtual async Task<IdentityResult> DeleteAsync(TRole role)
{
ThrowIfDisposed();
@ -236,10 +232,12 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Returns true if the role exists
/// Gets a flag indicating whether the specified <paramref name="roleName"/> exists, as an asynchronous operation.
/// </summary>
/// <param name="roleName"></param>
/// <returns></returns>
/// <param name="roleName">The role name whose existence should be checked.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing true if the role name exists, otherwise false.
/// </returns>
public virtual async Task<bool> RoleExistsAsync(string roleName)
{
ThrowIfDisposed();
@ -252,21 +250,23 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Normalize a key (role name) for uniqueness comparisons
/// Gets a normalized representation of the specified <paramref name="key"/>.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
/// <param name="key">The value to normalize.</param>
/// <returns>A normalized representation of the specified <paramref name="key"/>.</returns>
public virtual string NormalizeKey(string key)
{
return (KeyNormalizer == null) ? key : KeyNormalizer.Normalize(key);
}
/// <summary>
/// Find a role by id
/// Finds the role associated with the specified <paramref name="roleId"/> if any, as an asynchronous operation.
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
/// <param name="roleId">The role ID whose role should be returned.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the role
/// associated with the specified <paramref name="roleId"/>
/// </returns>
public virtual async Task<TRole> FindByIdAsync(string roleId)
{
ThrowIfDisposed();
@ -274,10 +274,13 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Return the name of the role
/// Gets the name of the specified <paramref name="role"/>, as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <returns></returns>
/// <param name="role">The role whose name should be retrieved.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the name of the
/// specified <paramref name="role"/>.
/// </returns>
public virtual async Task<string> GetRoleNameAsync(TRole role)
{
ThrowIfDisposed();
@ -285,11 +288,14 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Set the name of the role
/// Sets the name of the specified <paramref name="role"/>, as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <param name="name"></param>
/// <returns></returns>
/// <param name="role">The role whose name should be set.</param>
/// <param name="name">The name to set.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/>
/// of the operation.
/// </returns>
public virtual async Task<IdentityResult> SetRoleNameAsync(TRole role, string name)
{
ThrowIfDisposed();
@ -303,10 +309,13 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Return the role id for a role
/// Gets the ID of the specified <paramref name="role"/>, as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <returns></returns>
/// <param name="role">The role whose ID should be retrieved.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the ID of the
/// specified <paramref name="role"/>.
/// </returns>
public virtual async Task<string> GetRoleIdAsync(TRole role)
{
ThrowIfDisposed();
@ -314,10 +323,13 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// FindByLoginAsync a role by name
/// Finds the role associated with the specified <paramref name="roleName"/> if any, as an asynchronous operation.
/// </summary>
/// <param name="roleName"></param>
/// <returns></returns>
/// <param name="roleName">The name of the role to be returned.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the role
/// associated with the specified <paramref name="roleName"/>
/// </returns>
public virtual async Task<TRole> FindByNameAsync(string roleName)
{
ThrowIfDisposed();
@ -329,23 +341,15 @@ namespace Microsoft.AspNet.Identity
return await Store.FindByNameAsync(NormalizeKey(roleName), CancellationToken);
}
// IRoleClaimStore methods
private IRoleClaimStore<TRole> GetClaimStore()
{
var cast = Store as IRoleClaimStore<TRole>;
if (cast == null)
{
throw new NotSupportedException(Resources.StoreNotIRoleClaimStore);
}
return cast;
}
/// <summary>
/// Add a user claim
/// Adds a claim to a role, as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <param name="claim"></param>
/// <returns></returns>
/// <param name="role">The role to add the claim to.</param>
/// <param name="claim">The claim to add.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/>
/// of the operation.
/// </returns>
public virtual async Task<IdentityResult> AddClaimAsync(TRole role, Claim claim)
{
ThrowIfDisposed();
@ -367,11 +371,14 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Remove a user claim
/// Removes a claim from a role, as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <param name="claim"></param>
/// <returns></returns>
/// <param name="role">The role to remove the claim from.</param>
/// <param name="claim">The claim to add.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/>
/// of the operation.
/// </returns>
public virtual async Task<IdentityResult> RemoveClaimAsync(TRole role, Claim claim)
{
ThrowIfDisposed();
@ -389,10 +396,13 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Get a role's claims
/// Gets a list of claims associated with the specified <paramref name="role"/>, as an asynchronous operation.
/// </summary>
/// <param name="role"></param>
/// <returns></returns>
/// <param name="role">The role whose claims should be returned.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the list of <see cref="Claim"/>s
/// associated with the specified <paramref name="role"/>.
/// </returns>
public virtual async Task<IList<Claim>> GetClaimsAsync(TRole role)
{
ThrowIfDisposed();
@ -404,25 +414,19 @@ namespace Microsoft.AspNet.Identity
return await claimStore.GetClaimsAsync(role, CancellationToken);
}
protected virtual async Task<IDisposable> BeginLoggingScopeAsync(TRole role, [CallerMemberName] string methodName = null)
/// <summary>
/// Releases all resources used by the role manager.
/// </summary>
public void Dispose()
{
var state = Resources.FormatLoggingResultMessageForRole(methodName, await GetRoleIdAsync(role));
return Logger?.BeginScope(state);
}
private void ThrowIfDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().Name);
}
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// When disposing, actually dipose the store
/// Releases the unmanaged resources used by the role manager and optionally releases the managed resources.
/// </summary>
/// <param name="disposing"></param>
/// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
if (disposing && !_disposed)
@ -431,5 +435,55 @@ namespace Microsoft.AspNet.Identity
}
_disposed = true;
}
protected virtual async Task<IDisposable> BeginLoggingScopeAsync(TRole role, [CallerMemberName] string methodName = null)
{
var state = Resources.FormatLoggingResultMessageForRole(methodName, await GetRoleIdAsync(role));
return Logger?.BeginScope(state);
}
private async Task<IdentityResult> ValidateRoleInternal(TRole role)
{
var errors = new List<IdentityError>();
foreach (var v in RoleValidators)
{
var result = await v.ValidateAsync(this, role);
if (!result.Succeeded)
{
errors.AddRange(result.Errors);
}
}
return errors.Count > 0 ? IdentityResult.Failed(errors.ToArray()) : IdentityResult.Success;
}
private async Task<IdentityResult> UpdateRoleAsync(TRole role)
{
var result = await ValidateRoleInternal(role);
if (!result.Succeeded)
{
return result;
}
await UpdateNormalizedRoleNameAsync(role);
return await Store.UpdateAsync(role, CancellationToken);
}
// IRoleClaimStore methods
private IRoleClaimStore<TRole> GetClaimStore()
{
var cast = Store as IRoleClaimStore<TRole>;
if (cast == null)
{
throw new NotSupportedException(Resources.StoreNotIRoleClaimStore);
}
return cast;
}
private void ThrowIfDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().Name);
}
}
}
}

View File

@ -8,11 +8,15 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Validates roles before they are saved
/// Provides the default validation of roles.
/// </summary>
/// <typeparam name="TRole"></typeparam>
/// <typeparam name="TRole">The type encapsulating a role.</typeparam>
public class RoleValidator<TRole> : IRoleValidator<TRole> where TRole : class
{
/// <summary>
/// Creates a new instance of <see cref="RoleValidator{TRole}"/>/
/// </summary>
/// <param name="errors">The <see cref="IdentityErrorDescriber"/> used to provider error messages.</param>
public RoleValidator(IdentityErrorDescriber errors = null)
{
Describer = errors ?? new IdentityErrorDescriber();
@ -21,12 +25,11 @@ namespace Microsoft.AspNet.Identity
private IdentityErrorDescriber Describer { get; set; }
/// <summary>
/// Validates a role before saving
/// Validates a role as an asynchronous operation.
/// </summary>
/// <param name="manager"></param>
/// <param name="role"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="manager">The <see cref="RoleManager{TRole}"/> managing the role store.</param>
/// <param name="role">The role to validate.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the <see cref="IdentityResult"/> of the asynchronous validation.</returns>
public virtual async Task<IdentityResult> ValidateAsync(RoleManager<TRole> manager, TRole role)
{
if (manager == null)

View File

@ -11,13 +11,18 @@ using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Provides default implementation of validation functions for security stamps.
/// </summary>
/// <typeparam name="TUser">The type encapsulating a user.</typeparam>
public class SecurityStampValidator<TUser> : ISecurityStampValidator where TUser : class
{
/// <summary>
/// Rejects the identity if the stamp changes, and otherwise will sign in a new
/// ClaimsIdentity
/// Validates a security stamp of an identity as an asynchronous operation, and rebuilds the identity if the validation succeeds, otherwise rejects
/// the identity.
/// </summary>
/// <returns></returns>
/// <param name="context">The context containing the <see cref="ClaimsPrincipal"/>and <see cref="AuthenticationProperties"/> to validate.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous validation operation.</returns>
public virtual async Task ValidateAsync(CookieValidatePrincipalContext context)
{
var manager = context.HttpContext.RequestServices.GetRequiredService<SignInManager<TUser>>();
@ -36,11 +41,17 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Static helper class used to configure a CookieAuthenticationNotifications to validate a cookie against a user's security
/// stamp
/// Static helper class used to configure a CookieAuthenticationNotifications to validate a cookie against a user's security
/// stamp.
/// </summary>
public static class SecurityStampValidator
{
/// <summary>
/// Validates a principal against a user's stored security stamp.
/// the identity.
/// </summary>
/// <param name="context">The context containing the <see cref="ClaimsPrincipal"/>and <see cref="AuthenticationProperties"/> to validate.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous validation operation.</returns>
public static Task ValidatePrincipalAsync(CookieValidatePrincipalContext context)
{
var currentUtc = DateTimeOffset.UtcNow;

View File

@ -17,11 +17,22 @@ using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Interface that manages SignIn operations for a user
/// Provides the APIs for user sign in.
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TUser">The type encapsulating a user.</typeparam>
public class SignInManager<TUser> where TUser : class
{
private const string LoginProviderKey = "LoginProvider";
private const string XsrfKey = "XsrfId";
/// <summary>
/// Creates a new instance of <see cref="SignInManager{TUser}"/>.
/// </summary>
/// <param name="userManager">An instance of <see cref="UserManager"/> used to retrieve users from and persist users.</param>
/// <param name="contextAccessor">The accessor used to access the <see cref="HttpContext"/>.</param>
/// <param name="claimsFactory">The factory to use to create claims principals for a user.</param>
/// <param name="optionsAccessor">The accessor used to access the <see cref="IdentityOptions"/>.</param>
/// <param name="logger">The logger used to log messages, warnings and errors.</param>
public SignInManager(UserManager<TUser> userManager,
IHttpContextAccessor contextAccessor,
IUserClaimsPrincipalFactory<TUser> claimsFactory,
@ -48,15 +59,33 @@ namespace Microsoft.AspNet.Identity
Logger = logger;
}
/// <summary>
/// Gets the <see cref="ILogger"/> used to log messages from the manager.
/// </summary>
/// <value>
/// The <see cref="ILogger"/> used to log messages from the manager.
/// </value>
protected internal virtual ILogger Logger { get; set; }
internal UserManager<TUser> UserManager { get; set; }
internal HttpContext Context { get; set; }
internal IUserClaimsPrincipalFactory<TUser> ClaimsFactory { get; set; }
internal IdentityOptions Options { get; set; }
// Should this be a func?
/// <summary>
/// Creates a <see cref="ClaimsPrincipal"/> for the specified <paramref name="user"/>, as an asynchronous operation.
/// </summary>
/// <param name="user">The user to create a <see cref="ClaimsPrincipal"/> for.</param>
/// <returns>The task object representing the asynchronous operation, containing the ClaimsPrincipal for the specified user.</returns>
public virtual async Task<ClaimsPrincipal> CreateUserPrincipalAsync(TUser user) => await ClaimsFactory.CreateAsync(user);
/// <summary>
/// Returns a flag indicating whether the specified user can sign in.
/// </summary>
/// <param name="user">The user whose sign-in status should be returned.</param>
/// <returns>
/// The task object representing the asynchronous operation, containing a flag that is true
/// if the specified user can sign-in, otherwise false.
/// </returns>
public virtual async Task<bool> CanSignInAsync(TUser user)
{
if (Options.SignIn.RequireConfirmedEmail && !(await UserManager.IsEmailConfirmedAsync(user)))
@ -72,11 +101,11 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Called to regenerate the ApplicationCookie for the user, preserving the existing
/// AuthenticationProperties like rememberMe
/// Regenerates the user's application cookie, whilst preserving the existing
/// AuthenticationProperties like rememberMe, as an asynchronous operation.
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
/// <param name="user">The user whose sign-in cookie should be refreshed.</param>
/// <returns>The task object representing the asynchronous operation.</returns>
public virtual async Task RefreshSignInAsync(TUser user)
{
var authResult = await Context.Authentication.AuthenticateAsync(IdentityOptions.ApplicationCookieAuthenticationScheme);
@ -85,11 +114,25 @@ namespace Microsoft.AspNet.Identity
await SignInAsync(user, properties, authenticationMethod);
}
/// <summary>
/// Signs in the specified <paramref name="user"/>.
/// </summary>
/// <param name="user">The user to sign-in.</param>
/// <param name="isPersistent">Flag indicating whether the sign-in cookie should persist after the browser is closed.</param>
/// <param name="authenticationMethod">Name of the method used to authenticate the user.</param>
/// <returns>The task object representing the asynchronous operation.</returns>
public virtual Task SignInAsync(TUser user, bool isPersistent, string authenticationMethod = null)
{
return SignInAsync(user, new AuthenticationProperties { IsPersistent = isPersistent }, authenticationMethod);
}
/// <summary>
/// Signs in the specified <paramref name="user"/>.
/// </summary>
/// <param name="user">The user to sign-in.</param>
/// <param name="authenticationProperties">Properties applied to the login and authentication cookie.</param>
/// <param name="authenticationMethod">Name of the method used to authenticate the user.</param>
/// <returns>The task object representing the asynchronous operation.</returns>
public virtual async Task SignInAsync(TUser user, AuthenticationProperties authenticationProperties, string authenticationMethod = null)
{
var userPrincipal = await CreateUserPrincipalAsync(user);
@ -103,6 +146,9 @@ namespace Microsoft.AspNet.Identity
authenticationProperties ?? new AuthenticationProperties());
}
/// <summary>
/// Signs the current user out of the application.
/// </summary>
public virtual void SignOut()
{
Context.Authentication.SignOut(IdentityOptions.ApplicationCookieAuthenticationScheme);
@ -110,40 +156,14 @@ namespace Microsoft.AspNet.Identity
Context.Authentication.SignOut(IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme);
}
private async Task<bool> IsLockedOut(TUser user)
{
return UserManager.SupportsUserLockout && await UserManager.IsLockedOutAsync(user);
}
private async Task<SignInResult> PreSignInCheck(TUser user)
{
if (!await CanSignInAsync(user))
{
return SignInResult.NotAllowed;
}
if (await IsLockedOut(user))
{
return SignInResult.LockedOut;
}
return null;
}
private Task ResetLockout(TUser user)
{
if (UserManager.SupportsUserLockout)
{
return UserManager.ResetAccessFailedCountAsync(user);
}
return Task.FromResult(0);
}
/// <summary>
/// Validates that the claims identity has a security stamp matching the users
/// Returns the user if it matches, null otherwise
/// Validates the security stamp for the specified <paramref name="principal"/> against
/// the persisted stamp for the <paramref name="userId"/>, as an asynchronous operation.
/// </summary>
/// <param name="identity"></param>
/// <param name="userId"></param>
/// <returns></returns>
/// <param name="principal">The principal whose stamp should be validated.</param>
/// <param name="userId">The ID for the user.</param>
/// <returns>The task object representing the asynchronous operation. The task will contain the <typeparamref name="TUser"/>
/// if the stamp matches the persisted value, otherwise it will return false.</returns>
public virtual async Task<TUser> ValidateSecurityStampAsync(ClaimsPrincipal principal, string userId)
{
var user = await UserManager.FindByIdAsync(userId);
@ -159,6 +179,16 @@ namespace Microsoft.AspNet.Identity
return null;
}
/// <summary>
/// Attempts to sign in the specified <paramref name="user"/> and <paramref name="password"/> combination
/// as an asynchronous operation.
/// </summary>
/// <param name="user">The user to sign in.</param>
/// <param name="password">The password to attempt to sign in with.</param>
/// <param name="isPersistent">Flag indicating whether the sign-in cookie should persist after the browser is closed.</param>
/// <param name="shouldLockout">Flag indicating if the user account should be locked if the sign in fails.</param>
/// <returns>The task object representing the asynchronous operation containing the <see name="SignInResult"/>
/// for the sign-in attempt.</returns>
public virtual async Task<SignInResult> PasswordSignInAsync(TUser user, string password,
bool isPersistent, bool shouldLockout)
{
@ -197,6 +227,16 @@ namespace Microsoft.AspNet.Identity
}
}
/// <summary>
/// Attempts to sign in the specified <paramref name="userName"/> and <paramref name="password"/> combination
/// as an asynchronous operation.
/// </summary>
/// <param name="userName">The user name to sign in.</param>
/// <param name="password">The password to attempt to sign in with.</param>
/// <param name="isPersistent">Flag indicating whether the sign-in cookie should persist after the browser is closed.</param>
/// <param name="shouldLockout">Flag indicating if the user account should be locked if the sign in fails.</param>
/// <returns>The task object representing the asynchronous operation containing the <see name="SignInResult"/>
/// for the sign-in attempt.</returns>
public virtual async Task<SignInResult> PasswordSignInAsync(string userName, string password,
bool isPersistent, bool shouldLockout)
{
@ -209,21 +249,15 @@ namespace Microsoft.AspNet.Identity
return await PasswordSignInAsync(user, password, isPersistent, shouldLockout);
}
private static ClaimsIdentity CreateIdentity(TwoFactorAuthenticationInfo info)
{
if (info == null)
{
return null;
}
var identity = new ClaimsIdentity(IdentityOptions.TwoFactorUserIdCookieAuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, info.UserId));
if (info.LoginProvider != null)
{
identity.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, info.LoginProvider));
}
return identity;
}
/// <summary>
/// Returns a flag indicating if the current client browser has been remembered by two factor authentication
/// for the user attempting to login, as an asynchronous operation.
/// </summary>
/// <param name="user">The user attempting to login.</param>
/// <returns>
/// The task object representing the asynchronous operation containing true if the browser has been remembered
/// for the current user.
/// </returns>
public virtual async Task<bool> IsTwoFactorClientRememberedAsync(TUser user)
{
var userId = await UserManager.GetUserIdAsync(user);
@ -231,6 +265,12 @@ namespace Microsoft.AspNet.Identity
return (result?.Principal != null && result.Principal.FindFirstValue(ClaimTypes.Name) == userId);
}
/// <summary>
/// Sets a flag on the browser to indicate the user has selected "Remember this browser" for two factor authentication purposes,
/// as an asynchronous operation.
/// </summary>
/// <param name="user">The user who choose "remember this browser".</param>
/// <returns>The task object representing the asynchronous operation.</returns>
public virtual async Task RememberTwoFactorClientAsync(TUser user)
{
var userId = await UserManager.GetUserIdAsync(user);
@ -241,12 +281,26 @@ namespace Microsoft.AspNet.Identity
new AuthenticationProperties { IsPersistent = true });
}
/// <summary>
/// Clears the "Remember this browser flag" from the current browser, as an asynchronous operation.
/// </summary>
/// <returns>The task object representing the asynchronous operation.</returns>
public virtual Task ForgetTwoFactorClientAsync()
{
Context.Authentication.SignOut(IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme);
return Task.FromResult(0);
}
/// <summary>
/// Validates the two faction sign in code and creates and signs in the user, as an asynchronous operation.
/// </summary>
/// <param name="provider">The two factor authentication provider to validate the code against.</param>
/// <param name="code">The two factor authentication code to validate.</param>
/// <param name="isPersistent">Flag indicating whether the sign-in cookie should persist after the browser is closed.</param>
/// <param name="rememberClient">Flag indicating whether the current browser should be remember, suppressing all further
/// two factor authentication prompts.</param>
/// <returns>The task object representing the asynchronous operation containing the <see name="SignInResult"/>
/// for the sign-in attempt.</returns>
public virtual async Task<SignInResult> TwoFactorSignInAsync(string provider, string code, bool isPersistent,
bool rememberClient)
{
@ -292,9 +346,10 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Returns the user who has started the two factor authentication process
/// Gets the <typeparamref name="TUser"/> for the current two factor authentication login, as an asynchronous operation.
/// </summary>
/// <returns></returns>
/// <returns>The task object representing the asynchronous operation containing the <typeparamref name="TUser"/>
/// for the sign-in attempt.</returns>
public virtual async Task<TUser> GetTwoFactorAuthenticationUserAsync()
{
var info = await RetrieveTwoFactorInfoAsync();
@ -306,6 +361,14 @@ namespace Microsoft.AspNet.Identity
return await UserManager.FindByIdAsync(info.UserId);
}
/// <summary>
/// Signs in a user via a previously registered third party login, as an asynchronous operation.
/// </summary>
/// <param name="loginProvider">The login provider to use.</param>
/// <param name="providerKey">The unique provider identifier for the user.</param>
/// <param name="isPersistent">Flag indicating whether the sign-in cookie should persist after the browser is closed.</param>
/// <returns>The task object representing the asynchronous operation containing the <see name="SignInResult"/>
/// for the sign-in attempt.</returns>
public virtual async Task<SignInResult> ExternalLoginSignInAsync(string loginProvider, string providerKey, bool isPersistent)
{
var user = await UserManager.FindByLoginAsync(loginProvider, providerKey);
@ -325,14 +388,21 @@ namespace Microsoft.AspNet.Identity
}
}
private const string LoginProviderKey = "LoginProvider";
private const string XsrfKey = "XsrfId";
/// <summary>
/// Gets a collection of <see cref="AuthenticationDescription"/>s for the known external login providers.
/// </summary>
/// <returns>A collection of <see cref="AuthenticationDescription"/>s for the known external login providers.</returns>
public virtual IEnumerable<AuthenticationDescription> GetExternalAuthenticationSchemes()
{
return Context.Authentication.GetAuthenticationSchemes().Where(d => !string.IsNullOrEmpty(d.Caption));
}
/// <summary>
/// Gets the external login information for the current login, as an asynchronous operation.
/// </summary>
/// <param name="expectedXsrf">Flag indication whether a Cross Site Request Forgery token was expected in the current request.</param>
/// <returns>The task object representing the asynchronous operation containing the <see name="ExternalLoginInfo"/>
/// for the sign-in attempt.</returns>
public virtual async Task<ExternalLoginInfo> GetExternalLoginInfoAsync(string expectedXsrf = null)
{
var auth = await Context.Authentication.AuthenticateAsync(IdentityOptions.ExternalCookieAuthenticationScheme);
@ -362,7 +432,14 @@ namespace Microsoft.AspNet.Identity
}
return new ExternalLoginInfo(auth.Principal, provider, providerKey, auth.Description.Caption);
}
/// <summary>
/// Configures the redirect URL and user identifier for the specified external login <paramref name="provider"/>.
/// </summary>
/// <param name="provider">The provider to configure.</param>
/// <param name="redirectUrl">The external login URL users should be redirected to during the login glow.</param>
/// <param name="userId">The current user's identifier, which will be used to provide CSRF protection.</param>
/// <returns>A configured <see cref="AuthenticationProperties"/>.</returns>
public virtual AuthenticationProperties ConfigureExternalAuthenticationProperties(string provider, string redirectUrl, string userId = null)
{
var properties = new AuthenticationProperties { RedirectUri = redirectUrl };
@ -374,6 +451,51 @@ namespace Microsoft.AspNet.Identity
return properties;
}
/// <summary>
/// Starts a scope for wrapping log messages, as an asynchronous operation.
/// </summary>
/// <param name="user">The current user.</param>
/// <param name="methodName">The method that called this method.</param>
/// <returns>The task object representing the asynchronous operation.</returns>
protected virtual async Task<IDisposable> BeginLoggingScopeAsync(TUser user, [CallerMemberName] string methodName = null)
{
var state = Resources.FormatLoggingResultMessageForUser(methodName, await UserManager.GetUserIdAsync(user));
return Logger?.BeginScope(state);
}
/// <summary>
/// Creates a claims principal for the specified 2fa information.
/// </summary>
/// <param name="userId">The user whose is logging in via 2fa.</param>
/// <param name="loginProvider">The 2fa provider.</param>
/// <returns>A <see cref="ClaimsPrincipal"/> containing the user 2fa information.</returns>
internal static ClaimsPrincipal StoreTwoFactorInfo(string userId, string loginProvider)
{
var identity = new ClaimsIdentity(IdentityOptions.TwoFactorUserIdCookieAuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, userId));
if (loginProvider != null)
{
identity.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, loginProvider));
}
return new ClaimsPrincipal(identity);
}
private static ClaimsIdentity CreateIdentity(TwoFactorAuthenticationInfo info)
{
if (info == null)
{
return null;
}
var identity = new ClaimsIdentity(IdentityOptions.TwoFactorUserIdCookieAuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, info.UserId));
if (info.LoginProvider != null)
{
identity.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, info.LoginProvider));
}
return identity;
}
private async Task<SignInResult> SignInOrTwoFactorAsync(TUser user, bool isPersistent, string loginProvider = null)
{
if (UserManager.SupportsUserTwoFactor &&
@ -411,22 +533,33 @@ namespace Microsoft.AspNet.Identity
return null;
}
protected virtual async Task<IDisposable> BeginLoggingScopeAsync(TUser user, [CallerMemberName] string methodName = null)
private async Task<bool> IsLockedOut(TUser user)
{
var state = Resources.FormatLoggingResultMessageForUser(methodName, await UserManager.GetUserIdAsync(user));
return Logger?.BeginScope(state);
return UserManager.SupportsUserLockout && await UserManager.IsLockedOutAsync(user);
}
internal static ClaimsPrincipal StoreTwoFactorInfo(string userId, string loginProvider)
private async Task<SignInResult> PreSignInCheck(TUser user)
{
var identity = new ClaimsIdentity(IdentityOptions.TwoFactorUserIdCookieAuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, userId));
if (loginProvider != null)
if (!await CanSignInAsync(user))
{
identity.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, loginProvider));
return SignInResult.NotAllowed;
}
return new ClaimsPrincipal(identity);
if (await IsLockedOut(user))
{
return SignInResult.LockedOut;
}
return null;
}
private Task ResetLockout(TUser user)
{
if (UserManager.SupportsUserLockout)
{
return UserManager.ResetAccessFailedCountAsync(user);
}
return Task.FromResult(0);
}
internal class TwoFactorAuthenticationInfo
{
public string UserId { get; set; }

View File

@ -3,16 +3,21 @@
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Options for configuring sign in..
/// </summary>
public class SignInOptions
{
/// <summary>
/// If set, requires a confirmed email to sign in
/// Gets or sets a flag indicating whether a confirmed email address is required to sign in.
/// </summary>
/// <value>True if a user must have a confirmed email address before they can sign in, otherwise false.</value>
public bool RequireConfirmedEmail { get; set; }
/// <summary>
/// If set, requires a confirmed phone number to sign in
/// Gets or sets a flag indicating whether a confirmed telephone number is required to sign in.
/// </summary>
/// <value>True if a user must have a confirmed telephone number before they can sign in, otherwise false.</value>
public bool RequireConfirmedPhoneNumber { get; set; }
}
}

View File

@ -6,7 +6,7 @@ using Microsoft.Framework.Logging;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Represents the result of an sign in operation
/// Represents the result of a sign-in operation.
/// </summary>
public class SignInResult
{
@ -17,59 +17,69 @@ namespace Microsoft.AspNet.Identity
private static readonly SignInResult _twoFactorRequired = new SignInResult { RequiresTwoFactor = true };
/// <summary>
/// True if the operation was successful
/// Returns a flag indication whether the sign-in was successful.
/// </summary>
/// <value>True if the sign-in was successful, otherwise false.</value>
public bool Succeeded { get; protected set; }
/// <summary>
/// True if the user is locked out
/// Returns a flag indication whether the user attempting to sign-in is locked out.
/// </summary>
/// <value>True if the user attempting to sign-in is locked out, otherwise false.</value>
public bool IsLockedOut { get; protected set; }
/// <summary>
/// True if the user is not allowed to sign in
/// Returns a flag indication whether the user attempting to sign-in is not allowed to sign-in.
/// </summary>
/// <value>True if the user attempting to sign-in is not allowed to sign-in, otherwise false.</value>
public bool IsNotAllowed { get; protected set; }
/// <summary>
/// True if the sign in requires two factor
/// Returns a flag indication whether the user attempting to sign-in requires two factor authentication.
/// </summary>
/// <value>True if the user attempting to sign-in requires two factor authentication, otherwise false.</value>
public bool RequiresTwoFactor { get; protected set; }
/// <summary>
/// Static success result
/// Returns a <see cref="SignInResult"/> that represents a successful sign-in.
/// </summary>
/// <returns></returns>
/// <returns>A <see cref="SignInResult"/> that represents a successful sign-in.</returns>
public static SignInResult Success => _success;
/// <summary>
/// Static failure result
/// Returns a <see cref="SignInResult"/> that represents a failed sign-in.
/// </summary>
/// <returns></returns>
/// <returns>A <see cref="SignInResult"/> that represents a failed sign-in.</returns>
public static SignInResult Failed => _failed;
/// <summary>
/// Static locked out result
/// Returns a <see cref="SignInResult"/> that represents a sign-in attempt that failed because
/// the user was logged out.
/// </summary>
/// <returns></returns>
/// <returns>A <see cref="SignInResult"/> that represents sign-in attempt that failed due to the
/// user being locked out.</returns>
public static SignInResult LockedOut => _lockedOut;
/// <summary>
/// Static not allowed result
/// Returns a <see cref="SignInResult"/> that represents a sign-in attempt that failed because
/// the user is not allowed to sign-in.
/// </summary>
/// <returns></returns>
/// <returns>A <see cref="SignInResult"/> that represents sign-in attempt that failed due to the
/// user is not allowed to sign-in.</returns>
public static SignInResult NotAllowed => _notAllowed;
/// <summary>
/// Static two factor required result
/// Returns a <see cref="SignInResult"/> that represents a sign-in attempt that needs two-factor
/// authentication.
/// </summary>
/// <returns></returns>
/// <returns>A <see cref="SignInResult"/> that represents sign-in attempt that needs two-factor
/// authentication.</returns>
public static SignInResult TwoFactorRequired => _twoFactorRequired;
/// <summary>
/// Returns string representation of the result.
/// Converts the value of the current <see cref="SignInResult"/> object to its equivalent string representation.
/// </summary>
/// <returns></returns>
/// <returns>A string representation of value of the current <see cref="SignInResult"/> object.</returns>
public override string ToString()
{
return IsLockedOut ? "Lockedout" :
@ -79,9 +89,9 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Returns the level at which this result should be logged
/// Gets the log level for the current <see cref="SignInResult"/> object.
/// </summary>
/// <returns></returns>
/// <returns>The log level for the current <see cref="SignInResult"/> object.</returns>
public virtual LogLevel GetLogLevel()
{
return Succeeded || RequiresTwoFactor ? LogLevel.Verbose : LogLevel.Warning;

View File

@ -6,22 +6,37 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// TokenProvider that generates time based codes using the user's security stamp
/// Represents a token provider that generates time based codes using the user's security stamp.
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TUser">The type encapsulating a user.</typeparam>
public abstract class TotpSecurityStampBasedTokenProvider<TUser> : IUserTokenProvider<TUser>
where TUser : class
{
/// <summary>
/// Gets the name of the token provider.
/// </summary>
/// <value>The name of the token provider.</value>
public abstract string Name { get; }
/// <summary>
/// Generate a token for the user using their security stamp
/// Generates a token for the specified <paramref name="ref"/> and <paramref name="purpose"/>, as an asynchronous operation.
/// </summary>
/// <param name="purpose"></param>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <returns></returns>
/// <param name="purpose">The purpose the token will be used for.</param>
/// <param name="manager">The <see cref="UserManager{TUser}"/> that can be used to retrieve user properties.</param>
/// <param name="user">The user a token should be generated for.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the token for the specified
/// <paramref name="user"/> and <paramref name="purpose"/>.
/// </returns>
/// <remarks>
/// The <paramref name="purpose"/> parameter allows a token generator to be used for multiple types of token whilst
/// insuring a token for one purpose cannot be used for another. For example if you specified a purpose of "Email"
/// and validated it with the same purpose a token with the purpose of TOTP would not pass the heck even if it was
/// for the same user.
///
/// Implementations of <see cref="IUserTokenProvider{TUser}"/> should validate that purpose is not null or empty to
/// help with token separation.
/// </remarks>
public virtual async Task<string> GenerateAsync(string purpose, UserManager<TUser> manager, TUser user)
{
if (manager == null)
@ -34,13 +49,18 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Validate the token for the user
/// Returns a flag indicating whether the specified <paramref name="token"/> is valid for the given
/// <paramref name="user"/> and <paramref name="purpose"/>, as an asynchronous operation.
/// </summary>
/// <param name="purpose"></param>
/// <param name="token"></param>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <returns></returns>
/// <param name="purpose">The purpose the token will be used for.</param>
/// <param name="token">The token to validate.</param>
/// <param name="manager">The <see cref="UserManager{TUser}"/> that can be used to retrieve user properties.</param>
/// <param name="user">The user a token should be validated for.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the a flag indicating the result
/// of validating the <paramref name="token"> for the specified </paramref><paramref name="user"/> and <paramref name="purpose"/>.
/// The task will return true if the token is valid, otherwise false.
/// </returns>
public virtual async Task<bool> ValidateAsync(string purpose, string token, UserManager<TUser> manager, TUser user)
{
if (manager == null)
@ -58,12 +78,15 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Used for entropy in the token, uses the user.Id by default
/// Returns a constant, provider and user unique modifier used for entropy in generated tokens from user information, as an asynchronous operation.
/// </summary>
/// <param name="purpose"></param>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <returns></returns>
/// <param name="purpose">The purpose the token will be generated for.</param>
/// <param name="manager">The <see cref="UserManager{TUser}"/> that can be used to retrieve user properties.</param>
/// <param name="user">The user a token should be generated for.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing a constant modifier for the specified
/// <paramref name="user"/> and <paramref name="purpose"/>.
/// </returns>
public virtual async Task<string> GetUserModifierAsync(string purpose, UserManager<TUser> manager, TUser user)
{
if (manager == null)
@ -74,6 +97,17 @@ namespace Microsoft.AspNet.Identity
return "Totp:" + purpose + ":" + userId;
}
/// <summary>
/// Returns a flag indicating whether the token provider can generate a token suitable for two factor authentication token for
/// the specified <paramref name="ref"/>.
/// </summary>
/// <param name="manager">The <see cref="UserManager{TUser}"/> that can be used to retrieve user properties.</param>
/// <param name="user">The user a token could be generated for.</param>
/// <returns>
/// The <see cref="Task"/> that represents the asynchronous operation, containing the a flag indicating if a two
/// factor token could be generated by this provider for the specified <paramref name="user"/> and <paramref name="purpose"/>.
/// The task will return true if a two factor authentication token could be generated, otherwise false.
/// </returns>
public abstract Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<TUser> manager, TUser user);
}
}

View File

@ -6,15 +6,16 @@ using System;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Normalizes via ToUpperInvariant()
/// Implements <see cref="ILookupNormalizer"/> by converting keys to their upper cased invariant culture representation.
/// </summary>
public class UpperInvariantLookupNormalizer : ILookupNormalizer
{
/// <summary>
/// Normalizes via ToUpperInvariant()
/// Returns a normalized representation of the specified <paramref name="key"/>
/// by converting keys to their upper cased invariant culture representation.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
/// <param name="key">The key to normalize.</param>
/// <returns>A normalized representation of the specified <paramref name="key"/>.</returns>
public virtual string Normalize(string key)
{
if (key == null)

View File

@ -72,10 +72,11 @@ namespace Microsoft.AspNet.Identity
public IdentityOptions Options { get; private set; }
/// <summary>
/// Creates a populated <see cref="ClaimsPrincipal"/> for the specified <paramref name="user"/>.
/// Creates a <see cref="ClaimsPrincipal"/> from an user asynchronously.
/// </summary>
/// <param name="user">The user instance to create claims on.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the started task.</returns>
/// <param name="user">The user to create a <see cref="ClaimsPrincipal"/> from.</param>
/// <param name="authenticationType">The name of the authentication method the <paramref name="user"/> was sourced from.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous creation operation, containing the created <see cref="ClaimsPrincipal"/>.</returns>
public virtual async Task<ClaimsPrincipal> CreateAsync(TUser user)
{
if (user == null)

View File

@ -4,10 +4,16 @@
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Represents a linked login for a user (i.e. a local username/password or a facebook/google account
/// Represents login information and source for a user record.
/// </summary>
public class UserLoginInfo
{
/// <summary>
/// Creates a new instance of <see cref="UserLoginInfo"/>
/// </summary>
/// <param name="loginProvider">The provider associated with this login information.</param>
/// <param name="providerKey">The unique identifier for this user provided by the login provider.</param>
/// <param name="displayName">The display name for this user provided by the login provider.</param>
public UserLoginInfo(string loginProvider, string providerKey, string displayName)
{
LoginProvider = loginProvider;
@ -16,18 +22,31 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// Provider for the linked login, i.e. Local, Facebook, Google, etc.
/// Gets or sets the provider for this instance of <see cref="UserLoginInfo"/>.
/// </summary>
/// <value>The provider for the this instance of <see cref="UserLoginInfo"/></value>
/// <remarks>
/// Examples of the provider may be Local, Facebook, Google, etc.
/// </remarks>
public string LoginProvider { get; set; }
/// <summary>
/// Key for the linked login at the provider
/// Gets or sets the unique identifier for the user identity user provided by the login provider.
/// </summary>
/// <value>
/// The unique identifier for the user identity user provided by the login provider.
/// </value>
/// <remarks>
/// This would be unique per provider, examples may be @microsoft as a Twitter provider key.
/// </remarks>
public string ProviderKey { get; set; }
/// <summary>
/// Display name for the provider
/// Gets or sets the display name for the provider.
/// </summary>
/// <value>
/// The display name for the provider.
/// </value>
public string ProviderDisplayName { get; set; }
}
}

File diff suppressed because it is too large Load Diff

View File

@ -47,8 +47,7 @@ namespace Microsoft.AspNet.Identity
/// Gets or sets a flag indicating whether the application requires unique emails for its users.
/// </summary>
/// <value>
/// A flag indicating whether the application requires unique emails for its users.
/// This will be true if the application requires each user to have their own, unique email, otherwise false.
/// True if the application requires each user to have their own, unique email, otherwise false.
/// </value>
public bool RequireUniqueEmail { get; set; }
}

View File

@ -15,23 +15,30 @@ namespace Microsoft.AspNet.Identity
/// <summary>
/// Provides validation services for user classes.
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TRole">The type encapsulating a user.</typeparam>
public class UserValidator<TUser> : IUserValidator<TUser> where TUser : class
{
/// <summary>
/// Creates a new instance of <see cref="UserValidator{TUser}"/>/
/// </summary>
/// <param name="errors">The <see cref="IdentityErrorDescriber"/> used to provider error messages.</param>
public UserValidator(IdentityErrorDescriber errors = null)
{
Describer = errors ?? new IdentityErrorDescriber();
}
/// <summary>
/// Gets the <see cref="IdentityErrorDescriber"/> used to provider error messages for the current <see cref="UserValidator{TUser}"/>.
/// </summary>
/// <value>Yhe <see cref="IdentityErrorDescriber"/> used to provider error messages for the current <see cref="UserValidator{TUser}"/>.</value>
public IdentityErrorDescriber Describer { get; private set; }
/// <summary>
/// Validates a user before saving
/// Validates the specified <paramref name="user"/> as an asynchronous operation.
/// </summary>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <param name="manager">The <see cref="UserManager{TUser}"/> that can be used to retrieve user properties.</param>
/// <param name="user">The user to validate.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/> of the validation operation.</returns>
public virtual async Task<IdentityResult> ValidateAsync(UserManager<TUser> manager, TUser user)
{
if (manager == null)