Browse Source

Trim identity (#42675)

James Newton-King 3 years ago
parent
commit
eed7089fba

+ 4 - 0
eng/TrimmableProjects.props

@@ -31,6 +31,9 @@
     <TrimmableProject Include="Microsoft.AspNetCore.Routing" />
     <TrimmableProject Include="Microsoft.AspNetCore.WebUtilities" />
     <TrimmableProject Include="Microsoft.AspNetCore.Html.Abstractions" />
+    <TrimmableProject Include="Microsoft.AspNetCore.Identity" />
+    <TrimmableProject Include="Microsoft.Extensions.Identity.Core" />
+    <TrimmableProject Include="Microsoft.Extensions.Identity.Stores" />
     <TrimmableProject Include="Microsoft.AspNetCore.Connections.Abstractions" />
     <TrimmableProject Include="Microsoft.AspNetCore.Server.HttpSys" />
     <TrimmableProject Include="Microsoft.AspNetCore.Server.IISIntegration" />
@@ -88,6 +91,7 @@
     <TrimmableProject Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" />
     <TrimmableProject Include="Microsoft.AspNetCore.Components.WebAssembly" />
     <TrimmableProject Include="Microsoft.AspNetCore.Components.Web" />
+    <TrimmableProject Include="Microsoft.Extensions.Localization.Abstractions" />
     <TrimmableProject Include="Microsoft.Extensions.ObjectPool" />
     <TrimmableProject Include="Microsoft.JSInterop" />
     <TrimmableProject Include="Microsoft.Extensions.WebEncoders" />

+ 2 - 1
src/Identity/Core/src/IdentityBuilderExtensions.cs

@@ -1,6 +1,7 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using System.Diagnostics.CodeAnalysis;
 using Microsoft.Extensions.DependencyInjection;
 
 namespace Microsoft.AspNetCore.Identity;
@@ -55,7 +56,7 @@ public static class IdentityBuilderExtensions
     /// <typeparam name="TSignInManager">The type of the sign in manager to add.</typeparam>
     /// <param name="builder">The current <see cref="IdentityBuilder"/> instance.</param>
     /// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
-    public static IdentityBuilder AddSignInManager<TSignInManager>(this IdentityBuilder builder) where TSignInManager : class
+    public static IdentityBuilder AddSignInManager<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TSignInManager>(this IdentityBuilder builder) where TSignInManager : class
     {
         builder.AddSignInManagerDeps();
         var managerType = typeof(SignInManager<>).MakeGenericType(builder.UserType);

+ 3 - 2
src/Identity/Core/src/IdentityServiceCollectionExtensions.cs

@@ -1,6 +1,7 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using System.Diagnostics.CodeAnalysis;
 using Microsoft.AspNetCore.Authentication.Cookies;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Identity;
@@ -20,7 +21,7 @@ public static class IdentityServiceCollectionExtensions
     /// <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>(
+    public static IdentityBuilder AddIdentity<TUser, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TRole>(
         this IServiceCollection services)
         where TUser : class
         where TRole : class
@@ -34,7 +35,7 @@ public static class IdentityServiceCollectionExtensions
     /// <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>(
+    public static IdentityBuilder AddIdentity<TUser, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TRole>(
         this IServiceCollection services,
         Action<IdentityOptions> setupAction)
         where TUser : class

+ 4 - 0
src/Identity/Core/src/Microsoft.AspNetCore.Identity.csproj

@@ -7,11 +7,15 @@
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <PackageTags>aspnetcore;identity;membership</PackageTags>
     <IsPackable>false</IsPackable>
+    <IsTrimmable>true</IsTrimmable>
   </PropertyGroup>
 
   <ItemGroup>
     <Reference Include="Microsoft.AspNetCore.Authentication.Cookies" />
     <Reference Include="Microsoft.Extensions.Identity.Core" />
+
+    <Compile Include="$(SharedSourceRoot)TrimmingAttributes.cs" LinkBase="Shared"
+      Condition="'$(TargetFramework)' != '$(DefaultNetCoreTargetFramework)'" />
   </ItemGroup>
 
 </Project>

+ 2 - 1
src/Identity/EntityFrameworkCore/src/UserStore.cs

@@ -1,6 +1,7 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Linq;
 using System.Security.Claims;
@@ -89,7 +90,7 @@ public class UserStore<TUser, TRole, TContext, TKey> : UserStore<TUser, TRole, T
 /// <typeparam name="TUserLogin">The type representing a user external login.</typeparam>
 /// <typeparam name="TUserToken">The type representing a user token.</typeparam>
 /// <typeparam name="TRoleClaim">The type representing a role claim.</typeparam>
-public class UserStore<TUser, TRole, TContext, TKey, TUserClaim, TUserRole, TUserLogin, TUserToken, TRoleClaim> :
+public class UserStore<TUser, TRole, TContext, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TKey, TUserClaim, TUserRole, TUserLogin, TUserToken, TRoleClaim> :
     UserStoreBase<TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TUserToken, TRoleClaim>,
     IProtectedUserStore<TUser>
     where TUser : IdentityUser<TKey>

+ 18 - 16
src/Identity/Extensions.Core/src/IdentityBuilder.cs

@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System;
+using System.Diagnostics.CodeAnalysis;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.DependencyInjection.Extensions;
 using Microsoft.Extensions.Identity.Core;
@@ -30,7 +31,7 @@ public class IdentityBuilder
     /// <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) : this(user, services)
+    public IdentityBuilder(Type user, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type role, IServiceCollection services) : this(user, services)
         => RoleType = role;
 
     /// <summary>
@@ -47,6 +48,7 @@ public class IdentityBuilder
     /// <value>
     /// The <see cref="Type"/> used for roles.
     /// </value>
+    [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
     public Type? RoleType { get; private set; }
 
     /// <summary>
@@ -57,7 +59,7 @@ public class IdentityBuilder
     /// </value>
     public IServiceCollection Services { get; }
 
-    private IdentityBuilder AddScoped(Type serviceType, Type concreteType)
+    private IdentityBuilder AddScoped(Type serviceType, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type concreteType)
     {
         Services.AddScoped(serviceType, concreteType);
         return this;
@@ -68,7 +70,7 @@ public class IdentityBuilder
     /// </summary>
     /// <typeparam name="TValidator">The user validator type.</typeparam>
     /// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
-    public virtual IdentityBuilder AddUserValidator<TValidator>() where TValidator : class
+    public virtual IdentityBuilder AddUserValidator<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TValidator>() where TValidator : class
         => AddScoped(typeof(IUserValidator<>).MakeGenericType(UserType), typeof(TValidator));
 
     /// <summary>
@@ -76,7 +78,7 @@ public class IdentityBuilder
     /// </summary>
     /// <typeparam name="TFactory">The type of the claims principal factory.</typeparam>
     /// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
-    public virtual IdentityBuilder AddClaimsPrincipalFactory<TFactory>() where TFactory : class
+    public virtual IdentityBuilder AddClaimsPrincipalFactory<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TFactory>() where TFactory : class
         => AddScoped(typeof(IUserClaimsPrincipalFactory<>).MakeGenericType(UserType), typeof(TFactory));
 
     /// <summary>
@@ -84,7 +86,7 @@ public class IdentityBuilder
     /// </summary>
     /// <typeparam name="TDescriber">The type of the error describer.</typeparam>
     /// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
-    public virtual IdentityBuilder AddErrorDescriber<TDescriber>() where TDescriber : IdentityErrorDescriber
+    public virtual IdentityBuilder AddErrorDescriber<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TDescriber>() where TDescriber : IdentityErrorDescriber
     {
         Services.AddScoped<IdentityErrorDescriber, TDescriber>();
         return this;
@@ -95,7 +97,7 @@ public class IdentityBuilder
     /// </summary>
     /// <typeparam name="TValidator">The validator type used to validate passwords.</typeparam>
     /// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
-    public virtual IdentityBuilder AddPasswordValidator<TValidator>() where TValidator : class
+    public virtual IdentityBuilder AddPasswordValidator<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TValidator>() where TValidator : class
         => AddScoped(typeof(IPasswordValidator<>).MakeGenericType(UserType), typeof(TValidator));
 
     /// <summary>
@@ -103,7 +105,7 @@ public class IdentityBuilder
     /// </summary>
     /// <typeparam name="TStore">The user store type.</typeparam>
     /// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
-    public virtual IdentityBuilder AddUserStore<TStore>() where TStore : class
+    public virtual IdentityBuilder AddUserStore<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TStore>() where TStore : class
         => AddScoped(typeof(IUserStore<>).MakeGenericType(UserType), typeof(TStore));
 
     /// <summary>
@@ -112,7 +114,7 @@ public class IdentityBuilder
     /// <typeparam name="TProvider">The type of the token provider to add.</typeparam>
     /// <param name="providerName">The name of the provider to add.</param>
     /// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
-    public virtual IdentityBuilder AddTokenProvider<TProvider>(string providerName) where TProvider : class
+    public virtual IdentityBuilder AddTokenProvider<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TProvider>(string providerName) where TProvider : class
         => AddTokenProvider(providerName, typeof(TProvider));
 
     /// <summary>
@@ -121,7 +123,7 @@ public class IdentityBuilder
     /// <param name="providerName">The name of the provider to add.</param>
     /// <param name="provider">The type of the <see cref="IUserTwoFactorTokenProvider{TUser}"/> to add.</param>
     /// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
-    public virtual IdentityBuilder AddTokenProvider(string providerName, Type provider)
+    public virtual IdentityBuilder AddTokenProvider(string providerName, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type provider)
     {
         if (!typeof(IUserTwoFactorTokenProvider<>).MakeGenericType(UserType).IsAssignableFrom(provider))
         {
@@ -140,7 +142,7 @@ public class IdentityBuilder
     /// </summary>
     /// <typeparam name="TUserManager">The type of the user manager to add.</typeparam>
     /// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
-    public virtual IdentityBuilder AddUserManager<TUserManager>() where TUserManager : class
+    public virtual IdentityBuilder AddUserManager<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TUserManager>() where TUserManager : class
     {
         var userManagerType = typeof(UserManager<>).MakeGenericType(UserType);
         var customType = typeof(TUserManager);
@@ -160,7 +162,7 @@ public class IdentityBuilder
     /// </summary>
     /// <typeparam name="TRole">The role type.</typeparam>
     /// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
-    public virtual IdentityBuilder AddRoles<TRole>() where TRole : class
+    public virtual IdentityBuilder AddRoles<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TRole>() where TRole : class
     {
         RoleType = typeof(TRole);
         AddRoleValidator<RoleValidator<TRole>>();
@@ -174,7 +176,7 @@ public class IdentityBuilder
     /// </summary>
     /// <typeparam name="TRole">The role validator type.</typeparam>
     /// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
-    public virtual IdentityBuilder AddRoleValidator<TRole>() where TRole : class
+    public virtual IdentityBuilder AddRoleValidator<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TRole>() where TRole : class
     {
         if (RoleType == null)
         {
@@ -189,7 +191,7 @@ public class IdentityBuilder
     /// <typeparam name="TProtector">The personal data protector type.</typeparam>
     /// <typeparam name="TKeyRing">The personal data protector key ring type.</typeparam>
     /// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
-    public virtual IdentityBuilder AddPersonalDataProtection<TProtector, TKeyRing>()
+    public virtual IdentityBuilder AddPersonalDataProtection<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TProtector, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TKeyRing>()
         where TProtector : class, ILookupProtector
         where TKeyRing : class, ILookupProtectorKeyRing
     {
@@ -204,7 +206,7 @@ public class IdentityBuilder
     /// </summary>
     /// <typeparam name="TStore">The role store.</typeparam>
     /// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
-    public virtual IdentityBuilder AddRoleStore<TStore>() where TStore : class
+    public virtual IdentityBuilder AddRoleStore<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TStore>() where TStore : class
     {
         if (RoleType == null)
         {
@@ -218,7 +220,7 @@ public class IdentityBuilder
     /// </summary>
     /// <typeparam name="TRoleManager">The type of the role manager to add.</typeparam>
     /// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
-    public virtual IdentityBuilder AddRoleManager<TRoleManager>() where TRoleManager : class
+    public virtual IdentityBuilder AddRoleManager<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TRoleManager>() where TRoleManager : class
     {
         if (RoleType == null)
         {
@@ -242,6 +244,6 @@ public class IdentityBuilder
     /// </summary>
     /// <typeparam name="TUserConfirmation">The type of the user confirmation to add.</typeparam>
     /// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
-    public virtual IdentityBuilder AddUserConfirmation<TUserConfirmation>() where TUserConfirmation : class
+    public virtual IdentityBuilder AddUserConfirmation<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TUserConfirmation>() where TUserConfirmation : class
         => AddScoped(typeof(IUserConfirmation<>).MakeGenericType(UserType), typeof(TUserConfirmation));
 }

+ 5 - 1
src/Identity/Extensions.Core/src/Microsoft.Extensions.Identity.Core.csproj

@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
     <Description>ASP.NET Core Identity is the membership system for building ASP.NET Core web applications, including membership, login, and user data. ASP.NET Core Identity allows you to add login features to your application and makes it easy to customize data about the logged in user.</Description>
@@ -7,12 +7,16 @@
     <IsAspNetCoreApp>true</IsAspNetCoreApp>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <PackageTags>aspnetcore;identity;membership</PackageTags>
+    <IsTrimmable>true</IsTrimmable>
   </PropertyGroup>
 
   <ItemGroup>
     <Reference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" />
     <Reference Include="Microsoft.Extensions.Logging" />
     <Reference Include="Microsoft.Extensions.Options" />
+
+    <Compile Include="$(SharedSourceRoot)TrimmingAttributes.cs" LinkBase="Shared"
+      Condition="'$(TargetFramework)' != '$(DefaultNetCoreTargetFramework)'" />
   </ItemGroup>
 
   <ItemGroup

+ 4 - 0
src/Identity/Extensions.Stores/src/Microsoft.Extensions.Identity.Stores.csproj

@@ -7,12 +7,16 @@
     <IsAspNetCoreApp>true</IsAspNetCoreApp>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <PackageTags>aspnetcore;identity;membership</PackageTags>
+    <IsTrimmable>true</IsTrimmable>
   </PropertyGroup>
 
   <ItemGroup>
     <Reference Include="Microsoft.Extensions.Caching.Abstractions" />
     <Reference Include="Microsoft.Extensions.Logging" />
     <Reference Include="Microsoft.Extensions.Identity.Core" />
+
+    <Compile Include="$(SharedSourceRoot)TrimmingAttributes.cs" LinkBase="Shared"
+      Condition="'$(TargetFramework)' != '$(DefaultNetCoreTargetFramework)'" />
   </ItemGroup>
 
 </Project>

+ 3 - 1
src/Identity/Extensions.Stores/src/RoleStoreBase.cs

@@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Identity;
 /// <typeparam name="TKey">The type of the primary key for a role.</typeparam>
 /// <typeparam name="TUserRole">The type of the class representing a user role.</typeparam>
 /// <typeparam name="TRoleClaim">The type of the class representing a role claim.</typeparam>
-public abstract class RoleStoreBase<TRole, TKey, TUserRole, TRoleClaim> :
+public abstract class RoleStoreBase<TRole, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TKey, TUserRole, TRoleClaim> :
     IQueryableRoleStore<TRole>,
     IRoleClaimStore<TRole>
     where TRole : IdentityRole<TKey>
@@ -130,6 +130,8 @@ public abstract class RoleStoreBase<TRole, TKey, TUserRole, TRoleClaim> :
     /// </summary>
     /// <param name="id">The id to convert.</param>
     /// <returns>An instance of <typeparamref name="TKey"/> representing the provided <paramref name="id"/>.</returns>
+    [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code",
+        Justification = "TKey is annoated with RequiresUnreferencedCodeAttribute.All.")]
     public virtual TKey? ConvertIdFromString(string? id)
     {
         if (id == null)

+ 4 - 2
src/Identity/Extensions.Stores/src/UserStoreBase.cs

@@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Identity;
 /// <typeparam name="TUserClaim">The type representing a claim.</typeparam>
 /// <typeparam name="TUserLogin">The type representing a user external login.</typeparam>
 /// <typeparam name="TUserToken">The type representing a user token.</typeparam>
-public abstract class UserStoreBase<TUser, TKey, TUserClaim, TUserLogin, TUserToken> :
+public abstract class UserStoreBase<TUser, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TKey, TUserClaim, TUserLogin, TUserToken> :
     IUserLoginStore<TUser>,
     IUserClaimStore<TUser>,
     IUserPasswordStore<TUser>,
@@ -237,6 +237,8 @@ public abstract class UserStoreBase<TUser, TKey, TUserClaim, TUserLogin, TUserTo
     /// </summary>
     /// <param name="id">The id to convert.</param>
     /// <returns>An instance of <typeparamref name="TKey"/> representing the provided <paramref name="id"/>.</returns>
+    [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code",
+        Justification = "TKey is annoated with RequiresUnreferencedCodeAttribute.All.")]
     public virtual TKey? ConvertIdFromString(string? id)
     {
         if (id == null)
@@ -1085,7 +1087,7 @@ public abstract class UserStoreBase<TUser, TKey, TUserClaim, TUserLogin, TUserTo
 /// <typeparam name="TUserLogin">The type representing a user external login.</typeparam>
 /// <typeparam name="TUserToken">The type representing a user token.</typeparam>
 /// <typeparam name="TRoleClaim">The type representing a role claim.</typeparam>
-public abstract class UserStoreBase<TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TUserToken, TRoleClaim> :
+public abstract class UserStoreBase<TUser, TRole, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TKey, TUserClaim, TUserRole, TUserLogin, TUserToken, TRoleClaim> :
     UserStoreBase<TUser, TKey, TUserClaim, TUserLogin, TUserToken>,
     IUserRoleStore<TUser>
     where TUser : IdentityUser<TKey>

+ 2 - 1
src/Localization/Abstractions/src/Microsoft.Extensions.Localization.Abstractions.csproj

@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
     <Product>Microsoft .NET Extensions</Product>
@@ -12,6 +12,7 @@ Microsoft.Extensions.Localization.IStringLocalizer&lt;T&gt;</Description>
     <PackageTags>localization</PackageTags>
     <IsAspNetCoreApp>true</IsAspNetCoreApp>
     <Nullable>enable</Nullable>
+    <IsTrimmable>true</IsTrimmable>
   </PropertyGroup>
 
 </Project>

+ 4 - 0
src/Tools/Tools.slnf

@@ -38,7 +38,11 @@
       "src\\Http\\Routing.Abstractions\\src\\Microsoft.AspNetCore.Routing.Abstractions.csproj",
       "src\\Http\\Routing\\src\\Microsoft.AspNetCore.Routing.csproj",
       "src\\Http\\WebUtilities\\src\\Microsoft.AspNetCore.WebUtilities.csproj",
+      "src\\Identity\\Core\\src\\Microsoft.AspNetCore.Identity.csproj",
+      "src\\Identity\\Extensions.Core\\src\\Microsoft.Extensions.Identity.Core.csproj",
+      "src\\Identity\\Extensions.Stores\\src\\Microsoft.Extensions.Identity.Stores.csproj",
       "src\\JSInterop\\Microsoft.JSInterop\\src\\Microsoft.JSInterop.csproj",
+      "src\\Localization\\Abstractions\\src\\Microsoft.Extensions.Localization.Abstractions.csproj",
       "src\\Middleware\\CORS\\src\\Microsoft.AspNetCore.Cors.csproj",
       "src\\Middleware\\ConcurrencyLimiter\\src\\Microsoft.AspNetCore.ConcurrencyLimiter.csproj",
       "src\\Middleware\\Diagnostics.Abstractions\\src\\Microsoft.AspNetCore.Diagnostics.Abstractions.csproj",