// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Security.Claims; using System.Threading.Tasks; using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Identity { /// /// Provides methods to create a claims principal for a given user. /// /// The type used to represent a user. public class UserClaimsPrincipalFactory : IUserClaimsPrincipalFactory where TUser : class { /// /// Initializes a new instance of the class. /// /// The to retrieve user information from. /// The configured . public UserClaimsPrincipalFactory( UserManager userManager, IOptions optionsAccessor) { if (userManager == null) { throw new ArgumentNullException(nameof(userManager)); } if (optionsAccessor == null || optionsAccessor.Value == null) { throw new ArgumentNullException(nameof(optionsAccessor)); } UserManager = userManager; Options = optionsAccessor.Value; } /// /// Gets the for this factory. /// /// /// The current for this factory instance. /// public UserManager UserManager { get; private set; } /// /// Gets the for this factory. /// /// /// The current for this factory instance. /// public IdentityOptions Options { get; private set; } /// /// Creates a from an user asynchronously. /// /// The user to create a from. /// The that represents the asynchronous creation operation, containing the created . public virtual async Task CreateAsync(TUser user) { if (user == null) { throw new ArgumentNullException(nameof(user)); } var id = await GenerateClaimsAsync(user); return new ClaimsPrincipal(id); } /// /// Generate the claims for a user. /// /// The user to create a from. /// The that represents the asynchronous creation operation, containing the created . protected virtual async Task GenerateClaimsAsync(TUser user) { var userId = await UserManager.GetUserIdAsync(user); var userName = await UserManager.GetUserNameAsync(user); 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.SupportsUserSecurityStamp) { id.AddClaim(new Claim(Options.ClaimsIdentity.SecurityStampClaimType, await UserManager.GetSecurityStampAsync(user))); } if (UserManager.SupportsUserClaim) { id.AddClaims(await UserManager.GetClaimsAsync(user)); } return id; } } /// /// Provides methods to create a claims principal for a given user. /// /// The type used to represent a user. /// The type used to represent a role. public class UserClaimsPrincipalFactory : UserClaimsPrincipalFactory where TUser : class where TRole : class { /// /// Initializes a new instance of the class. /// /// The to retrieve user information from. /// The to retrieve a user's roles from. /// The configured . public UserClaimsPrincipalFactory(UserManager userManager, RoleManager roleManager, IOptions options) : base(userManager, options) { if (roleManager == null) { throw new ArgumentNullException(nameof(roleManager)); } RoleManager = roleManager; } /// /// Gets the for this factory. /// /// /// The current for this factory instance. /// public RoleManager RoleManager { get; private set; } /// /// Generate the claims for a user. /// /// The user to create a from. /// The that represents the asynchronous creation operation, containing the created . protected override async Task GenerateClaimsAsync(TUser user) { var id = await base.GenerateClaimsAsync(user); if (UserManager.SupportsUserRole) { var roles = await UserManager.GetRolesAsync(user); foreach (var roleName in roles) { id.AddClaim(new Claim(Options.ClaimsIdentity.RoleClaimType, roleName)); if (RoleManager.SupportsRoleClaims) { var role = await RoleManager.FindByNameAsync(roleName); if (role != null) { id.AddClaims(await RoleManager.GetClaimsAsync(role)); } } } } return id; } } }