| File: UserClaimsPrincipalFactory.cs | Web Access |
| Project: src\aspnetcore\src\Identity\Extensions.Core\src\Microsoft.Extensions.Identity.Core.csproj (Microsoft.Extensions.Identity.Core) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Shared; using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Identity; /// <summary> /// Provides methods to create a claims principal for a given user. /// </summary> /// <typeparam name="TUser">The type used to represent a user.</typeparam> public class UserClaimsPrincipalFactory<TUser> : IUserClaimsPrincipalFactory<TUser> where TUser : class { /// <summary> /// Initializes a new instance of the <see cref="UserClaimsPrincipalFactory{TUser}"/> class. /// </summary> /// <param name="userManager">The <see cref="UserManager{TUser}"/> to retrieve user information from.</param> /// <param name="optionsAccessor">The configured <see cref="IdentityOptions"/>.</param> public UserClaimsPrincipalFactory( UserManager<TUser> userManager, IOptions<IdentityOptions> optionsAccessor) { ArgumentNullThrowHelper.ThrowIfNull(userManager); if (optionsAccessor == null || optionsAccessor.Value == null) { ArgumentNullThrowHelper.ThrowIfNull(optionsAccessor); throw new ArgumentException($"{nameof(optionsAccessor)} cannot wrap a null value.", nameof(optionsAccessor)); } UserManager = userManager; Options = optionsAccessor.Value; } /// <summary> /// Gets the <see cref="UserManager{TUser}"/> for this factory. /// </summary> /// <value> /// The current <see cref="UserManager{TUser}"/> for this factory instance. /// </value> public UserManager<TUser> UserManager { get; private set; } /// <summary> /// Gets the <see cref="IdentityOptions"/> for this factory. /// </summary> /// <value> /// The current <see cref="IdentityOptions"/> for this factory instance. /// </value> public IdentityOptions Options { get; private set; } /// <summary> /// Creates a <see cref="ClaimsPrincipal"/> from an user asynchronously. /// </summary> /// <param name="user">The user to create a <see cref="ClaimsPrincipal"/> 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) { ArgumentNullThrowHelper.ThrowIfNull(user); var id = await GenerateClaimsAsync(user).ConfigureAwait(false); return new ClaimsPrincipal(id); } /// <summary> /// Generate the claims for a user. /// </summary> /// <param name="user">The user to create a <see cref="ClaimsIdentity"/> from.</param> /// <returns>The <see cref="Task"/> that represents the asynchronous creation operation, containing the created <see cref="ClaimsIdentity"/>.</returns> protected virtual async Task<ClaimsIdentity> GenerateClaimsAsync(TUser user) { var userId = await UserManager.GetUserIdAsync(user).ConfigureAwait(false); var userName = await UserManager.GetUserNameAsync(user).ConfigureAwait(false); var id = new ClaimsIdentity("Identity.Application", // REVIEW: Used to match Application scheme Options.ClaimsIdentity.UserNameClaimType, Options.ClaimsIdentity.RoleClaimType); id.AddClaim(new Claim(Options.ClaimsIdentity.UserIdClaimType, userId)); id.AddClaim(new Claim(Options.ClaimsIdentity.UserNameClaimType, userName!)); if (UserManager.SupportsUserEmail) { var email = await UserManager.GetEmailAsync(user).ConfigureAwait(false); if (!string.IsNullOrEmpty(email)) { id.AddClaim(new Claim(Options.ClaimsIdentity.EmailClaimType, email)); } } if (UserManager.SupportsUserSecurityStamp) { id.AddClaim(new Claim(Options.ClaimsIdentity.SecurityStampClaimType, await UserManager.GetSecurityStampAsync(user).ConfigureAwait(false))); } if (UserManager.SupportsUserClaim) { id.AddClaims(await UserManager.GetClaimsAsync(user).ConfigureAwait(false)); } return id; } } /// <summary> /// Provides methods to create a claims principal for a given user. /// </summary> /// <typeparam name="TUser">The type used to represent a user.</typeparam> /// <typeparam name="TRole">The type used to represent a role.</typeparam> public class UserClaimsPrincipalFactory<TUser, TRole> : UserClaimsPrincipalFactory<TUser> where TUser : class where TRole : class { /// <summary> /// Initializes a new instance of the <see cref="UserClaimsPrincipalFactory{TUser, TRole}"/> class. /// </summary> /// <param name="userManager">The <see cref="UserManager{TUser}"/> to retrieve user information from.</param> /// <param name="roleManager">The <see cref="RoleManager{TRole}"/> to retrieve a user's roles from.</param> /// <param name="options">The configured <see cref="IdentityOptions"/>.</param> public UserClaimsPrincipalFactory(UserManager<TUser> userManager, RoleManager<TRole> roleManager, IOptions<IdentityOptions> options) : base(userManager, options) { ArgumentNullThrowHelper.ThrowIfNull(roleManager); RoleManager = roleManager; } /// <summary> /// Gets the <see cref="RoleManager{TRole}"/> for this factory. /// </summary> /// <value> /// The current <see cref="RoleManager{TRole}"/> for this factory instance. /// </value> public RoleManager<TRole> RoleManager { get; private set; } /// <summary> /// Generate the claims for a user. /// </summary> /// <param name="user">The user to create a <see cref="ClaimsIdentity"/> from.</param> /// <returns>The <see cref="Task"/> that represents the asynchronous creation operation, containing the created <see cref="ClaimsIdentity"/>.</returns> protected override async Task<ClaimsIdentity> GenerateClaimsAsync(TUser user) { var id = await base.GenerateClaimsAsync(user).ConfigureAwait(false); if (UserManager.SupportsUserRole) { var roles = await UserManager.GetRolesAsync(user).ConfigureAwait(false); foreach (var roleName in roles) { id.AddClaim(new Claim(Options.ClaimsIdentity.RoleClaimType, roleName)); if (RoleManager.SupportsRoleClaims) { var role = await RoleManager.FindByNameAsync(roleName).ConfigureAwait(false); if (role != null) { id.AddClaims(await RoleManager.GetClaimsAsync(role).ConfigureAwait(false)); } } } } return id; } }