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
SolutionGuid = {B3F2A592-CCE0-40C2-8CA4-7B1293DED874}
EndGlobalSection
EndGlobal
EndGlobal

View File

@ -2,7 +2,6 @@ using IdentitySample.DefaultUI.Data;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@ -33,14 +32,23 @@ namespace IdentitySample.DefaultUI
options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
x => x.MigrationsAssembly("IdentitySample.DefaultUI")));
services.AddIdentity<ApplicationUser, IdentityRole>(o => o.Stores.MaxLengthForKeys = 128)
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultUI()
.AddDefaultTokenProviders();
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.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{

View File

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

View File

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

View File

@ -12,6 +12,15 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary>
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>
/// Adds and configures the identity system for the specified User and Role types.
/// </summary>

View File

@ -31,6 +31,26 @@ namespace Microsoft.AspNetCore.Identity
.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>
/// Adds a <see cref="SignInManager{TUser}"/> for the <seealso cref="IdentityBuilder.UserType"/>.
/// </summary>
@ -39,8 +59,8 @@ namespace Microsoft.AspNetCore.Identity
/// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
public static IdentityBuilder AddSignInManager<TSignInManager>(this IdentityBuilder builder) where TSignInManager : class
{
builder.AddSignInManagerDeps();
var managerType = typeof(SignInManager<>).MakeGenericType(builder.UserType);
var customType = typeof(TSignInManager);
if (!managerType.GetTypeInfo().IsAssignableFrom(customType.GetTypeInfo()))
{

View File

@ -4,7 +4,7 @@
namespace Microsoft.AspNetCore.Identity
{
/// <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>
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.
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace Microsoft.Extensions.DependencyInjection
@ -28,27 +25,7 @@ namespace Microsoft.Extensions.DependencyInjection
this IServiceCollection services)
where TUser : class
where TRole : class
{
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);
=> services.AddIdentity<TUser, TRole>(setupAction: null);
/// <summary>
/// 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);
}
/// <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>
public static IdentityBuilder AddDefaultUI(this IdentityBuilder builder)
{
builder.AddSignInManager();
AddAdditionalApplicationParts(builder);
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.
using System;
using System.Collections.Generic;
using System.Security.Claims;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Xunit;
@ -71,5 +69,28 @@ namespace Microsoft.AspNetCore.Identity.Test
var myOptions = optionsGetter.Value;
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 Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;

View File

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