Split Auth into AddIdentityCookies (#1442)

This commit is contained in:
Hao Kung 2018-03-13 13:11:29 -07:00 committed by GitHub
parent 0ef83207d4
commit efe0c6be7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 249 additions and 40 deletions

View File

@ -965,4 +965,4 @@ Global
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B3F2A592-CCE0-40C2-8CA4-7B1293DED874} SolutionGuid = {B3F2A592-CCE0-40C2-8CA4-7B1293DED874}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@ -2,7 +2,6 @@ using IdentitySample.DefaultUI.Data;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@ -33,14 +32,23 @@ namespace IdentitySample.DefaultUI
options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
x => x.MigrationsAssembly("IdentitySample.DefaultUI"))); x => x.MigrationsAssembly("IdentitySample.DefaultUI")));
services.AddIdentity<ApplicationUser, IdentityRole>(o => o.Stores.MaxLengthForKeys = 128)
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultUI()
.AddDefaultTokenProviders();
services.AddMvc(); services.AddMvc();
services.AddIdentityCore<ApplicationUser>(o => o.Stores.MaxLengthForKeys = 128)
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultUI()
.AddDefaultTokenProviders();
services.AddAuthentication(o =>
{
o.DefaultScheme = IdentityConstants.ApplicationScheme;
o.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddIdentityCookies(o => { });
} }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{ {

View File

@ -8,6 +8,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\EF\Microsoft.AspNetCore.Identity.EntityFrameworkCore.csproj" /> <ProjectReference Include="..\..\src\EF\Microsoft.AspNetCore.Identity.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\src\Identity\Microsoft.AspNetCore.Identity.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -32,11 +32,20 @@ namespace IdentitySample
services.AddDbContext<ApplicationDbContext>(options => services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>() services.AddMvc();
services.AddIdentityCore<ApplicationUser>()
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>() .AddEntityFrameworkStores<ApplicationDbContext>()
.AddSignInManager()
.AddDefaultTokenProviders(); .AddDefaultTokenProviders();
services.AddMvc(); services.AddAuthentication(o =>
{
o.DefaultScheme = IdentityConstants.ApplicationScheme;
o.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddIdentityCookies(o => { });
// Add application services. // Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>(); services.AddTransient<IEmailSender, AuthMessageSender>();

View File

@ -12,6 +12,15 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
public static class IdentityServiceCollectionExtensions public static class IdentityServiceCollectionExtensions
{ {
/// <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>
/// <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 AddIdentityCore<TUser>(this IServiceCollection services) where TUser : class
=> services.AddIdentityCore<TUser>(o => { });
/// <summary> /// <summary>
/// Adds and configures the identity system for the specified User and Role types. /// Adds and configures the identity system for the specified User and Role types.
/// </summary> /// </summary>

View File

@ -31,6 +31,26 @@ namespace Microsoft.AspNetCore.Identity
.AddTokenProvider(TokenOptions.DefaultAuthenticatorProvider, authenticatorProviderType); .AddTokenProvider(TokenOptions.DefaultAuthenticatorProvider, authenticatorProviderType);
} }
private static void AddSignInManagerDeps(this IdentityBuilder builder)
{
builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped(typeof(ISecurityStampValidator), typeof(SecurityStampValidator<>).MakeGenericType(builder.UserType));
builder.Services.AddScoped(typeof(ITwoFactorSecurityStampValidator), typeof(TwoFactorSecurityStampValidator<>).MakeGenericType(builder.UserType));
}
/// <summary>
/// Adds a <see cref="SignInManager{TUser}"/> for the <seealso cref="IdentityBuilder.UserType"/>.
/// </summary>
/// <param name="builder">The current <see cref="IdentityBuilder"/> instance.</param>
/// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
public static IdentityBuilder AddSignInManager(this IdentityBuilder builder)
{
builder.AddSignInManagerDeps();
var managerType = typeof(SignInManager<>).MakeGenericType(builder.UserType);
builder.Services.AddScoped(managerType);
return builder;
}
/// <summary> /// <summary>
/// Adds a <see cref="SignInManager{TUser}"/> for the <seealso cref="IdentityBuilder.UserType"/>. /// Adds a <see cref="SignInManager{TUser}"/> for the <seealso cref="IdentityBuilder.UserType"/>.
/// </summary> /// </summary>
@ -39,8 +59,8 @@ namespace Microsoft.AspNetCore.Identity
/// <returns>The current <see cref="IdentityBuilder"/> instance.</returns> /// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
public static IdentityBuilder AddSignInManager<TSignInManager>(this IdentityBuilder builder) where TSignInManager : class public static IdentityBuilder AddSignInManager<TSignInManager>(this IdentityBuilder builder) where TSignInManager : class
{ {
builder.AddSignInManagerDeps();
var managerType = typeof(SignInManager<>).MakeGenericType(builder.UserType); var managerType = typeof(SignInManager<>).MakeGenericType(builder.UserType);
var customType = typeof(TSignInManager); var customType = typeof(TSignInManager);
if (!managerType.GetTypeInfo().IsAssignableFrom(customType.GetTypeInfo())) if (!managerType.GetTypeInfo().IsAssignableFrom(customType.GetTypeInfo()))
{ {

View File

@ -4,7 +4,7 @@
namespace Microsoft.AspNetCore.Identity namespace Microsoft.AspNetCore.Identity
{ {
/// <summary> /// <summary>
/// Represents all the options you can use to configure the cookies middleware used by the identity system. /// Represents all the options you can use to configure the cookies middleware uesd by the identity system.
/// </summary> /// </summary>
public class IdentityConstants public class IdentityConstants
{ {

View File

@ -0,0 +1,34 @@
// 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 Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Identity
{
/// <summary>
/// Used to configure identity cookie options.
/// </summary>
public class IdentityCookiesBuilder
{
/// <summary>
/// Used to configure the application cookie.
/// </summary>
public OptionsBuilder<CookieAuthenticationOptions> ApplicationCookie { get; set; }
/// <summary>
/// Used to configure the external cookie.
/// </summary>
public OptionsBuilder<CookieAuthenticationOptions> ExternalCookie { get; set; }
/// <summary>
/// Used to configure the two factor remember me cookie.
/// </summary>
public OptionsBuilder<CookieAuthenticationOptions> TwoFactorRememberMeCookie { get; set; }
/// <summary>
/// Used to configure the two factor user id cookie.
/// </summary>
public OptionsBuilder<CookieAuthenticationOptions> TwoFactorUserIdCookie { get; set; }
}
}

View File

@ -0,0 +1,103 @@
// 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 Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Identity
{
/// <summary>
/// Helper functions for configuring identity services.
/// </summary>
public static class IdentityCookieAuthenticationBuilderExtensions
{
/// <summary>
/// Adds cookie authentication.
/// </summary>
/// <param name="builder">The current <see cref="AuthenticationBuilder"/> instance.</param>
/// <returns>The <see cref="IdentityCookiesBuilder"/> which can be used to configure the identity cookies.</returns>
public static IdentityCookiesBuilder AddIdentityCookies(this AuthenticationBuilder builder)
=> builder.AddIdentityCookies(o => { });
/// <summary>
/// Adds the cookie authentication needed for sign in manager.
/// </summary>
/// <param name="builder">The current <see cref="AuthenticationBuilder"/> instance.</param>
/// <param name="configureCookies">Action used to configure the cookies.</param>
/// <returns>The <see cref="IdentityCookiesBuilder"/> which can be used to configure the identity cookies.</returns>
public static IdentityCookiesBuilder AddIdentityCookies(this AuthenticationBuilder builder, Action<IdentityCookiesBuilder> configureCookies)
{
var cookieBuilder = new IdentityCookiesBuilder();
cookieBuilder.ApplicationCookie = builder.AddApplicationCookie();
cookieBuilder.ExternalCookie = builder.AddExternalCookie();
cookieBuilder.TwoFactorRememberMeCookie = builder.AddTwoFactorRememberMeCookie();
cookieBuilder.TwoFactorUserIdCookie = builder.AddTwoFactorUserIdCookie();
configureCookies?.Invoke(cookieBuilder);
return cookieBuilder;
}
/// <summary>
/// Adds the identity application cookie.
/// </summary>
/// <param name="builder">The current <see cref="AuthenticationBuilder"/> instance.</param>
/// <returns>The <see cref="OptionsBuilder{TOptions}"/> which can be used to configure the cookie authentication.</returns>
public static OptionsBuilder<CookieAuthenticationOptions> AddApplicationCookie(this AuthenticationBuilder builder)
{
builder.AddCookie(IdentityConstants.ApplicationScheme, o =>
{
o.LoginPath = new PathString("/Account/Login");
o.Events = new CookieAuthenticationEvents
{
OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync
};
});
return new OptionsBuilder<CookieAuthenticationOptions>(builder.Services, IdentityConstants.ApplicationScheme);
}
/// <summary>
/// Adds the identity cookie used for external logins.
/// </summary>
/// <param name="builder">The current <see cref="AuthenticationBuilder"/> instance.</param>
/// <returns>The <see cref="OptionsBuilder{TOptions}"/> which can be used to configure the cookie authentication.</returns>
public static OptionsBuilder<CookieAuthenticationOptions> AddExternalCookie(this AuthenticationBuilder builder)
{
builder.AddCookie(IdentityConstants.ExternalScheme, o =>
{
o.Cookie.Name = IdentityConstants.ExternalScheme;
o.ExpireTimeSpan = TimeSpan.FromMinutes(5);
});
return new OptionsBuilder<CookieAuthenticationOptions>(builder.Services, IdentityConstants.ExternalScheme);
}
/// <summary>
/// Adds the identity cookie used for two factor remember me.
/// </summary>
/// <param name="builder">The current <see cref="AuthenticationBuilder"/> instance.</param>
/// <returns>The <see cref="OptionsBuilder{TOptions}"/> which can be used to configure the cookie authentication.</returns>
public static OptionsBuilder<CookieAuthenticationOptions> AddTwoFactorRememberMeCookie(this AuthenticationBuilder builder)
{
builder.AddCookie(IdentityConstants.TwoFactorRememberMeScheme, o => o.Cookie.Name = IdentityConstants.TwoFactorRememberMeScheme);
return new OptionsBuilder<CookieAuthenticationOptions>(builder.Services, IdentityConstants.TwoFactorRememberMeScheme);
}
/// <summary>
/// Adds the identity cookie used for two factor logins.
/// </summary>
/// <param name="builder">The current <see cref="AuthenticationBuilder"/> instance.</param>
/// <returns>The <see cref="OptionsBuilder{TOptions}"/> which can be used to configure the cookie authentication.</returns>
public static OptionsBuilder<CookieAuthenticationOptions> AddTwoFactorUserIdCookie(this AuthenticationBuilder builder)
{
builder.AddCookie(IdentityConstants.TwoFactorUserIdScheme, o =>
{
o.Cookie.Name = IdentityConstants.TwoFactorUserIdScheme;
o.ExpireTimeSpan = TimeSpan.FromMinutes(5);
});
return new OptionsBuilder<CookieAuthenticationOptions>(builder.Services, IdentityConstants.TwoFactorUserIdScheme);
}
}
}

View File

@ -2,12 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
namespace Microsoft.Extensions.DependencyInjection namespace Microsoft.Extensions.DependencyInjection
@ -28,27 +25,7 @@ namespace Microsoft.Extensions.DependencyInjection
this IServiceCollection services) this IServiceCollection services)
where TUser : class where TUser : class
where TRole : class where TRole : class
{ => services.AddIdentity<TUser, TRole>(setupAction: null);
return services.AddIdentity<TUser, TRole>(setupAction: null);
}
/// <summary>
/// Configures the application cookie.
/// </summary>
/// <param name="services">The services available in the application.</param>
/// <param name="configure">An action to configure the <see cref="CookieAuthenticationOptions"/>.</param>
/// <returns>The services.</returns>
public static IServiceCollection ConfigureApplicationCookie(this IServiceCollection services, Action<CookieAuthenticationOptions> configure)
=> services.Configure(IdentityConstants.ApplicationScheme, configure);
/// <summary>
/// Configure the external cookie.
/// </summary>
/// <param name="services">The services available in the application.</param>
/// <param name="configure">An action to configure the <see cref="CookieAuthenticationOptions"/>.</param>
/// <returns>The services.</returns>
public static IServiceCollection ConfigureExternalCookie(this IServiceCollection services, Action<CookieAuthenticationOptions> configure)
=> services.Configure(IdentityConstants.ExternalScheme, configure);
/// <summary> /// <summary>
/// Adds and configures the identity system for the specified User and Role types. /// Adds and configures the identity system for the specified User and Role types.
@ -122,5 +99,24 @@ namespace Microsoft.Extensions.DependencyInjection
return new IdentityBuilder(typeof(TUser), typeof(TRole), services); return new IdentityBuilder(typeof(TUser), typeof(TRole), services);
} }
/// <summary>
/// Configures the application cookie.
/// </summary>
/// <param name="services">The services available in the application.</param>
/// <param name="configure">An action to configure the <see cref="CookieAuthenticationOptions"/>.</param>
/// <returns>The services.</returns>
public static IServiceCollection ConfigureApplicationCookie(this IServiceCollection services, Action<CookieAuthenticationOptions> configure)
=> services.Configure(IdentityConstants.ApplicationScheme, configure);
/// <summary>
/// Configure the external cookie.
/// </summary>
/// <param name="services">The services available in the application.</param>
/// <param name="configure">An action to configure the <see cref="CookieAuthenticationOptions"/>.</param>
/// <returns>The services.</returns>
public static IServiceCollection ConfigureExternalCookie(this IServiceCollection services, Action<CookieAuthenticationOptions> configure)
=> services.Configure(IdentityConstants.ExternalScheme, configure);
} }
} }

View File

@ -31,6 +31,7 @@ namespace Microsoft.AspNetCore.Identity
/// <returns>The <see cref="IdentityBuilder"/>.</returns> /// <returns>The <see cref="IdentityBuilder"/>.</returns>
public static IdentityBuilder AddDefaultUI(this IdentityBuilder builder) public static IdentityBuilder AddDefaultUI(this IdentityBuilder builder)
{ {
builder.AddSignInManager();
AddAdditionalApplicationParts(builder); AddAdditionalApplicationParts(builder);
builder.Services.ConfigureOptions( builder.Services.ConfigureOptions(

View File

@ -2,10 +2,8 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Collections.Generic;
using System.Security.Claims; using System.Security.Claims;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Xunit; using Xunit;
@ -71,5 +69,28 @@ namespace Microsoft.AspNetCore.Identity.Test
var myOptions = optionsGetter.Value; var myOptions = optionsGetter.Value;
Assert.True(myOptions.User.RequireUniqueEmail); Assert.True(myOptions.User.RequireUniqueEmail);
} }
[Fact]
public void CanConfigureCookieOptions()
{
var services = new ServiceCollection();
services.AddAuthentication().AddIdentityCookies(o =>
{
o.ApplicationCookie.Configure(a => a.Cookie.Name = "a");
o.ExternalCookie.Configure(a => a.Cookie.Name = "b");
o.TwoFactorRememberMeCookie.Configure(a => a.Cookie.Name = "c");
o.TwoFactorUserIdCookie.Configure(a => a.Cookie.Name = "d");
});
var serviceProvider = services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptionsMonitor<CookieAuthenticationOptions>>();
Assert.NotNull(options);
Assert.Equal("a", options.Get(IdentityConstants.ApplicationScheme).Cookie.Name);
Assert.Equal("b", options.Get(IdentityConstants.ExternalScheme).Cookie.Name);
Assert.Equal("c", options.Get(IdentityConstants.TwoFactorRememberMeScheme).Cookie.Name);
Assert.Equal("d", options.Get(IdentityConstants.TwoFactorUserIdScheme).Cookie.Name);
}
} }
} }

View File

@ -6,7 +6,6 @@ using System.Security.Claims;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;

View File

@ -35,11 +35,19 @@ namespace Identity.DefaultUI.WebSite
sqlOptions => sqlOptions.MigrationsAssembly("Identity.DefaultUI.WebSite") sqlOptions => sqlOptions.MigrationsAssembly("Identity.DefaultUI.WebSite")
)); ));
services.AddIdentity<IdentityUser, IdentityRole>() services.AddIdentityCore<IdentityUser>()
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<IdentityDbContext>() .AddEntityFrameworkStores<IdentityDbContext>()
.AddDefaultUI() .AddDefaultUI()
.AddDefaultTokenProviders(); .AddDefaultTokenProviders();
services.AddAuthentication(o =>
{
o.DefaultScheme = IdentityConstants.ApplicationScheme;
o.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddIdentityCookies(o => {});
services.AddMvc() services.AddMvc()
.AddRazorPagesOptions(options => .AddRazorPagesOptions(options =>
{ {