React to AuthN changes

This commit is contained in:
Hao Kung 2015-03-02 16:39:01 -08:00
parent 747f4137c6
commit 3aaa628365
27 changed files with 534 additions and 462 deletions

View File

@ -2,10 +2,11 @@
using System.Security.Claims; using System.Security.Claims;
using System.Security.Principal; using System.Security.Principal;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Authentication;
using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Security; using Microsoft.AspNet.Authorization;
namespace IdentitySample.Models namespace IdentitySample.Models
{ {
@ -29,7 +30,7 @@ namespace IdentitySample.Models
public IActionResult Login(string returnUrl = null) public IActionResult Login(string returnUrl = null)
{ {
ViewBag.ReturnUrl = returnUrl; ViewBag.ReturnUrl = returnUrl;
ViewBag.LoginProviders = SignInManager.GetExternalAuthenticationTypes().ToList(); ViewBag.LoginProviders = SignInManager.GetExternalAuthenticationSchemes().ToList();
return View(); return View();
} }
@ -164,7 +165,7 @@ namespace IdentitySample.Models
ViewBag.ReturnUrl = returnUrl; ViewBag.ReturnUrl = returnUrl;
ViewBag.LoginProvider = info.LoginProvider; ViewBag.LoginProvider = info.LoginProvider;
// REVIEW: handle case where email not in claims? // REVIEW: handle case where email not in claims?
var email = info.ExternalIdentity.FindFirstValue(ClaimTypes.Email); var email = info.ExternalPrincipal.FindFirstValue(ClaimTypes.Email);
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email }); return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email });
} }
} }
@ -176,7 +177,7 @@ namespace IdentitySample.Models
[ValidateAntiForgeryToken] [ValidateAntiForgeryToken]
public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl = null) public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl = null)
{ {
if (User.Identity.IsAuthenticated) if (User.IsSignedIn())
{ {
return RedirectToAction("Index", "Manage"); return RedirectToAction("Index", "Manage");
} }
@ -414,7 +415,7 @@ namespace IdentitySample.Models
private async Task<ApplicationUser> GetCurrentUserAsync() private async Task<ApplicationUser> GetCurrentUserAsync()
{ {
return await UserManager.FindByIdAsync(Context.User.Identity.GetUserId()); return await UserManager.FindByIdAsync(Context.User.GetUserId());
} }
private IActionResult RedirectToLocal(string returnUrl) private IActionResult RedirectToLocal(string returnUrl)

View File

@ -2,9 +2,9 @@
using System.Security.Principal; using System.Security.Principal;
using System.Threading.Tasks; using System.Threading.Tasks;
using IdentitySample.Models; using IdentitySample.Models;
using Microsoft.AspNet.Authorization;
using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Security;
namespace IdentitySample namespace IdentitySample
{ {
@ -300,7 +300,7 @@ namespace IdentitySample
return View("Error"); return View("Error");
} }
var userLogins = await UserManager.GetLoginsAsync(user); var userLogins = await UserManager.GetLoginsAsync(user);
var otherLogins = SignInManager.GetExternalAuthenticationTypes().Where(auth => userLogins.All(ul => auth.AuthenticationType != ul.LoginProvider)).ToList(); var otherLogins = SignInManager.GetExternalAuthenticationSchemes().Where(auth => userLogins.All(ul => auth.AuthenticationScheme != ul.LoginProvider)).ToList();
ViewBag.ShowRemoveButton = user.PasswordHash != null || userLogins.Count > 1; ViewBag.ShowRemoveButton = user.PasswordHash != null || userLogins.Count > 1;
return View(new ManageLoginsViewModel return View(new ManageLoginsViewModel
{ {
@ -317,7 +317,7 @@ namespace IdentitySample
{ {
// Request a redirect to the external login provider to link a login for the current user // Request a redirect to the external login provider to link a login for the current user
var redirectUrl = Url.Action("LinkLoginCallback", "Manage"); var redirectUrl = Url.Action("LinkLoginCallback", "Manage");
var properties = SignInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, User.Identity.GetUserId()); var properties = SignInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, User.GetUserId());
return new ChallengeResult(provider, properties); return new ChallengeResult(provider, properties);
} }
@ -331,7 +331,7 @@ namespace IdentitySample
{ {
return View("Error"); return View("Error");
} }
var info = await SignInManager.GetExternalLoginInfoAsync(User.Identity.GetUserId()); var info = await SignInManager.GetExternalLoginInfoAsync(User.GetUserId());
if (info == null) if (info == null)
{ {
return RedirectToAction("ManageLogins", new { Message = ManageMessageId.Error }); return RedirectToAction("ManageLogins", new { Message = ManageMessageId.Error });
@ -353,7 +353,7 @@ namespace IdentitySample
private async Task<bool> HasPhoneNumber() private async Task<bool> HasPhoneNumber()
{ {
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); var user = await UserManager.FindByIdAsync(User.GetUserId());
if (user != null) if (user != null)
{ {
return user.PhoneNumber != null; return user.PhoneNumber != null;
@ -375,7 +375,7 @@ namespace IdentitySample
private async Task<ApplicationUser> GetCurrentUserAsync() private async Task<ApplicationUser> GetCurrentUserAsync()
{ {
return await UserManager.FindByIdAsync(Context.User.Identity.GetUserId()); return await UserManager.FindByIdAsync(Context.User.GetUserId());
} }
private IActionResult RedirectToLocal(string returnUrl) private IActionResult RedirectToLocal(string returnUrl)

View File

@ -3,7 +3,7 @@
"DefaultAdminPassword": "YouShouldChangeThisPassword1!", "DefaultAdminPassword": "YouShouldChangeThisPassword1!",
"Data": { "Data": {
"IdentityConnection": { "IdentityConnection": {
"Connectionstring": "Server=(localdb)\\mssqllocaldb;Database=IdentityMvc-1-7-15;Trusted_Connection=True;MultipleActiveResultSets=true" "Connectionstring": "Server=(localdb)\\mssqllocaldb;Database=IdentityMvc-2-20-15-3;Trusted_Connection=True;MultipleActiveResultSets=true"
} }
}, },
"Identity": { "Identity": {

View File

@ -1,8 +1,8 @@
using Microsoft.AspNet.Http.Security; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNet.Http.Authentication;
using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.Rendering;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace IdentitySample.Models namespace IdentitySample.Models
{ {

View File

@ -74,7 +74,7 @@
<div id="socialLoginList"> <div id="socialLoginList">
<p> <p>
@foreach (AuthenticationDescription p in ViewBag.LoginProviders) { @foreach (AuthenticationDescription p in ViewBag.LoginProviders) {
<button type="submit" class="btn btn-default" id="@p.AuthenticationType" name="provider" value="@p.AuthenticationType" title="Log in using your @p.Caption account">@p.AuthenticationType</button> <button type="submit" class="btn btn-default" id="@p.AuthenticationScheme" name="provider" value="@p.AuthenticationScheme" title="Log in using your @p.Caption account">@p.AuthenticationScheme</button>
} }
</p> </p>
</div> </div>

View File

@ -52,7 +52,7 @@
<p> <p>
@foreach (AuthenticationDescription p in Model.OtherLogins) @foreach (AuthenticationDescription p in Model.OtherLogins)
{ {
<button type="submit" class="btn btn-default" id="@p.AuthenticationType" name="provider" value="@p.AuthenticationType" title="Log in using your @p.Caption account">@p.AuthenticationType</button> <button type="submit" class="btn btn-default" id="@p.AuthenticationScheme" name="provider" value="@p.AuthenticationScheme" title="Log in using your @p.Caption account">@p.AuthenticationScheme</button>
} }
</p> </p>
</div> </div>

View File

@ -1,6 +1,6 @@
@using System.Security.Principal @using System.Security.Principal
@if (User.Identity.IsAuthenticated) @if (User.IsSignedIn())
{ {
using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" })) using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" }))
{ {
@ -8,7 +8,7 @@
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">
<li> <li>
@Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" }) @Html.ActionLink("Hello " + User.GetUserName() + "!", "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" })
</li> </li>
<li><a href="javascript:document.getElementById('logoutForm').submit()">Log off</a></li> <li><a href="javascript:document.getElementById('logoutForm').submit()">Log off</a></li>
</ul> </ul>

View File

@ -11,10 +11,11 @@
"Microsoft.AspNet.Diagnostics": "1.0.0-*", "Microsoft.AspNet.Diagnostics": "1.0.0-*",
"Microsoft.AspNet.Identity": "3.0.0-*", "Microsoft.AspNet.Identity": "3.0.0-*",
"Microsoft.AspNet.Identity.EntityFramework": "3.0.0-*", "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-*",
"Microsoft.AspNet.Security.Cookies": "1.0.0-*", "Microsoft.AspNet.Authentication.Cookies": "1.0.0-*",
"Microsoft.AspNet.Security.Facebook": "1.0.0-*", "Microsoft.AspNet.Authentication.Facebook": "1.0.0-*",
"Microsoft.AspNet.Security.Google": "1.0.0-*", "Microsoft.AspNet.Authentication.Google": "1.0.0-*",
"Microsoft.AspNet.Security.Twitter": "1.0.0-*", "Microsoft.AspNet.Authentication.Twitter": "1.0.0-*",
"Microsoft.AspNet.Authorization": "1.0.0-*",
"Microsoft.AspNet.StaticFiles": "1.0.0-*", "Microsoft.AspNet.StaticFiles": "1.0.0-*",
"EntityFramework.SqlServer": "7.0.0-*", "EntityFramework.SqlServer": "7.0.0-*",
"Microsoft.Framework.ConfigurationModel.Json": "1.0.0-*", "Microsoft.Framework.ConfigurationModel.Json": "1.0.0-*",

View File

@ -23,10 +23,10 @@ namespace Microsoft.AspNet.Builder
{ {
throw new ArgumentNullException("app"); throw new ArgumentNullException("app");
} }
app.UseCookieAuthentication(null, IdentityOptions.ExternalCookieAuthenticationType); app.UseCookieAuthentication(null, IdentityOptions.ExternalCookieAuthenticationScheme);
app.UseCookieAuthentication(null, IdentityOptions.TwoFactorRememberMeCookieAuthenticationType); app.UseCookieAuthentication(null, IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme);
app.UseCookieAuthentication(null, IdentityOptions.TwoFactorUserIdCookieAuthenticationType); app.UseCookieAuthentication(null, IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme);
app.UseCookieAuthentication(null, IdentityOptions.ApplicationCookieAuthenticationType); app.UseCookieAuthentication(null, IdentityOptions.ApplicationCookieAuthenticationScheme);
return app; return app;
} }
} }

View File

@ -1,61 +0,0 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Security.Claims;
namespace System.Security.Principal
{
/// <summary>
/// Claims related extensions for <see cref="IIdentity"/>.
/// </summary>
public static class ClaimsIdentityExtensions
{
/// <summary>
/// Returns the Name claim value if present otherwise returns null.
/// </summary>
/// <param name="identity">The <see cref="IIdentity"/> instance this method extends.</param>
/// <returns>The Name claim value, or null if the claim is not present.</returns>
/// <remarks>The name claim is identified by <see cref="ClaimsIdentity.DefaultNameClaimType"/>.</remarks>
public static string GetUserName(this IIdentity identity)
{
if (identity == null)
{
throw new ArgumentNullException("identity");
}
var ci = identity as ClaimsIdentity;
return ci != null ? ci.FindFirstValue(ClaimsIdentity.DefaultNameClaimType) : null;
}
/// <summary>
/// Returns the User ID claim value if present otherwise returns null.
/// </summary>
/// <param name="identity">The <see cref="IIdentity"/> instance this method extends.</param>
/// <returns>The User ID claim value, or null if the claim is not present.</returns>
/// <remarks>The name claim is identified by <see cref="ClaimTypes.NameIdentifier"/>.</remarks>
public static string GetUserId(this IIdentity identity)
{
if (identity == null)
{
throw new ArgumentNullException("identity");
}
var ci = identity as ClaimsIdentity;
return ci != null ? ci.FindFirstValue(ClaimTypes.NameIdentifier) : null;
}
/// <summary>
/// Returns the value for the first claim of the specified type otherwise null the claim is not present.
/// </summary>
/// <param name="identity">The <see cref="IIdentity"/> instance this method extends.</param>
/// <param name="claimType">The claim type whose first value should be returned.</param>
/// <returns>The value of the first instance of the specifed claim type, or null if the claim is not present.</returns>
public static string FindFirstValue(this ClaimsIdentity identity, string claimType)
{
if (identity == null)
{
throw new ArgumentNullException("identity");
}
var claim = identity.FindFirst(claimType);
return claim != null ? claim.Value : null;
}
}
}

View File

@ -7,12 +7,12 @@ namespace Microsoft.AspNet.Identity
{ {
public class ExternalLoginInfo : UserLoginInfo public class ExternalLoginInfo : UserLoginInfo
{ {
public ExternalLoginInfo(ClaimsIdentity externalIdentity, string loginProvider, string providerKey, public ExternalLoginInfo(ClaimsPrincipal externalPrincipal, string loginProvider, string providerKey,
string displayName) : base(loginProvider, providerKey, displayName) string displayName) : base(loginProvider, providerKey, displayName)
{ {
ExternalIdentity = externalIdentity; ExternalPrincipal = externalPrincipal;
} }
public ClaimsIdentity ExternalIdentity { get; set; } public ClaimsPrincipal ExternalPrincipal { get; set; }
} }
} }

View File

@ -1,14 +1,13 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// 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.Security.Claims;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Security.Cookies; using Microsoft.AspNet.Authentication.Cookies;
namespace Microsoft.AspNet.Identity namespace Microsoft.AspNet.Identity
{ {
public interface ISecurityStampValidator public interface ISecurityStampValidator
{ {
Task ValidateAsync(CookieValidateIdentityContext context, ClaimsIdentity identity); Task ValidateAsync(CookieValidatePrincipalContext context);
} }
} }

View File

@ -2,24 +2,23 @@
// 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.Security.Claims; using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity namespace Microsoft.AspNet.Identity
{ {
/// <summary> /// <summary>
/// Interface for creating a ClaimsIdentity from an user /// Interface for creating a ClaimsPrincipal from an user
/// </summary> /// </summary>
/// <typeparam name="TUser"></typeparam> /// <typeparam name="TUser"></typeparam>
public interface IClaimsIdentityFactory<TUser> public interface IUserClaimsPrincipalFactory<TUser>
where TUser : class where TUser : class
{ {
/// <summary> /// <summary>
/// Create a ClaimsIdentity from an user /// Create a ClaimsPrincipal from an user
/// </summary> /// </summary>
/// <param name="user"></param> /// <param name="user"></param>
/// <param name="authenticationType"></param> /// <param name="authenticationType"></param>
/// <returns></returns> /// <returns></returns>
Task<ClaimsIdentity> CreateAsync(TUser user); Task<ClaimsPrincipal> CreateAsync(TUser user);
} }
} }

View File

@ -1,9 +1,6 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// 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 Microsoft.AspNet.Http;
using Microsoft.AspNet.Security;
using Microsoft.AspNet.Security.Cookies;
using System; using System;
namespace Microsoft.AspNet.Identity namespace Microsoft.AspNet.Identity
@ -31,9 +28,15 @@ namespace Microsoft.AspNet.Identity
public string ChangeEmailTokenProvider { get; set; } = Resources.DefaultTokenProvider; public string ChangeEmailTokenProvider { get; set; } = Resources.DefaultTokenProvider;
public static string ApplicationCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".Application"; public static string ApplicationCookieAuthenticationScheme { get; set; } = typeof(IdentityOptions).Namespace + ".Application";
public static string ExternalCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".External"; public static string ExternalCookieAuthenticationScheme { get; set; } = typeof(IdentityOptions).Namespace + ".External";
public static string TwoFactorUserIdCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorUserId"; public static string TwoFactorUserIdCookieAuthenticationScheme { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorUserId";
public static string TwoFactorRememberMeCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorRemeberMe"; public static string TwoFactorRememberMeCookieAuthenticationScheme { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorRemeberMe";
public static string ApplicationCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".Application.AuthType";
public static string ExternalCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".External.AuthType";
public static string TwoFactorUserIdCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorUserId.AuthType";
public static string TwoFactorRememberMeCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorRemeberMe.AuthType";
} }
} }

View File

@ -5,8 +5,8 @@ using System;
using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Security; using Microsoft.AspNet.Authentication;
using Microsoft.AspNet.Security.Cookies; using Microsoft.AspNet.Authentication.Cookies;
using Microsoft.Framework.ConfigurationModel; using Microsoft.Framework.ConfigurationModel;
namespace Microsoft.Framework.DependencyInjection namespace Microsoft.Framework.DependencyInjection
@ -65,7 +65,7 @@ namespace Microsoft.Framework.DependencyInjection
// No interface for the error describer so we can add errors without rev'ing the interface // No interface for the error describer so we can add errors without rev'ing the interface
services.TryAdd(describe.Transient<IdentityErrorDescriber, IdentityErrorDescriber>()); services.TryAdd(describe.Transient<IdentityErrorDescriber, IdentityErrorDescriber>());
services.TryAdd(describe.Scoped<ISecurityStampValidator, SecurityStampValidator<TUser>>()); services.TryAdd(describe.Scoped<ISecurityStampValidator, SecurityStampValidator<TUser>>());
services.TryAdd(describe.Scoped<IClaimsIdentityFactory<TUser>, ClaimsIdentityFactory<TUser, TRole>>()); services.TryAdd(describe.Scoped<IUserClaimsPrincipalFactory<TUser>, UserClaimsPrincipalFactory<TUser, TRole>>());
services.TryAdd(describe.Scoped<UserManager<TUser>, UserManager<TUser>>()); services.TryAdd(describe.Scoped<UserManager<TUser>, UserManager<TUser>>());
services.TryAdd(describe.Scoped<SignInManager<TUser>, SignInManager<TUser>>()); services.TryAdd(describe.Scoped<SignInManager<TUser>, SignInManager<TUser>>());
services.TryAdd(describe.Scoped<RoleManager<TRole>, RoleManager<TRole>>()); services.TryAdd(describe.Scoped<RoleManager<TRole>, RoleManager<TRole>>());
@ -76,39 +76,39 @@ namespace Microsoft.Framework.DependencyInjection
} }
services.Configure<ExternalAuthenticationOptions>(options => services.Configure<ExternalAuthenticationOptions>(options =>
{ {
options.SignInAsAuthenticationType = IdentityOptions.ExternalCookieAuthenticationType; options.SignInScheme = IdentityOptions.ExternalCookieAuthenticationScheme;
}); });
// Configure all of the cookie middlewares // Configure all of the cookie middlewares
services.Configure<CookieAuthenticationOptions>(options => services.Configure<CookieAuthenticationOptions>(options =>
{ {
options.AuthenticationType = IdentityOptions.ApplicationCookieAuthenticationType; options.AuthenticationScheme = IdentityOptions.ApplicationCookieAuthenticationScheme;
options.LoginPath = new PathString("/Account/Login"); options.LoginPath = new PathString("/Account/Login");
options.Notifications = new CookieAuthenticationNotifications options.Notifications = new CookieAuthenticationNotifications
{ {
OnValidateIdentity = SecurityStampValidator.ValidateIdentityAsync OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync
}; };
}, IdentityOptions.ApplicationCookieAuthenticationType); }, IdentityOptions.ApplicationCookieAuthenticationScheme);
services.Configure<CookieAuthenticationOptions>(options => services.Configure<CookieAuthenticationOptions>(options =>
{ {
options.AuthenticationType = IdentityOptions.ExternalCookieAuthenticationType; options.AuthenticationScheme = IdentityOptions.ExternalCookieAuthenticationScheme;
options.AuthenticationMode = AuthenticationMode.Passive; options.AutomaticAuthentication = false;
options.CookieName = IdentityOptions.ExternalCookieAuthenticationType; options.CookieName = IdentityOptions.ExternalCookieAuthenticationScheme;
options.ExpireTimeSpan = TimeSpan.FromMinutes(5); options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
}, IdentityOptions.ExternalCookieAuthenticationType); }, IdentityOptions.ExternalCookieAuthenticationScheme);
services.Configure<CookieAuthenticationOptions>(options => services.Configure<CookieAuthenticationOptions>(options =>
{ {
options.AuthenticationType = IdentityOptions.TwoFactorRememberMeCookieAuthenticationType; options.AuthenticationScheme = IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme;
options.AuthenticationMode = AuthenticationMode.Passive; options.AutomaticAuthentication = false;
options.CookieName = IdentityOptions.TwoFactorRememberMeCookieAuthenticationType; options.CookieName = IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme;
}, IdentityOptions.TwoFactorRememberMeCookieAuthenticationType); }, IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme);
services.Configure<CookieAuthenticationOptions>(options => services.Configure<CookieAuthenticationOptions>(options =>
{ {
options.AuthenticationType = IdentityOptions.TwoFactorUserIdCookieAuthenticationType; options.AuthenticationScheme = IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme;
options.AuthenticationMode = AuthenticationMode.Passive; options.AutomaticAuthentication = false;
options.CookieName = IdentityOptions.TwoFactorUserIdCookieAuthenticationType; options.CookieName = IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme;
options.ExpireTimeSpan = TimeSpan.FromMinutes(5); options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
}, IdentityOptions.TwoFactorUserIdCookieAuthenticationType); }, IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme);
return new IdentityBuilder(typeof(TUser), typeof(TRole), services); return new IdentityBuilder(typeof(TUser), typeof(TRole), services);
} }

View File

@ -0,0 +1,80 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Linq;
using System.Security.Claims;
using Microsoft.AspNet.Identity;
namespace System.Security.Principal
{
/// <summary>
/// Claims related extensions for <see cref="IPrincipal"/>.
/// </summary>
public static class PrincipalExtensions
{
/// <summary>
/// Returns the Name claim value if present otherwise returns null.
/// </summary>
/// <param name="principal">The <see cref="IPrincipal"/> instance this method extends.</param>
/// <returns>The Name claim value, or null if the claim is not present.</returns>
/// <remarks>The name claim is identified by <see cref="ClaimsIdentity.DefaultNameClaimType"/>.</remarks>
public static string GetUserName(this IPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
var cp = principal as ClaimsPrincipal;
return cp != null ? cp.FindFirstValue(ClaimsIdentity.DefaultNameClaimType) : null;
}
/// <summary>
/// Returns the User ID claim value if present otherwise returns null.
/// </summary>
/// <param name="principal">The <see cref="IPrincipal"/> instance this method extends.</param>
/// <returns>The User ID claim value, or null if the claim is not present.</returns>
/// <remarks>The name claim is identified by <see cref="ClaimTypes.NameIdentifier"/>.</remarks>
public static string GetUserId(this IPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
var ci = principal as ClaimsPrincipal;
return ci != null ? ci.FindFirstValue(ClaimTypes.NameIdentifier) : null;
}
/// <summary>
/// Returns true if the principal has an identity with the application cookie identity
/// </summary>
/// <param name="principal">The <see cref="IPrincipal"/> instance this method extends.</param>
/// <returns>True if the user is logged in with identity.</returns>
public static bool IsSignedIn(this IPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
var p = principal as ClaimsPrincipal;
return p?.Identities != null &&
p.Identities.Any(i => i.AuthenticationType == IdentityOptions.ApplicationCookieAuthenticationType);
}
/// <summary>
/// Returns the value for the first claim of the specified type otherwise null the claim is not present.
/// </summary>
/// <param name="identity">The <see cref="IIdentity"/> instance this method extends.</param>
/// <param name="claimType">The claim type whose first value should be returned.</param>
/// <returns>The value of the first instance of the specifed claim type, or null if the claim is not present.</returns>
public static string FindFirstValue(this ClaimsPrincipal principal, string claimType)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
var claim = principal.FindFirst(claimType);
return claim != null ? claim.Value : null;
}
}
}

View File

@ -2,11 +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.Security.Claims;
using System.Security.Principal; using System.Security.Principal;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Security.Cookies; using Microsoft.AspNet.Authentication.Cookies;
using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel; using Microsoft.Framework.OptionsModel;
@ -19,11 +17,11 @@ namespace Microsoft.AspNet.Identity
/// ClaimsIdentity /// ClaimsIdentity
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public virtual async Task ValidateAsync(CookieValidateIdentityContext context, ClaimsIdentity identity) public virtual async Task ValidateAsync(CookieValidatePrincipalContext context)
{ {
var manager = context.HttpContext.RequestServices.GetRequiredService<SignInManager<TUser>>(); var manager = context.HttpContext.RequestServices.GetRequiredService<SignInManager<TUser>>();
var userId = identity.GetUserId(); var userId = context.Principal.GetUserId();
var user = await manager.ValidateSecurityStampAsync(identity, userId); var user = await manager.ValidateSecurityStampAsync(context.Principal, userId);
if (user != null) if (user != null)
{ {
var isPersistent = false; var isPersistent = false;
@ -35,7 +33,7 @@ namespace Microsoft.AspNet.Identity
} }
else else
{ {
context.RejectIdentity(); context.RejectPrincipal();
manager.SignOut(); manager.SignOut();
} }
} }
@ -47,7 +45,7 @@ namespace Microsoft.AspNet.Identity
/// </summary> /// </summary>
public static class SecurityStampValidator public static class SecurityStampValidator
{ {
public static Task ValidateIdentityAsync(CookieValidateIdentityContext context) public static Task ValidatePrincipalAsync(CookieValidatePrincipalContext context)
{ {
var currentUtc = DateTimeOffset.UtcNow; var currentUtc = DateTimeOffset.UtcNow;
if (context.Options != null && context.Options.SystemClock != null) if (context.Options != null && context.Options.SystemClock != null)
@ -72,7 +70,7 @@ namespace Microsoft.AspNet.Identity
if (validate) if (validate)
{ {
var validator = context.HttpContext.RequestServices.GetRequiredService<ISecurityStampValidator>(); var validator = context.HttpContext.RequestServices.GetRequiredService<ISecurityStampValidator>();
return validator.ValidateAsync(context, context.Identity); return validator.ValidateAsync(context);
} }
return Task.FromResult(0); return Task.FromResult(0);
} }

View File

@ -9,7 +9,7 @@ using System.Security.Principal;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Security; using Microsoft.AspNet.Http.Authentication;
using Microsoft.Framework.Logging; using Microsoft.Framework.Logging;
using Microsoft.Framework.OptionsModel; using Microsoft.Framework.OptionsModel;
@ -23,7 +23,7 @@ namespace Microsoft.AspNet.Identity
{ {
public SignInManager(UserManager<TUser> userManager, public SignInManager(UserManager<TUser> userManager,
IHttpContextAccessor contextAccessor, IHttpContextAccessor contextAccessor,
IClaimsIdentityFactory<TUser> claimsFactory, IUserClaimsPrincipalFactory<TUser> claimsFactory,
IOptions<IdentityOptions> optionsAccessor = null, IOptions<IdentityOptions> optionsAccessor = null,
ILogger<SignInManager<TUser>> logger = null) ILogger<SignInManager<TUser>> logger = null)
{ {
@ -50,12 +50,12 @@ namespace Microsoft.AspNet.Identity
public UserManager<TUser> UserManager { get; private set; } public UserManager<TUser> UserManager { get; private set; }
public HttpContext Context { get; private set; } public HttpContext Context { get; private set; }
public IClaimsIdentityFactory<TUser> ClaimsFactory { get; private set; } public IUserClaimsPrincipalFactory<TUser> ClaimsFactory { get; private set; }
public IdentityOptions Options { get; private set; } public IdentityOptions Options { get; private set; }
public ILogger<SignInManager<TUser>> Logger { get; set; } public ILogger<SignInManager<TUser>> Logger { get; set; }
// Should this be a func? // Should this be a func?
public virtual async Task<ClaimsIdentity> CreateUserIdentityAsync(TUser user) public virtual async Task<ClaimsPrincipal> CreateUserPrincipalAsync(TUser user)
{ {
return await ClaimsFactory.CreateAsync(user); return await ClaimsFactory.CreateAsync(user);
} }
@ -75,19 +75,22 @@ namespace Microsoft.AspNet.Identity
public virtual async Task SignInAsync(TUser user, bool isPersistent, string authenticationMethod = null) public virtual async Task SignInAsync(TUser user, bool isPersistent, string authenticationMethod = null)
{ {
var userIdentity = await CreateUserIdentityAsync(user); var userPrincipal = await CreateUserPrincipalAsync(user);
// Review: should we guard against CreateUserPrincipal returning null?
if (authenticationMethod != null) if (authenticationMethod != null)
{ {
userIdentity.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, authenticationMethod)); userPrincipal.Identities.First().AddClaim(new Claim(ClaimTypes.AuthenticationMethod, authenticationMethod));
} }
Context.Response.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, userIdentity); Context.Response.SignIn(IdentityOptions.ApplicationCookieAuthenticationScheme,
userPrincipal,
new AuthenticationProperties() { IsPersistent = isPersistent });
} }
public virtual void SignOut() public virtual void SignOut()
{ {
Context.Response.SignOut(IdentityOptions.ApplicationCookieAuthenticationType); Context.Response.SignOut(IdentityOptions.ApplicationCookieAuthenticationScheme);
Context.Response.SignOut(IdentityOptions.ExternalCookieAuthenticationType); Context.Response.SignOut(IdentityOptions.ExternalCookieAuthenticationScheme);
Context.Response.SignOut(IdentityOptions.TwoFactorUserIdCookieAuthenticationType); Context.Response.SignOut(IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme);
} }
private async Task<bool> IsLockedOut(TUser user) private async Task<bool> IsLockedOut(TUser user)
@ -124,13 +127,13 @@ namespace Microsoft.AspNet.Identity
/// <param name="identity"></param> /// <param name="identity"></param>
/// <param name="userId"></param> /// <param name="userId"></param>
/// <returns></returns> /// <returns></returns>
public virtual async Task<TUser> ValidateSecurityStampAsync(ClaimsIdentity identity, string userId) public virtual async Task<TUser> ValidateSecurityStampAsync(ClaimsPrincipal principal, string userId)
{ {
var user = await UserManager.FindByIdAsync(userId); var user = await UserManager.FindByIdAsync(userId);
if (user != null && UserManager.SupportsUserSecurityStamp) if (user != null && UserManager.SupportsUserSecurityStamp)
{ {
var securityStamp = var securityStamp =
identity.FindFirstValue(Options.ClaimsIdentity.SecurityStampClaimType); principal.FindFirstValue(Options.ClaimsIdentity.SecurityStampClaimType);
if (securityStamp == await UserManager.GetSecurityStampAsync(user)) if (securityStamp == await UserManager.GetSecurityStampAsync(user))
{ {
return user; return user;
@ -221,8 +224,8 @@ namespace Microsoft.AspNet.Identity
{ {
var userId = await UserManager.GetUserIdAsync(user); var userId = await UserManager.GetUserIdAsync(user);
var result = var result =
await Context.AuthenticateAsync(IdentityOptions.TwoFactorRememberMeCookieAuthenticationType); await Context.AuthenticateAsync(IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme);
return (result != null && result.Identity != null && result.Identity.Name == userId); return (result?.Principal != null && result.Principal.FindFirstValue(ClaimTypes.Name) == userId);
} }
public virtual async Task RememberTwoFactorClientAsync(TUser user) public virtual async Task RememberTwoFactorClientAsync(TUser user)
@ -230,12 +233,14 @@ namespace Microsoft.AspNet.Identity
var userId = await UserManager.GetUserIdAsync(user); var userId = await UserManager.GetUserIdAsync(user);
var rememberBrowserIdentity = new ClaimsIdentity(IdentityOptions.TwoFactorRememberMeCookieAuthenticationType); var rememberBrowserIdentity = new ClaimsIdentity(IdentityOptions.TwoFactorRememberMeCookieAuthenticationType);
rememberBrowserIdentity.AddClaim(new Claim(ClaimTypes.Name, userId)); rememberBrowserIdentity.AddClaim(new Claim(ClaimTypes.Name, userId));
Context.Response.SignIn(new AuthenticationProperties { IsPersistent = true }, rememberBrowserIdentity); Context.Response.SignIn(IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme,
new ClaimsPrincipal(rememberBrowserIdentity),
new AuthenticationProperties { IsPersistent = true });
} }
public virtual Task ForgetTwoFactorClientAsync() public virtual Task ForgetTwoFactorClientAsync()
{ {
Context.Response.SignOut(IdentityOptions.TwoFactorRememberMeCookieAuthenticationType); Context.Response.SignOut(IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme);
return Task.FromResult(0); return Task.FromResult(0);
} }
@ -264,7 +269,7 @@ namespace Microsoft.AspNet.Identity
// Cleanup external cookie // Cleanup external cookie
if (twoFactorInfo.LoginProvider != null) if (twoFactorInfo.LoginProvider != null)
{ {
Context.Response.SignOut(IdentityOptions.ExternalCookieAuthenticationType); Context.Response.SignOut(IdentityOptions.ExternalCookieAuthenticationScheme);
} }
await SignInAsync(user, isPersistent, twoFactorInfo.LoginProvider); await SignInAsync(user, isPersistent, twoFactorInfo.LoginProvider);
if (rememberClient) if (rememberClient)
@ -314,15 +319,15 @@ namespace Microsoft.AspNet.Identity
private const string LoginProviderKey = "LoginProvider"; private const string LoginProviderKey = "LoginProvider";
private const string XsrfKey = "XsrfId"; private const string XsrfKey = "XsrfId";
public virtual IEnumerable<AuthenticationDescription> GetExternalAuthenticationTypes() public virtual IEnumerable<AuthenticationDescription> GetExternalAuthenticationSchemes()
{ {
return Context.GetAuthenticationTypes().Where(d => !string.IsNullOrEmpty(d.Caption)); return Context.GetAuthenticationSchemes().Where(d => !string.IsNullOrEmpty(d.Caption));
} }
public virtual async Task<ExternalLoginInfo> GetExternalLoginInfoAsync(string expectedXsrf = null) public virtual async Task<ExternalLoginInfo> GetExternalLoginInfoAsync(string expectedXsrf = null)
{ {
var auth = await Context.AuthenticateAsync(IdentityOptions.ExternalCookieAuthenticationType); var auth = await Context.AuthenticateAsync(IdentityOptions.ExternalCookieAuthenticationScheme);
if (auth == null || auth.Identity == null || auth.Properties.Dictionary == null || !auth.Properties.Dictionary.ContainsKey(LoginProviderKey)) if (auth == null || auth.Principal == null || auth.Properties.Dictionary == null || !auth.Properties.Dictionary.ContainsKey(LoginProviderKey))
{ {
return null; return null;
} }
@ -340,13 +345,13 @@ namespace Microsoft.AspNet.Identity
} }
} }
var providerKey = auth.Identity.FindFirstValue(ClaimTypes.NameIdentifier); var providerKey = auth.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
var provider = auth.Properties.Dictionary[LoginProviderKey] as string; var provider = auth.Properties.Dictionary[LoginProviderKey] as string;
if (providerKey == null || provider == null) if (providerKey == null || provider == null)
{ {
return null; return null;
} }
return new ExternalLoginInfo(auth.Identity, provider, providerKey, auth.Description.Caption); return new ExternalLoginInfo(auth.Principal, provider, providerKey, auth.Description.Caption);
} }
public virtual AuthenticationProperties ConfigureExternalAuthenticationProperties(string provider, string redirectUrl, string userId = null) public virtual AuthenticationProperties ConfigureExternalAuthenticationProperties(string provider, string redirectUrl, string userId = null)
@ -370,14 +375,14 @@ namespace Microsoft.AspNet.Identity
{ {
// Store the userId for use after two factor check // Store the userId for use after two factor check
var userId = await UserManager.GetUserIdAsync(user); var userId = await UserManager.GetUserIdAsync(user);
Context.Response.SignIn(StoreTwoFactorInfo(userId, loginProvider)); Context.Response.SignIn(IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme, StoreTwoFactorInfo(userId, loginProvider));
return SignInResult.TwoFactorRequired; return SignInResult.TwoFactorRequired;
} }
} }
// Cleanup external cookie // Cleanup external cookie
if (loginProvider != null) if (loginProvider != null)
{ {
Context.Response.SignOut(IdentityOptions.ExternalCookieAuthenticationType); Context.Response.SignOut(IdentityOptions.ExternalCookieAuthenticationScheme);
} }
await SignInAsync(user, isPersistent, loginProvider); await SignInAsync(user, isPersistent, loginProvider);
return SignInResult.Success; return SignInResult.Success;
@ -385,13 +390,13 @@ namespace Microsoft.AspNet.Identity
private async Task<TwoFactorAuthenticationInfo> RetrieveTwoFactorInfoAsync() private async Task<TwoFactorAuthenticationInfo> RetrieveTwoFactorInfoAsync()
{ {
var result = await Context.AuthenticateAsync(IdentityOptions.TwoFactorUserIdCookieAuthenticationType); var result = await Context.AuthenticateAsync(IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme);
if (result != null && result.Identity != null) if (result?.Principal != null)
{ {
return new TwoFactorAuthenticationInfo return new TwoFactorAuthenticationInfo
{ {
UserId = result.Identity.Name, UserId = result.Principal.FindFirstValue(ClaimTypes.Name),
LoginProvider = result.Identity.FindFirstValue(ClaimTypes.AuthenticationMethod) LoginProvider = result.Principal.FindFirstValue(ClaimTypes.AuthenticationMethod)
}; };
} }
return null; return null;
@ -426,7 +431,7 @@ namespace Microsoft.AspNet.Identity
return status; return status;
} }
internal static ClaimsIdentity StoreTwoFactorInfo(string userId, string loginProvider) internal static ClaimsPrincipal StoreTwoFactorInfo(string userId, string loginProvider)
{ {
var identity = new ClaimsIdentity(IdentityOptions.TwoFactorUserIdCookieAuthenticationType); var identity = new ClaimsIdentity(IdentityOptions.TwoFactorUserIdCookieAuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, userId)); identity.AddClaim(new Claim(ClaimTypes.Name, userId));
@ -434,7 +439,7 @@ namespace Microsoft.AspNet.Identity
{ {
identity.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, loginProvider)); identity.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, loginProvider));
} }
return identity; return new ClaimsPrincipal(identity);
} }
internal class TwoFactorAuthenticationInfo internal class TwoFactorAuthenticationInfo

View File

@ -11,11 +11,11 @@ using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Identity namespace Microsoft.AspNet.Identity
{ {
/// <summary> /// <summary>
/// Provides methods to create a claims identity for a given user. /// Provides methods to create a claims principal for a given user.
/// </summary> /// </summary>
/// <typeparam name="TUser">The type used to represent a user.</typeparam> /// <typeparam name="TUser">The type used to represent a user.</typeparam>
/// <typeparam name="TRole">The type used to represent a role.</typeparam> /// <typeparam name="TRole">The type used to represent a role.</typeparam>
public class ClaimsIdentityFactory<TUser, TRole> : IClaimsIdentityFactory<TUser> public class UserClaimsPrincipalFactory<TUser, TRole> : IUserClaimsPrincipalFactory<TUser>
where TUser : class where TUser : class
where TRole : class where TRole : class
{ {
@ -25,7 +25,7 @@ namespace Microsoft.AspNet.Identity
/// <param name="userManager">The <see cref="UserManager{TUser}"/> to retrieve user information from.</param> /// <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="roleManager">The <see cref="RoleManager{TRole}"/> to retrieve a user's roles from.</param>
/// <param name="optionsAccessor">The configured <see cref="IdentityOptions"/>.</param> /// <param name="optionsAccessor">The configured <see cref="IdentityOptions"/>.</param>
public ClaimsIdentityFactory( public UserClaimsPrincipalFactory(
UserManager<TUser> userManager, UserManager<TUser> userManager,
RoleManager<TRole> roleManager, RoleManager<TRole> roleManager,
IOptions<IdentityOptions> optionsAccessor) IOptions<IdentityOptions> optionsAccessor)
@ -72,12 +72,11 @@ namespace Microsoft.AspNet.Identity
public IdentityOptions Options { get; private set; } public IdentityOptions Options { get; private set; }
/// <summary> /// <summary>
/// Creates a populated <see cref="ClaimsIdentity"/> for the specified <paramref name="user"/>. /// Creates a populated <see cref="ClaimsPrincipal"/> for the specified <paramref name="user"/>.
/// </summary> /// </summary>
/// <param name="user">The user instance to create claims on.</param> /// <param name="user">The user instance to create claims on.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe while waiting for the tasks to complete.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the started task.</returns> /// <returns>A <see cref="Task{TResult}"/> that represents the started task.</returns>
public virtual async Task<ClaimsIdentity> CreateAsync(TUser user) public virtual async Task<ClaimsPrincipal> CreateAsync(TUser user)
{ {
if (user == null) if (user == null)
{ {
@ -85,10 +84,11 @@ namespace Microsoft.AspNet.Identity
} }
var userId = await UserManager.GetUserIdAsync(user); var userId = await UserManager.GetUserIdAsync(user);
var userName = await UserManager.GetUserNameAsync(user); var userName = await UserManager.GetUserNameAsync(user);
var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationType, Options.ClaimsIdentity.UserNameClaimType, var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationType,
Options.ClaimsIdentity.UserNameClaimType,
Options.ClaimsIdentity.RoleClaimType); Options.ClaimsIdentity.RoleClaimType);
id.AddClaim(new Claim(Options.ClaimsIdentity.UserIdClaimType, userId)); id.AddClaim(new Claim(Options.ClaimsIdentity.UserIdClaimType, userId));
id.AddClaim(new Claim(Options.ClaimsIdentity.UserNameClaimType, userName, ClaimValueTypes.String)); id.AddClaim(new Claim(Options.ClaimsIdentity.UserNameClaimType, userName));
if (UserManager.SupportsUserSecurityStamp) if (UserManager.SupportsUserSecurityStamp)
{ {
id.AddClaim(new Claim(Options.ClaimsIdentity.SecurityStampClaimType, id.AddClaim(new Claim(Options.ClaimsIdentity.SecurityStampClaimType,
@ -99,7 +99,7 @@ namespace Microsoft.AspNet.Identity
var roles = await UserManager.GetRolesAsync(user); var roles = await UserManager.GetRolesAsync(user);
foreach (var roleName in roles) foreach (var roleName in roles)
{ {
id.AddClaim(new Claim(Options.ClaimsIdentity.RoleClaimType, roleName, ClaimValueTypes.String)); id.AddClaim(new Claim(Options.ClaimsIdentity.RoleClaimType, roleName));
if (RoleManager.SupportsRoleClaims) if (RoleManager.SupportsRoleClaims)
{ {
var role = await RoleManager.FindByNameAsync(roleName); var role = await RoleManager.FindByNameAsync(roleName);
@ -114,7 +114,7 @@ namespace Microsoft.AspNet.Identity
{ {
id.AddClaims(await UserManager.GetClaimsAsync(user)); id.AddClaims(await UserManager.GetClaimsAsync(user));
} }
return id; return new ClaimsPrincipal(id);
} }
} }
} }

View File

@ -1,14 +1,14 @@
{ {
"version": "3.0.0-*", "version": "3.0.0-*",
"dependencies": { "dependencies": {
"Microsoft.AspNet.Authentication" : "1.0.0-*",
"Microsoft.AspNet.Authentication.Cookies": "1.0.0-*",
"Microsoft.AspNet.Cryptography.KeyDerivation": "1.0.0-*", "Microsoft.AspNet.Cryptography.KeyDerivation": "1.0.0-*",
"Microsoft.AspNet.Http" : "1.0.0-*", "Microsoft.AspNet.Http" : "1.0.0-*",
"Microsoft.AspNet.Security" : "1.0.0-*",
"Microsoft.AspNet.Security.Cookies": "1.0.0-*",
"Microsoft.Framework.ConfigurationModel": "1.0.0-*", "Microsoft.Framework.ConfigurationModel": "1.0.0-*",
"Microsoft.Framework.DependencyInjection" : "1.0.0-*", "Microsoft.Framework.DependencyInjection" : "1.0.0-*",
"Microsoft.Framework.OptionsModel": "1.0.0-*", "Microsoft.Framework.Logging": "1.0.0-*",
"Microsoft.Framework.Logging": "1.0.0-*" "Microsoft.Framework.OptionsModel": "1.0.0-*"
}, },
"frameworks": { "frameworks": {
"aspnet50": {}, "aspnet50": {},

View File

@ -6,7 +6,7 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Builder; using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Security; using Microsoft.AspNet.Http.Authentication;
using Microsoft.AspNet.Identity.Test; using Microsoft.AspNet.Identity.Test;
using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.Runtime.Infrastructure; using Microsoft.Framework.Runtime.Infrastructure;
@ -30,7 +30,9 @@ namespace Microsoft.AspNet.Identity.InMemory.Test
var context = new Mock<HttpContext>(); var context = new Mock<HttpContext>();
var response = new Mock<HttpResponse>(); var response = new Mock<HttpResponse>();
context.Setup(c => c.Response).Returns(response.Object).Verifiable(); context.Setup(c => c.Response).Returns(response.Object).Verifiable();
response.Setup(r => r.SignIn(It.Is<AuthenticationProperties>(v => v.IsPersistent == isPersistent), It.IsAny<ClaimsIdentity>())).Verifiable(); response.Setup(r => r.SignIn(IdentityOptions.ApplicationCookieAuthenticationScheme,
It.IsAny<ClaimsPrincipal>(),
It.Is<AuthenticationProperties>(v => v.IsPersistent == isPersistent))).Verifiable();
var contextAccessor = new Mock<IHttpContextAccessor>(); var contextAccessor = new Mock<IHttpContextAccessor>();
contextAccessor.Setup(a => a.HttpContext).Returns(context.Object); contextAccessor.Setup(a => a.HttpContext).Returns(context.Object);
app.UseServices(services => app.UseServices(services =>

View File

@ -4,8 +4,8 @@
"Microsoft.AspNet.Http" : "1.0.0-*", "Microsoft.AspNet.Http" : "1.0.0-*",
"Microsoft.AspNet.Identity" : "3.0.0-*", "Microsoft.AspNet.Identity" : "3.0.0-*",
"Microsoft.AspNet.RequestContainer" : "1.0.0-*", "Microsoft.AspNet.RequestContainer" : "1.0.0-*",
"Microsoft.AspNet.Security" : "1.0.0-*", "Microsoft.AspNet.Authentication" : "1.0.0-*",
"Microsoft.AspNet.Security.Cookies" : "1.0.0-*", "Microsoft.AspNet.Authentication.Cookies" : "1.0.0-*",
"Microsoft.AspNet.Testing" : "1.0.0-*", "Microsoft.AspNet.Testing" : "1.0.0-*",
"Microsoft.Framework.ConfigurationModel": "1.0.0-*", "Microsoft.Framework.ConfigurationModel": "1.0.0-*",
"Microsoft.Framework.DependencyInjection" : "1.0.0-*", "Microsoft.Framework.DependencyInjection" : "1.0.0-*",

View File

@ -1,77 +0,0 @@
// Copyright (c) Microsoft Open Technologies, Inc. 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.Security.Principal;
using Xunit;
namespace Microsoft.AspNet.Identity.Test
{
public class ClaimsIdentityExtensionsTest
{
public const string ExternalAuthenticationType = "TestExternalAuth";
[Fact]
public void IdentityNullCheckTest()
{
IIdentity identity = null;
Assert.Throws<ArgumentNullException>("identity", () => identity.GetUserId());
Assert.Throws<ArgumentNullException>("identity", () => identity.GetUserName());
ClaimsIdentity claimsIdentity = null;
Assert.Throws<ArgumentNullException>("identity", () => claimsIdentity.FindFirstValue(null));
}
[Fact]
public void IdentityNullIfNotClaimsIdentityTest()
{
IIdentity identity = new TestIdentity();
Assert.Null(identity.GetUserId());
Assert.Null(identity.GetUserName());
}
[Fact]
public void UserNameAndIdTest()
{
var id = CreateTestExternalIdentity();
Assert.Equal("NameIdentifier", id.GetUserId());
Assert.Equal("Name", id.GetUserName());
}
[Fact]
public void IdentityExtensionsFindFirstValueNullIfUnknownTest()
{
var id = CreateTestExternalIdentity();
Assert.Null(id.FindFirstValue("bogus"));
}
private static ClaimsIdentity CreateTestExternalIdentity()
{
return new ClaimsIdentity(
new[]
{
new Claim(ClaimTypes.NameIdentifier, "NameIdentifier", null, ExternalAuthenticationType),
new Claim(ClaimTypes.Name, "Name")
},
ExternalAuthenticationType);
}
private class TestIdentity : IIdentity
{
public string AuthenticationType
{
get { throw new NotImplementedException(); }
}
public bool IsAuthenticated
{
get { throw new NotImplementedException(); }
}
public string Name
{
get { throw new NotImplementedException(); }
}
}
}
}

View File

@ -0,0 +1,120 @@
// Copyright (c) Microsoft Open Technologies, Inc. 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.Security.Principal;
using Xunit;
namespace Microsoft.AspNet.Identity.Test
{
public class ClaimsIdentityExtensionsTest
{
public const string ExternalAuthenticationScheme = "TestExternalAuth";
[Fact]
public void IdentityNullCheckTest()
{
IPrincipal p = null;
Assert.Throws<ArgumentNullException>("principal", () => p.GetUserId());
Assert.Throws<ArgumentNullException>("principal", () => p.GetUserName());
ClaimsPrincipal cp = null;
Assert.Throws<ArgumentNullException>("principal", () => cp.FindFirstValue(null));
}
[Fact]
public void IdentityNullIfNotClaimsIdentityTest()
{
IPrincipal identity = new TestPrincipal();
Assert.Null(identity.GetUserId());
Assert.Null(identity.GetUserName());
}
[Fact]
public void UserNameAndIdTest()
{
var p = CreateTestExternalIdentity();
Assert.Equal("NameIdentifier", p.GetUserId());
Assert.Equal("Name", p.GetUserName());
}
[Fact]
public void IdentityExtensionsFindFirstValueNullIfUnknownTest()
{
var id = CreateTestExternalIdentity();
Assert.Null(id.FindFirstValue("bogus"));
}
[Fact]
public void IsSignedInWithDefaultAppAuthenticationType()
{
var id = CreateAppIdentity();
Assert.True(id.IsSignedIn());
}
[Fact]
public void IsSignedInFalseWithWrongAppAuthenticationType()
{
var id = CreateAppIdentity("bogus");
Assert.False(id.IsSignedIn());
}
private static ClaimsPrincipal CreateAppIdentity(string authType = null)
{
authType = authType ?? IdentityOptions.ApplicationCookieAuthenticationType;
return new ClaimsPrincipal(new ClaimsIdentity(
new[]
{
new Claim(ClaimTypes.NameIdentifier, "NameIdentifier"),
new Claim(ClaimTypes.Name, "Name")
},
authType));
}
private static ClaimsPrincipal CreateTestExternalIdentity()
{
return new ClaimsPrincipal(new ClaimsIdentity(
new[]
{
new Claim(ClaimTypes.NameIdentifier, "NameIdentifier", null, ExternalAuthenticationScheme),
new Claim(ClaimTypes.Name, "Name")
},
ExternalAuthenticationScheme));
}
private class TestPrincipal : IPrincipal
{
public IIdentity Identity
{
get
{
throw new NotImplementedException();
}
}
public bool IsInRole(string role)
{
throw new NotImplementedException();
}
}
private class TestIdentity : IIdentity
{
public string AuthenticationType
{
get { throw new NotImplementedException(); }
}
public bool IsAuthenticated
{
get { throw new NotImplementedException(); }
}
public string Name
{
get { throw new NotImplementedException(); }
}
}
}
}

View File

@ -3,13 +3,12 @@
using System; using System;
using System.Security.Claims; using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Authentication;
using Microsoft.AspNet.Authentication.Cookies;
using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Security; using Microsoft.AspNet.Http.Authentication;
using Microsoft.AspNet.Security;
using Microsoft.AspNet.Security.Cookies;
using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback; using Microsoft.Framework.DependencyInjection.Fallback;
using Microsoft.Framework.OptionsModel; using Microsoft.Framework.OptionsModel;
@ -21,25 +20,25 @@ namespace Microsoft.AspNet.Identity.Test
public class SecurityStampTest public class SecurityStampTest
{ {
[Fact] [Fact]
public async Task OnValidateIdentityThrowsWithEmptyServiceCollection() public async Task OnValidatePrincipalThrowsWithEmptyServiceCollection()
{ {
var httpContext = new Mock<HttpContext>(); var httpContext = new Mock<HttpContext>();
httpContext.Setup(c => c.RequestServices).Returns(new ServiceCollection().BuildServiceProvider()); httpContext.Setup(c => c.RequestServices).Returns(new ServiceCollection().BuildServiceProvider());
var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationType); var id = new ClaimsPrincipal(new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationScheme));
var ticket = new AuthenticationTicket(id, new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow }); var ticket = new AuthenticationTicket(id, new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow }, IdentityOptions.ApplicationCookieAuthenticationScheme);
var context = new CookieValidateIdentityContext(httpContext.Object, ticket, new CookieAuthenticationOptions()); var context = new CookieValidatePrincipalContext(httpContext.Object, ticket, new CookieAuthenticationOptions());
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => SecurityStampValidator.ValidateIdentityAsync(context)); var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => SecurityStampValidator.ValidatePrincipalAsync(context));
Assert.True(ex.Message.Contains("No service for type 'Microsoft.Framework.OptionsModel.IOptions")); Assert.True(ex.Message.Contains("No service for type 'Microsoft.Framework.OptionsModel.IOptions"));
} }
[Theory] [Theory]
[InlineData(true)] [InlineData(true)]
[InlineData(false)] [InlineData(false)]
public async Task OnValidateIdentityTestSuccess(bool isPersistent) public async Task OnValidatePrincipalTestSuccess(bool isPersistent)
{ {
var user = new IdentityUser("test"); var user = new IdentityUser("test");
var userManager = MockHelpers.MockUserManager<IdentityUser>(); var userManager = MockHelpers.MockUserManager<IdentityUser>();
var claimsManager = new Mock<IClaimsIdentityFactory<IdentityUser>>(); var claimsManager = new Mock<IUserClaimsPrincipalFactory<IdentityUser>>();
var identityOptions = new IdentityOptions { SecurityStampValidationInterval = TimeSpan.Zero }; var identityOptions = new IdentityOptions { SecurityStampValidationInterval = TimeSpan.Zero };
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
@ -48,24 +47,26 @@ namespace Microsoft.AspNet.Identity.Test
contextAccessor.Setup(a => a.HttpContext).Returns(httpContext.Object); contextAccessor.Setup(a => a.HttpContext).Returns(httpContext.Object);
var signInManager = new Mock<SignInManager<IdentityUser>>(userManager.Object, var signInManager = new Mock<SignInManager<IdentityUser>>(userManager.Object,
contextAccessor.Object, claimsManager.Object, options.Object, null); contextAccessor.Object, claimsManager.Object, options.Object, null);
signInManager.Setup(s => s.ValidateSecurityStampAsync(It.IsAny<ClaimsIdentity>(), user.Id)).ReturnsAsync(user).Verifiable(); signInManager.Setup(s => s.ValidateSecurityStampAsync(It.IsAny<ClaimsPrincipal>(), user.Id)).ReturnsAsync(user).Verifiable();
signInManager.Setup(s => s.SignInAsync(user, isPersistent, null)).Returns(Task.FromResult(0)).Verifiable(); signInManager.Setup(s => s.SignInAsync(user, isPersistent, null)).Returns(Task.FromResult(0)).Verifiable();
var services = new ServiceCollection(); var services = new ServiceCollection();
services.AddInstance(options.Object); services.AddInstance(options.Object);
services.AddInstance(signInManager.Object); services.AddInstance(signInManager.Object);
services.AddInstance<ISecurityStampValidator>(new SecurityStampValidator<IdentityUser>()); services.AddInstance<ISecurityStampValidator>(new SecurityStampValidator<IdentityUser>());
httpContext.Setup(c => c.RequestServices).Returns(services.BuildServiceProvider()); httpContext.Setup(c => c.RequestServices).Returns(services.BuildServiceProvider());
var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationType); var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationScheme);
id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id)); id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id));
var ticket = new AuthenticationTicket(id, new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow, IsPersistent = isPersistent }); var ticket = new AuthenticationTicket(new ClaimsPrincipal(id),
var context = new CookieValidateIdentityContext(httpContext.Object, ticket, new CookieAuthenticationOptions()); new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow, IsPersistent = isPersistent },
IdentityOptions.ApplicationCookieAuthenticationScheme);
var context = new CookieValidatePrincipalContext(httpContext.Object, ticket, new CookieAuthenticationOptions());
Assert.NotNull(context.Properties); Assert.NotNull(context.Properties);
Assert.NotNull(context.Options); Assert.NotNull(context.Options);
Assert.NotNull(context.Identity); Assert.NotNull(context.Principal);
await await
SecurityStampValidator.ValidateIdentityAsync(context); SecurityStampValidator.ValidatePrincipalAsync(context);
Assert.NotNull(context.Identity); Assert.NotNull(context.Principal);
signInManager.VerifyAll(); signInManager.VerifyAll();
} }
@ -74,7 +75,7 @@ namespace Microsoft.AspNet.Identity.Test
{ {
var user = new IdentityUser("test"); var user = new IdentityUser("test");
var userManager = MockHelpers.MockUserManager<IdentityUser>(); var userManager = MockHelpers.MockUserManager<IdentityUser>();
var claimsManager = new Mock<IClaimsIdentityFactory<IdentityUser>>(); var claimsManager = new Mock<IUserClaimsPrincipalFactory<IdentityUser>>();
var identityOptions = new IdentityOptions { SecurityStampValidationInterval = TimeSpan.Zero }; var identityOptions = new IdentityOptions { SecurityStampValidationInterval = TimeSpan.Zero };
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
@ -83,23 +84,24 @@ namespace Microsoft.AspNet.Identity.Test
contextAccessor.Setup(a => a.HttpContext).Returns(httpContext.Object); contextAccessor.Setup(a => a.HttpContext).Returns(httpContext.Object);
var signInManager = new Mock<SignInManager<IdentityUser>>(userManager.Object, var signInManager = new Mock<SignInManager<IdentityUser>>(userManager.Object,
contextAccessor.Object, claimsManager.Object, options.Object, null); contextAccessor.Object, claimsManager.Object, options.Object, null);
signInManager.Setup(s => s.ValidateSecurityStampAsync(It.IsAny<ClaimsIdentity>(), user.Id)).ReturnsAsync(null).Verifiable(); signInManager.Setup(s => s.ValidateSecurityStampAsync(It.IsAny<ClaimsPrincipal>(), user.Id)).ReturnsAsync(null).Verifiable();
var services = new ServiceCollection(); var services = new ServiceCollection();
services.AddInstance(options.Object); services.AddInstance(options.Object);
services.AddInstance(signInManager.Object); services.AddInstance(signInManager.Object);
services.AddInstance<ISecurityStampValidator>(new SecurityStampValidator<IdentityUser>()); services.AddInstance<ISecurityStampValidator>(new SecurityStampValidator<IdentityUser>());
httpContext.Setup(c => c.RequestServices).Returns(services.BuildServiceProvider()); httpContext.Setup(c => c.RequestServices).Returns(services.BuildServiceProvider());
var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationType); var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationScheme);
id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id)); id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id));
var ticket = new AuthenticationTicket(id, new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow }); var ticket = new AuthenticationTicket(new ClaimsPrincipal(id),
var context = new CookieValidateIdentityContext(httpContext.Object, ticket, new CookieAuthenticationOptions()); new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow },
IdentityOptions.ApplicationCookieAuthenticationScheme);
var context = new CookieValidatePrincipalContext(httpContext.Object, ticket, new CookieAuthenticationOptions());
Assert.NotNull(context.Properties); Assert.NotNull(context.Properties);
Assert.NotNull(context.Options); Assert.NotNull(context.Options);
Assert.NotNull(context.Identity); Assert.NotNull(context.Principal);
await await SecurityStampValidator.ValidatePrincipalAsync(context);
SecurityStampValidator.ValidateIdentityAsync(context); Assert.Null(context.Principal);
Assert.Null(context.Identity);
signInManager.VerifyAll(); signInManager.VerifyAll();
} }
@ -109,7 +111,7 @@ namespace Microsoft.AspNet.Identity.Test
var user = new IdentityUser("test"); var user = new IdentityUser("test");
var httpContext = new Mock<HttpContext>(); var httpContext = new Mock<HttpContext>();
var userManager = MockHelpers.MockUserManager<IdentityUser>(); var userManager = MockHelpers.MockUserManager<IdentityUser>();
var claimsManager = new Mock<IClaimsIdentityFactory<IdentityUser>>(); var claimsManager = new Mock<IUserClaimsPrincipalFactory<IdentityUser>>();
var identityOptions = new IdentityOptions { SecurityStampValidationInterval = TimeSpan.Zero }; var identityOptions = new IdentityOptions { SecurityStampValidationInterval = TimeSpan.Zero };
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
@ -117,23 +119,24 @@ namespace Microsoft.AspNet.Identity.Test
contextAccessor.Setup(a => a.HttpContext).Returns(httpContext.Object); contextAccessor.Setup(a => a.HttpContext).Returns(httpContext.Object);
var signInManager = new Mock<SignInManager<IdentityUser>>(userManager.Object, var signInManager = new Mock<SignInManager<IdentityUser>>(userManager.Object,
contextAccessor.Object, claimsManager.Object, options.Object, null); contextAccessor.Object, claimsManager.Object, options.Object, null);
signInManager.Setup(s => s.ValidateSecurityStampAsync(It.IsAny<ClaimsIdentity>(), user.Id)).ReturnsAsync(null).Verifiable(); signInManager.Setup(s => s.ValidateSecurityStampAsync(It.IsAny<ClaimsPrincipal>(), user.Id)).ReturnsAsync(null).Verifiable();
var services = new ServiceCollection(); var services = new ServiceCollection();
services.AddInstance(options.Object); services.AddInstance(options.Object);
services.AddInstance(signInManager.Object); services.AddInstance(signInManager.Object);
services.AddInstance<ISecurityStampValidator>(new SecurityStampValidator<IdentityUser>()); services.AddInstance<ISecurityStampValidator>(new SecurityStampValidator<IdentityUser>());
httpContext.Setup(c => c.RequestServices).Returns(services.BuildServiceProvider()); httpContext.Setup(c => c.RequestServices).Returns(services.BuildServiceProvider());
var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationType); var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationScheme);
id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id)); id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id));
var ticket = new AuthenticationTicket(id, new AuthenticationProperties()); var ticket = new AuthenticationTicket(new ClaimsPrincipal(id),
var context = new CookieValidateIdentityContext(httpContext.Object, ticket, new CookieAuthenticationOptions()); new AuthenticationProperties(),
IdentityOptions.ApplicationCookieAuthenticationScheme);
var context = new CookieValidatePrincipalContext(httpContext.Object, ticket, new CookieAuthenticationOptions());
Assert.NotNull(context.Properties); Assert.NotNull(context.Properties);
Assert.NotNull(context.Options); Assert.NotNull(context.Options);
Assert.NotNull(context.Identity); Assert.NotNull(context.Principal);
await await SecurityStampValidator.ValidatePrincipalAsync(context);
SecurityStampValidator.ValidateIdentityAsync(context); Assert.Null(context.Principal);
Assert.Null(context.Identity);
signInManager.VerifyAll(); signInManager.VerifyAll();
} }
@ -143,7 +146,7 @@ namespace Microsoft.AspNet.Identity.Test
var user = new IdentityUser("test"); var user = new IdentityUser("test");
var httpContext = new Mock<HttpContext>(); var httpContext = new Mock<HttpContext>();
var userManager = MockHelpers.MockUserManager<IdentityUser>(); var userManager = MockHelpers.MockUserManager<IdentityUser>();
var claimsManager = new Mock<IClaimsIdentityFactory<IdentityUser>>(); var claimsManager = new Mock<IUserClaimsPrincipalFactory<IdentityUser>>();
var identityOptions = new IdentityOptions { SecurityStampValidationInterval = TimeSpan.FromDays(1) }; var identityOptions = new IdentityOptions { SecurityStampValidationInterval = TimeSpan.FromDays(1) };
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
@ -151,24 +154,25 @@ namespace Microsoft.AspNet.Identity.Test
contextAccessor.Setup(a => a.HttpContext).Returns(httpContext.Object); contextAccessor.Setup(a => a.HttpContext).Returns(httpContext.Object);
var signInManager = new Mock<SignInManager<IdentityUser>>(userManager.Object, var signInManager = new Mock<SignInManager<IdentityUser>>(userManager.Object,
contextAccessor.Object, claimsManager.Object, options.Object, null); contextAccessor.Object, claimsManager.Object, options.Object, null);
signInManager.Setup(s => s.ValidateSecurityStampAsync(It.IsAny<ClaimsIdentity>(), user.Id)).Throws(new Exception("Shouldn't be called")); signInManager.Setup(s => s.ValidateSecurityStampAsync(It.IsAny<ClaimsPrincipal>(), user.Id)).Throws(new Exception("Shouldn't be called"));
signInManager.Setup(s => s.SignInAsync(user, false, null)).Throws(new Exception("Shouldn't be called")); signInManager.Setup(s => s.SignInAsync(user, false, null)).Throws(new Exception("Shouldn't be called"));
var services = new ServiceCollection(); var services = new ServiceCollection();
services.AddInstance(options.Object); services.AddInstance(options.Object);
services.AddInstance(signInManager.Object); services.AddInstance(signInManager.Object);
services.AddInstance<ISecurityStampValidator>(new SecurityStampValidator<IdentityUser>()); services.AddInstance<ISecurityStampValidator>(new SecurityStampValidator<IdentityUser>());
httpContext.Setup(c => c.RequestServices).Returns(services.BuildServiceProvider()); httpContext.Setup(c => c.RequestServices).Returns(services.BuildServiceProvider());
var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationType); var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationScheme);
id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id)); id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id));
var ticket = new AuthenticationTicket(id, new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow }); var ticket = new AuthenticationTicket(new ClaimsPrincipal(id),
var context = new CookieValidateIdentityContext(httpContext.Object, ticket, new CookieAuthenticationOptions()); new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow },
IdentityOptions.ApplicationCookieAuthenticationScheme);
var context = new CookieValidatePrincipalContext(httpContext.Object, ticket, new CookieAuthenticationOptions());
Assert.NotNull(context.Properties); Assert.NotNull(context.Properties);
Assert.NotNull(context.Options); Assert.NotNull(context.Options);
Assert.NotNull(context.Identity); Assert.NotNull(context.Principal);
await await SecurityStampValidator.ValidatePrincipalAsync(context);
SecurityStampValidator.ValidateIdentityAsync(context); Assert.NotNull(context.Principal);
Assert.NotNull(context.Identity);
} }
} }
} }

View File

@ -3,15 +3,14 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Security.Claims; using System.Security.Claims;
using System.Security.Principal; using System.Security.Principal;
using System.Text; using System.Text;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Security; using Microsoft.AspNet.Http.Authentication;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel; using Microsoft.Framework.OptionsModel;
using Moq; using Moq;
using Xunit; using Xunit;
@ -28,7 +27,7 @@ namespace Microsoft.AspNet.Identity.Test
// var app = new ApplicationBuilder(new ServiceCollection().BuildServiceProvider()); // var app = new ApplicationBuilder(new ServiceCollection().BuildServiceProvider());
// app.UseCookieAuthentication(new CookieAuthenticationOptions // app.UseCookieAuthentication(new CookieAuthenticationOptions
// { // {
// AuthenticationType = ClaimsIdentityOptions.DefaultAuthenticationType // AuthenticationScheme = ClaimsIdentityOptions.DefaultAuthenticationScheme
// }); // });
// TODO: how to functionally test context? // TODO: how to functionally test context?
@ -63,7 +62,7 @@ namespace Microsoft.AspNet.Identity.Test
// // Assert // // Assert
// Assert.Equal(SignInStatus.Success, result); // Assert.Equal(SignInStatus.Success, result);
// contextAccessor.VerifyAll(); // contextAccessor.Verify();
//} //}
[Fact] [Fact]
@ -81,16 +80,16 @@ namespace Microsoft.AspNet.Identity.Test
//TODO: Mock fails in K (this works fine in net45) //TODO: Mock fails in K (this works fine in net45)
//[Fact] //[Fact]
//public async Task EnsureClaimsIdentityFactoryCreateIdentityCalled() //public async Task EnsureClaimsPrincipalFactoryCreateIdentityCalled()
//{ //{
// // Setup // // Setup
// var user = new TestUser { UserName = "Foo" }; // var user = new TestUser { UserName = "Foo" };
// var userManager = MockHelpers.TestUserManager<TestUser>(); // var userManager = MockHelpers.TestUserManager<TestUser>();
// var identityFactory = new Mock<IClaimsIdentityFactory<TestUser>>(); // var identityFactory = new Mock<IUserClaimsPrincipalFactory<TestUser>>();
// const string authType = "Test"; // const string authType = "Test";
// var testIdentity = new ClaimsIdentity(authType); // var testIdentity = new ClaimsIdentity(authType);
// identityFactory.Setup(s => s.CreateAsync(userManager, user, authType)).ReturnsAsync(testIdentity).Verifiable(); // identityFactory.Setup(s => s.CreateAsync(userManager, user, authType)).ReturnsAsync(testIdentity).Verifiable();
// userManager.ClaimsIdentityFactory = identityFactory.Object; // userManager.UserClaimsPrincipalFactory = identityFactory.Object;
// var context = new Mock<HttpContext>(); // var context = new Mock<HttpContext>();
// var response = new Mock<HttpResponse>(); // var response = new Mock<HttpResponse>();
// context.Setup(c => c.Response).Returns(response.Object).Verifiable(); // context.Setup(c => c.Response).Returns(response.Object).Verifiable();
@ -103,10 +102,10 @@ namespace Microsoft.AspNet.Identity.Test
// helper.SignIn(user, false); // helper.SignIn(user, false);
// // Assert // // Assert
// identityFactory.VerifyAll(); // identityFactory.Verify();
// context.VerifyAll(); // context.Verify();
// contextAccessor.VerifyAll(); // contextAccessor.Verify();
// response.VerifyAll(); // response.Verify();
//} //}
[Fact] [Fact]
@ -114,11 +113,9 @@ namespace Microsoft.AspNet.Identity.Test
{ {
// Setup // Setup
var user = new TestUser { UserName = "Foo" }; var user = new TestUser { UserName = "Foo" };
var manager = MockHelpers.MockUserManager<TestUser>(); var manager = SetupUserManager(user);
manager.Setup(m => m.SupportsUserLockout).Returns(true).Verifiable(); manager.Setup(m => m.SupportsUserLockout).Returns(true).Verifiable();
manager.Setup(m => m.IsLockedOutAsync(user)).ReturnsAsync(true).Verifiable(); manager.Setup(m => m.IsLockedOutAsync(user)).ReturnsAsync(true).Verifiable();
manager.Setup(m => m.FindByNameAsync(user.UserName)).ReturnsAsync(user).Verifiable();
manager.Setup(m => m.GetUserIdAsync(user)).ReturnsAsync(user.Id.ToString()).Verifiable();
var context = new Mock<HttpContext>(); var context = new Mock<HttpContext>();
var contextAccessor = new Mock<IHttpContextAccessor>(); var contextAccessor = new Mock<IHttpContextAccessor>();
@ -127,10 +124,10 @@ namespace Microsoft.AspNet.Identity.Test
var identityOptions = new IdentityOptions(); var identityOptions = new IdentityOptions();
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object); var claimsFactory = new UserClaimsPrincipalFactory<TestUser, TestRole>(manager.Object, roleManager.Object, options.Object);
var logStore = new StringBuilder(); var logStore = new StringBuilder();
var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore); var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore);
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object, logger.Object); var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory, options.Object, logger.Object);
string expected = string.Format("{0} for user: {1} : Result : {2}", "PasswordSignInAsync", user.Id, "Lockedout"); string expected = string.Format("{0} for user: {1} : Result : {2}", "PasswordSignInAsync", user.Id, "Lockedout");
// Act // Act
@ -140,7 +137,17 @@ namespace Microsoft.AspNet.Identity.Test
Assert.False(result.Succeeded); Assert.False(result.Succeeded);
Assert.True(result.IsLockedOut); Assert.True(result.IsLockedOut);
Assert.NotEqual(-1, logStore.ToString().IndexOf(expected)); Assert.NotEqual(-1, logStore.ToString().IndexOf(expected));
manager.VerifyAll(); manager.Verify();
}
private static Mock<UserManager<TestUser>> SetupUserManager(TestUser user)
{
var manager = MockHelpers.MockUserManager<TestUser>();
manager.Setup(m => m.FindByNameAsync(user.UserName)).ReturnsAsync(user);
manager.Setup(m => m.FindByIdAsync(user.Id)).ReturnsAsync(user);
manager.Setup(m => m.GetUserIdAsync(user)).ReturnsAsync(user.Id.ToString());
manager.Setup(m => m.GetUserNameAsync(user)).ReturnsAsync(user.UserName);
return manager;
} }
[Theory] [Theory]
@ -150,29 +157,25 @@ namespace Microsoft.AspNet.Identity.Test
{ {
// Setup // Setup
var user = new TestUser { UserName = "Foo" }; var user = new TestUser { UserName = "Foo" };
var manager = MockHelpers.MockUserManager<TestUser>(); var manager = SetupUserManager(user);
manager.Setup(m => m.SupportsUserLockout).Returns(true).Verifiable(); manager.Setup(m => m.SupportsUserLockout).Returns(true).Verifiable();
manager.Setup(m => m.IsLockedOutAsync(user)).ReturnsAsync(false).Verifiable(); manager.Setup(m => m.IsLockedOutAsync(user)).ReturnsAsync(false).Verifiable();
manager.Setup(m => m.FindByNameAsync(user.UserName)).ReturnsAsync(user).Verifiable();
manager.Setup(m => m.CheckPasswordAsync(user, "password")).ReturnsAsync(true).Verifiable(); manager.Setup(m => m.CheckPasswordAsync(user, "password")).ReturnsAsync(true).Verifiable();
manager.Setup(m => m.ResetAccessFailedCountAsync(user)).ReturnsAsync(IdentityResult.Success).Verifiable();
manager.Setup(m => m.GetUserIdAsync(user)).ReturnsAsync(user.Id.ToString()).Verifiable();
var context = new Mock<HttpContext>(); var context = new Mock<HttpContext>();
var response = new Mock<HttpResponse>(); var response = new Mock<HttpResponse>();
context.Setup(c => c.Response).Returns(response.Object).Verifiable(); context.Setup(c => c.Response).Returns(response.Object).Verifiable();
response.Setup(r => r.SignIn(It.Is<AuthenticationProperties>(v => v.IsPersistent == isPersistent), It.IsAny<ClaimsIdentity>())).Verifiable(); SetupSignIn(response, user.Id, isPersistent);
var contextAccessor = new Mock<IHttpContextAccessor>(); var contextAccessor = new Mock<IHttpContextAccessor>();
contextAccessor.Setup(a => a.HttpContext).Returns(context.Object); contextAccessor.Setup(a => a.HttpContext).Returns(context.Object);
var roleManager = MockHelpers.MockRoleManager<TestRole>(); var roleManager = MockHelpers.MockRoleManager<TestRole>();
var identityOptions = new IdentityOptions(); var identityOptions = new IdentityOptions();
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object); var claimsFactory = new UserClaimsPrincipalFactory<TestUser, TestRole>(manager.Object, roleManager.Object, options.Object);
claimsFactory.Setup(m => m.CreateAsync(user)).ReturnsAsync(new ClaimsIdentity("Microsoft.AspNet.Identity")).Verifiable();
var logStore = new StringBuilder(); var logStore = new StringBuilder();
var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore); var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore);
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object, logger.Object); var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory, options.Object, logger.Object);
string expected = string.Format("{0} for user: {1} : Result : {2}", "PasswordSignInAsync", user.Id, "Succeeded"); string expected = string.Format("{0} for user: {1} : Result : {2}", "PasswordSignInAsync", user.Id, "Succeeded");
// Act // Act
@ -181,11 +184,10 @@ namespace Microsoft.AspNet.Identity.Test
// Assert // Assert
Assert.True(result.Succeeded); Assert.True(result.Succeeded);
Assert.NotEqual(-1, logStore.ToString().IndexOf(expected)); Assert.NotEqual(-1, logStore.ToString().IndexOf(expected));
manager.VerifyAll(); manager.Verify();
context.VerifyAll(); context.Verify();
response.VerifyAll(); response.Verify();
contextAccessor.VerifyAll(); contextAccessor.Verify();
claimsFactory.VerifyAll();
} }
[Fact] [Fact]
@ -193,17 +195,15 @@ namespace Microsoft.AspNet.Identity.Test
{ {
// Setup // Setup
var user = new TestUser { UserName = "Foo" }; var user = new TestUser { UserName = "Foo" };
var manager = MockHelpers.MockUserManager<TestUser>(); var manager = SetupUserManager(user);
manager.Setup(m => m.SupportsUserLockout).Returns(true).Verifiable(); manager.Setup(m => m.SupportsUserLockout).Returns(true).Verifiable();
manager.Setup(m => m.IsLockedOutAsync(user)).ReturnsAsync(false).Verifiable(); manager.Setup(m => m.IsLockedOutAsync(user)).ReturnsAsync(false).Verifiable();
manager.Setup(m => m.FindByNameAsync(user.UserName)).ReturnsAsync(user).Verifiable();
manager.Setup(m => m.CheckPasswordAsync(user, "password")).ReturnsAsync(true).Verifiable(); manager.Setup(m => m.CheckPasswordAsync(user, "password")).ReturnsAsync(true).Verifiable();
manager.Setup(m => m.ResetAccessFailedCountAsync(user)).ReturnsAsync(IdentityResult.Success).Verifiable(); manager.Setup(m => m.ResetAccessFailedCountAsync(user)).ReturnsAsync(IdentityResult.Success).Verifiable();
manager.Setup(m => m.GetUserIdAsync(user)).ReturnsAsync(user.Id.ToString()).Verifiable();
var context = new Mock<HttpContext>(); var context = new Mock<HttpContext>();
var response = new Mock<HttpResponse>(); var response = new Mock<HttpResponse>();
response.Setup(r => r.SignIn(It.IsAny<AuthenticationProperties>(), It.IsAny<ClaimsIdentity>())).Verifiable(); SetupSignIn(response);
context.Setup(c => c.Response).Returns(response.Object).Verifiable(); context.Setup(c => c.Response).Returns(response.Object).Verifiable();
var contextAccessor = new Mock<IHttpContextAccessor>(); var contextAccessor = new Mock<IHttpContextAccessor>();
contextAccessor.Setup(a => a.HttpContext).Returns(context.Object); contextAccessor.Setup(a => a.HttpContext).Returns(context.Object);
@ -211,18 +211,18 @@ namespace Microsoft.AspNet.Identity.Test
var identityOptions = new IdentityOptions(); var identityOptions = new IdentityOptions();
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object); var claimsFactory = new UserClaimsPrincipalFactory<TestUser, TestRole>(manager.Object, roleManager.Object, options.Object);
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object); var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory, options.Object);
// Act // Act
var result = await helper.PasswordSignInAsync(user.UserName, "password", false, false); var result = await helper.PasswordSignInAsync(user.UserName, "password", false, false);
// Assert // Assert
Assert.True(result.Succeeded); Assert.True(result.Succeeded);
manager.VerifyAll(); manager.Verify();
context.VerifyAll(); context.Verify();
response.VerifyAll(); response.Verify();
contextAccessor.VerifyAll(); contextAccessor.Verify();
} }
[Theory] [Theory]
@ -232,7 +232,7 @@ namespace Microsoft.AspNet.Identity.Test
{ {
// Setup // Setup
var user = new TestUser { UserName = "Foo" }; var user = new TestUser { UserName = "Foo" };
var manager = MockHelpers.MockUserManager<TestUser>(); var manager = SetupUserManager(user);
manager.Setup(m => m.SupportsUserLockout).Returns(supportsLockout).Verifiable(); manager.Setup(m => m.SupportsUserLockout).Returns(supportsLockout).Verifiable();
if (supportsLockout) if (supportsLockout)
{ {
@ -243,8 +243,6 @@ namespace Microsoft.AspNet.Identity.Test
manager.Setup(m => m.GetValidTwoFactorProvidersAsync(user)).Returns(Task.FromResult(providers)).Verifiable(); manager.Setup(m => m.GetValidTwoFactorProvidersAsync(user)).Returns(Task.FromResult(providers)).Verifiable();
manager.Setup(m => m.SupportsUserTwoFactor).Returns(true).Verifiable(); manager.Setup(m => m.SupportsUserTwoFactor).Returns(true).Verifiable();
manager.Setup(m => m.GetTwoFactorEnabledAsync(user)).ReturnsAsync(true).Verifiable(); manager.Setup(m => m.GetTwoFactorEnabledAsync(user)).ReturnsAsync(true).Verifiable();
manager.Setup(m => m.FindByNameAsync(user.UserName)).ReturnsAsync(user).Verifiable();
manager.Setup(m => m.GetUserIdAsync(user)).ReturnsAsync(user.Id).Verifiable();
manager.Setup(m => m.CheckPasswordAsync(user, "password")).ReturnsAsync(true).Verifiable(); manager.Setup(m => m.CheckPasswordAsync(user, "password")).ReturnsAsync(true).Verifiable();
if (supportsLockout) if (supportsLockout)
{ {
@ -252,7 +250,9 @@ namespace Microsoft.AspNet.Identity.Test
} }
var context = new Mock<HttpContext>(); var context = new Mock<HttpContext>();
var response = new Mock<HttpResponse>(); var response = new Mock<HttpResponse>();
response.Setup(r => r.SignIn(It.Is<ClaimsIdentity>(id => id.Name == user.Id))).Verifiable(); response.Setup(r => r.SignIn(IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme,
It.Is<ClaimsPrincipal>(id => id.FindFirstValue(ClaimTypes.Name) == user.Id),
It.IsAny<AuthenticationProperties>())).Verifiable();
context.Setup(c => c.Response).Returns(response.Object).Verifiable(); context.Setup(c => c.Response).Returns(response.Object).Verifiable();
var contextAccessor = new Mock<IHttpContextAccessor>(); var contextAccessor = new Mock<IHttpContextAccessor>();
contextAccessor.Setup(a => a.HttpContext).Returns(context.Object); contextAccessor.Setup(a => a.HttpContext).Returns(context.Object);
@ -262,7 +262,11 @@ namespace Microsoft.AspNet.Identity.Test
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
var logStore = new StringBuilder(); var logStore = new StringBuilder();
var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore); var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore);
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, new ClaimsIdentityFactory<TestUser, TestRole>(manager.Object, roleManager.Object, options.Object), options.Object, logger.Object); var helper = new SignInManager<TestUser>(manager.Object,
contextAccessor.Object,
new UserClaimsPrincipalFactory<TestUser, TestRole>(manager.Object, roleManager.Object, options.Object),
options.Object,
logger.Object);
string expected = string.Format("{0} for user: {1} : Result : {2}", "PasswordSignInAsync", user.Id, "RequiresTwoFactor"); string expected = string.Format("{0} for user: {1} : Result : {2}", "PasswordSignInAsync", user.Id, "RequiresTwoFactor");
// Act // Act
@ -272,10 +276,10 @@ namespace Microsoft.AspNet.Identity.Test
Assert.False(result.Succeeded); Assert.False(result.Succeeded);
Assert.True(result.RequiresTwoFactor); Assert.True(result.RequiresTwoFactor);
Assert.NotEqual(-1, logStore.ToString().IndexOf(expected)); Assert.NotEqual(-1, logStore.ToString().IndexOf(expected));
manager.VerifyAll(); manager.Verify();
context.VerifyAll(); context.Verify();
response.VerifyAll(); response.Verify();
contextAccessor.VerifyAll(); contextAccessor.Verify();
} }
[Theory] [Theory]
@ -289,33 +293,29 @@ namespace Microsoft.AspNet.Identity.Test
var user = new TestUser { UserName = "Foo" }; var user = new TestUser { UserName = "Foo" };
const string loginProvider = "login"; const string loginProvider = "login";
const string providerKey = "fookey"; const string providerKey = "fookey";
var manager = MockHelpers.MockUserManager<TestUser>(); var manager = SetupUserManager(user);
manager.Setup(m => m.SupportsUserLockout).Returns(supportsLockout).Verifiable(); manager.Setup(m => m.SupportsUserLockout).Returns(supportsLockout).Verifiable();
if (supportsLockout) if (supportsLockout)
{ {
manager.Setup(m => m.IsLockedOutAsync(user)).ReturnsAsync(false).Verifiable(); manager.Setup(m => m.IsLockedOutAsync(user)).ReturnsAsync(false).Verifiable();
} }
manager.Setup(m => m.FindByLoginAsync(loginProvider, providerKey)).ReturnsAsync(user).Verifiable(); manager.Setup(m => m.FindByLoginAsync(loginProvider, providerKey)).ReturnsAsync(user).Verifiable();
manager.Setup(m => m.GetUserIdAsync(user)).ReturnsAsync(user.Id.ToString()).Verifiable();
var context = new Mock<HttpContext>(); var context = new Mock<HttpContext>();
var response = new Mock<HttpResponse>(); var response = new Mock<HttpResponse>();
context.Setup(c => c.Response).Returns(response.Object).Verifiable(); context.Setup(c => c.Response).Returns(response.Object).Verifiable();
response.Setup(r => r.SignIn( SetupSignIn(response, user.Id, isPersistent, loginProvider);
It.Is<AuthenticationProperties>(v => v.IsPersistent == isPersistent),
It.Is<ClaimsIdentity>(i => i.FindFirstValue(ClaimTypes.AuthenticationMethod) == loginProvider))).Verifiable();
var contextAccessor = new Mock<IHttpContextAccessor>(); var contextAccessor = new Mock<IHttpContextAccessor>();
contextAccessor.Setup(a => a.HttpContext).Returns(context.Object); contextAccessor.Setup(a => a.HttpContext).Returns(context.Object);
var roleManager = MockHelpers.MockRoleManager<TestRole>(); var roleManager = MockHelpers.MockRoleManager<TestRole>();
var identityOptions = new IdentityOptions(); var identityOptions = new IdentityOptions();
response.Setup(r => r.SignOut(IdentityOptions.ExternalCookieAuthenticationType)).Verifiable(); response.Setup(r => r.SignOut(IdentityOptions.ExternalCookieAuthenticationScheme)).Verifiable();
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object); var claimsFactory = new UserClaimsPrincipalFactory<TestUser, TestRole>(manager.Object, roleManager.Object, options.Object);
claimsFactory.Setup(m => m.CreateAsync(user)).ReturnsAsync(new ClaimsIdentity("Microsoft.AspNet.Identity")).Verifiable();
var logStore = new StringBuilder(); var logStore = new StringBuilder();
var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore); var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore);
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object, logger.Object); var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory, options.Object, logger.Object);
string expected = string.Format("{0} for user: {1} : Result : {2}", "ExternalLoginSignInAsync", user.Id.ToString(), "Succeeded"); string expected = string.Format("{0} for user: {1} : Result : {2}", "ExternalLoginSignInAsync", user.Id.ToString(), "Succeeded");
// Act // Act
@ -324,11 +324,10 @@ namespace Microsoft.AspNet.Identity.Test
// Assert // Assert
Assert.True(result.Succeeded); Assert.True(result.Succeeded);
Assert.NotEqual(-1, logStore.ToString().IndexOf(expected)); Assert.NotEqual(-1, logStore.ToString().IndexOf(expected));
manager.VerifyAll(); manager.Verify();
context.VerifyAll(); context.Verify();
response.VerifyAll(); response.Verify();
contextAccessor.VerifyAll(); contextAccessor.Verify();
claimsFactory.VerifyAll();
} }
[Theory] [Theory]
@ -352,7 +351,7 @@ namespace Microsoft.AspNet.Identity.Test
{ {
// Setup // Setup
var user = new TestUser { UserName = "Foo" }; var user = new TestUser { UserName = "Foo" };
var manager = MockHelpers.MockUserManager<TestUser>(); var manager = SetupUserManager(user);
var provider = "twofactorprovider"; var provider = "twofactorprovider";
var code = "123456"; var code = "123456";
manager.Setup(m => m.SupportsUserLockout).Returns(supportsLockout).Verifiable(); manager.Setup(m => m.SupportsUserLockout).Returns(supportsLockout).Verifiable();
@ -361,10 +360,7 @@ namespace Microsoft.AspNet.Identity.Test
manager.Setup(m => m.IsLockedOutAsync(user)).ReturnsAsync(false).Verifiable(); manager.Setup(m => m.IsLockedOutAsync(user)).ReturnsAsync(false).Verifiable();
manager.Setup(m => m.ResetAccessFailedCountAsync(user)).ReturnsAsync(IdentityResult.Success).Verifiable(); manager.Setup(m => m.ResetAccessFailedCountAsync(user)).ReturnsAsync(IdentityResult.Success).Verifiable();
} }
manager.Setup(m => m.FindByIdAsync(user.Id)).ReturnsAsync(user).Verifiable();
manager.Setup(m => m.VerifyTwoFactorTokenAsync(user, provider, code)).ReturnsAsync(true).Verifiable(); manager.Setup(m => m.VerifyTwoFactorTokenAsync(user, provider, code)).ReturnsAsync(true).Verifiable();
manager.Setup(m => m.GetUserIdAsync(user)).ReturnsAsync(user.Id).Verifiable();
manager.Setup(m => m.GetUserNameAsync(user)).ReturnsAsync(user.UserName).Verifiable();
var context = new Mock<HttpContext>(); var context = new Mock<HttpContext>();
var response = new Mock<HttpResponse>(); var response = new Mock<HttpResponse>();
var contextAccessor = new Mock<IHttpContextAccessor>(); var contextAccessor = new Mock<IHttpContextAccessor>();
@ -376,30 +372,30 @@ namespace Microsoft.AspNet.Identity.Test
var identityOptions = new IdentityOptions(); var identityOptions = new IdentityOptions();
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
var claimsFactory = new ClaimsIdentityFactory<TestUser, TestRole>(manager.Object, roleManager.Object, options.Object); var claimsFactory = new UserClaimsPrincipalFactory<TestUser, TestRole>(manager.Object, roleManager.Object, options.Object);
if (externalLogin) if (externalLogin)
{ {
response.Setup(r => r.SignIn( response.Setup(r => r.SignIn(
It.Is<AuthenticationProperties>(v => v.IsPersistent == isPersistent), IdentityOptions.ApplicationCookieAuthenticationScheme,
It.Is<ClaimsIdentity>(i => i.FindFirstValue(ClaimTypes.NameIdentifier) == user.Id It.Is<ClaimsPrincipal>(i => i.FindFirstValue(ClaimTypes.AuthenticationMethod) == loginProvider
&& i.FindFirstValue(ClaimTypes.AuthenticationMethod) == loginProvider))).Verifiable(); && i.FindFirstValue(ClaimTypes.NameIdentifier) == user.Id),
response.Setup(r => r.SignOut(IdentityOptions.ExternalCookieAuthenticationType)).Verifiable(); It.Is<AuthenticationProperties>(v => v.IsPersistent == isPersistent))).Verifiable();
response.Setup(r => r.SignOut(IdentityOptions.ExternalCookieAuthenticationScheme)).Verifiable();
} }
else else
{ {
response.Setup(r => r.SignIn( SetupSignIn(response, user.Id);
It.Is<AuthenticationProperties>(v => v.IsPersistent == isPersistent),
It.Is<ClaimsIdentity>(i => i.FindFirstValue(ClaimTypes.NameIdentifier) == user.Id))).Verifiable();
} }
if (rememberClient) if (rememberClient)
{ {
response.Setup(r => r.SignIn( response.Setup(r => r.SignIn(
It.Is<AuthenticationProperties>(v => v.IsPersistent == true), IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme,
It.Is<ClaimsIdentity>(i => i.FindFirstValue(ClaimTypes.Name) == user.Id It.Is<ClaimsPrincipal>(i => i.FindFirstValue(ClaimTypes.Name) == user.Id
&& i.AuthenticationType == IdentityOptions.TwoFactorRememberMeCookieAuthenticationType))).Verifiable(); && i.Identities.First().AuthenticationType == IdentityOptions.TwoFactorRememberMeCookieAuthenticationType),
It.Is<AuthenticationProperties>(v => v.IsPersistent == true))).Verifiable();
} }
context.Setup(c => c.Response).Returns(response.Object).Verifiable(); context.Setup(c => c.Response).Returns(response.Object).Verifiable();
context.Setup(c => c.AuthenticateAsync(IdentityOptions.TwoFactorUserIdCookieAuthenticationType)).ReturnsAsync(authResult).Verifiable(); context.Setup(c => c.AuthenticateAsync(IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme)).ReturnsAsync(authResult).Verifiable();
contextAccessor.Setup(a => a.HttpContext).Returns(context.Object); contextAccessor.Setup(a => a.HttpContext).Returns(context.Object);
var logStore = new StringBuilder(); var logStore = new StringBuilder();
var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore); var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore);
@ -412,10 +408,10 @@ namespace Microsoft.AspNet.Identity.Test
// Assert // Assert
Assert.True(result.Succeeded); Assert.True(result.Succeeded);
Assert.NotEqual(-1, logStore.ToString().IndexOf(expected)); Assert.NotEqual(-1, logStore.ToString().IndexOf(expected));
manager.VerifyAll(); manager.Verify();
context.VerifyAll(); context.Verify();
response.VerifyAll(); response.Verify();
contextAccessor.VerifyAll(); contextAccessor.Verify();
} }
[Fact] [Fact]
@ -423,7 +419,7 @@ namespace Microsoft.AspNet.Identity.Test
{ {
// Setup // Setup
var user = new TestUser { UserName = "Foo" }; var user = new TestUser { UserName = "Foo" };
var manager = MockHelpers.MockUserManager<TestUser>(); var manager = SetupUserManager(user);
var context = new Mock<HttpContext>(); var context = new Mock<HttpContext>();
var response = new Mock<HttpResponse>(); var response = new Mock<HttpResponse>();
var contextAccessor = new Mock<IHttpContextAccessor>(); var contextAccessor = new Mock<IHttpContextAccessor>();
@ -431,14 +427,14 @@ namespace Microsoft.AspNet.Identity.Test
var identityOptions = new IdentityOptions(); var identityOptions = new IdentityOptions();
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
var claimsFactory = new ClaimsIdentityFactory<TestUser, TestRole>(manager.Object, roleManager.Object, options.Object); var claimsFactory = new UserClaimsPrincipalFactory<TestUser, TestRole>(manager.Object, roleManager.Object, options.Object);
manager.Setup(m => m.GetUserIdAsync(user)).ReturnsAsync(user.Id).Verifiable();
context.Setup(c => c.Response).Returns(response.Object).Verifiable(); context.Setup(c => c.Response).Returns(response.Object).Verifiable();
response.Setup(r => r.SignIn( response.Setup(r => r.SignIn(
It.Is<AuthenticationProperties>(v => v.IsPersistent == true), IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme,
It.Is<ClaimsIdentity>(i => i.FindFirstValue(ClaimTypes.Name) == user.Id It.Is<ClaimsPrincipal>(i => i.FindFirstValue(ClaimTypes.Name) == user.Id
&& i.AuthenticationType == IdentityOptions.TwoFactorRememberMeCookieAuthenticationType))).Verifiable(); && i.Identities.First().AuthenticationType == IdentityOptions.TwoFactorRememberMeCookieAuthenticationType),
It.Is<AuthenticationProperties>(v => v.IsPersistent == true))).Verifiable();
contextAccessor.Setup(a => a.HttpContext).Returns(context.Object).Verifiable(); contextAccessor.Setup(a => a.HttpContext).Returns(context.Object).Verifiable();
options.Setup(a => a.Options).Returns(identityOptions).Verifiable(); options.Setup(a => a.Options).Returns(identityOptions).Verifiable();
@ -448,11 +444,11 @@ namespace Microsoft.AspNet.Identity.Test
await helper.RememberTwoFactorClientAsync(user); await helper.RememberTwoFactorClientAsync(user);
// Assert // Assert
manager.VerifyAll(); manager.Verify();
context.VerifyAll(); context.Verify();
response.VerifyAll(); response.Verify();
contextAccessor.VerifyAll(); contextAccessor.Verify();
options.VerifyAll(); options.Verify();
} }
[Theory] [Theory]
@ -462,7 +458,7 @@ namespace Microsoft.AspNet.Identity.Test
{ {
// Setup // Setup
var user = new TestUser { UserName = "Foo" }; var user = new TestUser { UserName = "Foo" };
var manager = MockHelpers.MockUserManager<TestUser>(); var manager = SetupUserManager(user);
manager.Setup(m => m.GetTwoFactorEnabledAsync(user)).ReturnsAsync(true).Verifiable(); manager.Setup(m => m.GetTwoFactorEnabledAsync(user)).ReturnsAsync(true).Verifiable();
IList<string> providers = new List<string>(); IList<string> providers = new List<string>();
providers.Add("PhoneNumber"); providers.Add("PhoneNumber");
@ -470,25 +466,23 @@ namespace Microsoft.AspNet.Identity.Test
manager.Setup(m => m.SupportsUserLockout).Returns(true).Verifiable(); manager.Setup(m => m.SupportsUserLockout).Returns(true).Verifiable();
manager.Setup(m => m.SupportsUserTwoFactor).Returns(true).Verifiable(); manager.Setup(m => m.SupportsUserTwoFactor).Returns(true).Verifiable();
manager.Setup(m => m.IsLockedOutAsync(user)).ReturnsAsync(false).Verifiable(); manager.Setup(m => m.IsLockedOutAsync(user)).ReturnsAsync(false).Verifiable();
manager.Setup(m => m.FindByNameAsync(user.UserName)).ReturnsAsync(user).Verifiable();
manager.Setup(m => m.GetUserIdAsync(user)).ReturnsAsync(user.Id).Verifiable();
manager.Setup(m => m.CheckPasswordAsync(user, "password")).ReturnsAsync(true).Verifiable(); manager.Setup(m => m.CheckPasswordAsync(user, "password")).ReturnsAsync(true).Verifiable();
var context = new Mock<HttpContext>(); var context = new Mock<HttpContext>();
var response = new Mock<HttpResponse>(); var response = new Mock<HttpResponse>();
context.Setup(c => c.Response).Returns(response.Object).Verifiable(); context.Setup(c => c.Response).Returns(response.Object).Verifiable();
response.Setup(r => r.SignIn(It.Is<AuthenticationProperties>(v => v.IsPersistent == isPersistent), It.Is<ClaimsIdentity>(i => i.AuthenticationType == IdentityOptions.ApplicationCookieAuthenticationType))).Verifiable(); SetupSignIn(response);
var id = new ClaimsIdentity(IdentityOptions.TwoFactorRememberMeCookieAuthenticationType); var id = new ClaimsIdentity(IdentityOptions.TwoFactorRememberMeCookieAuthenticationType);
id.AddClaim(new Claim(ClaimTypes.Name, user.Id)); id.AddClaim(new Claim(ClaimTypes.Name, user.Id));
var authResult = new AuthenticationResult(id, new AuthenticationProperties(), new AuthenticationDescription()); var authResult = new AuthenticationResult(new ClaimsPrincipal(id), new AuthenticationProperties(), new AuthenticationDescription());
context.Setup(c => c.AuthenticateAsync(IdentityOptions.TwoFactorRememberMeCookieAuthenticationType)).ReturnsAsync(authResult).Verifiable(); context.Setup(c => c.AuthenticateAsync(IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme)).ReturnsAsync(authResult).Verifiable();
var contextAccessor = new Mock<IHttpContextAccessor>(); var contextAccessor = new Mock<IHttpContextAccessor>();
contextAccessor.Setup(a => a.HttpContext).Returns(context.Object); contextAccessor.Setup(a => a.HttpContext).Returns(context.Object);
var roleManager = MockHelpers.MockRoleManager<TestRole>(); var roleManager = MockHelpers.MockRoleManager<TestRole>();
var identityOptions = new IdentityOptions(); var identityOptions = new IdentityOptions();
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object); var claimsFactory = new Mock<UserClaimsPrincipalFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object);
claimsFactory.Setup(m => m.CreateAsync(user)).ReturnsAsync(new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationType)).Verifiable(); claimsFactory.Setup(m => m.CreateAsync(user)).ReturnsAsync(new ClaimsPrincipal(new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationType))).Verifiable();
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object); var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object);
// Act // Act
@ -496,34 +490,34 @@ namespace Microsoft.AspNet.Identity.Test
// Assert // Assert
Assert.True(result.Succeeded); Assert.True(result.Succeeded);
manager.VerifyAll(); manager.Verify();
context.VerifyAll(); context.Verify();
response.VerifyAll(); response.Verify();
contextAccessor.VerifyAll(); contextAccessor.Verify();
claimsFactory.VerifyAll(); claimsFactory.Verify();
} }
[Theory] [Theory]
[InlineData("Microsoft.AspNet.Identity.Authentication.Application")] [InlineData("Microsoft.AspNet.Identity.Authentication.Application")]
[InlineData("Foo")] [InlineData("Foo")]
public void SignOutCallsContextResponseSignOut(string authenticationType) public void SignOutCallsContextResponseSignOut(string authenticationScheme)
{ {
// Setup // Setup
var manager = MockHelpers.MockUserManager<TestUser>(); var manager = MockHelpers.MockUserManager<TestUser>();
var context = new Mock<HttpContext>(); var context = new Mock<HttpContext>();
var response = new Mock<HttpResponse>(); var response = new Mock<HttpResponse>();
context.Setup(c => c.Response).Returns(response.Object).Verifiable(); context.Setup(c => c.Response).Returns(response.Object).Verifiable();
response.Setup(r => r.SignOut(authenticationType)).Verifiable(); response.Setup(r => r.SignOut(authenticationScheme)).Verifiable();
response.Setup(r => r.SignOut(IdentityOptions.TwoFactorUserIdCookieAuthenticationType)).Verifiable(); response.Setup(r => r.SignOut(IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme)).Verifiable();
response.Setup(r => r.SignOut(IdentityOptions.ExternalCookieAuthenticationType)).Verifiable(); response.Setup(r => r.SignOut(IdentityOptions.ExternalCookieAuthenticationScheme)).Verifiable();
var contextAccessor = new Mock<IHttpContextAccessor>(); var contextAccessor = new Mock<IHttpContextAccessor>();
contextAccessor.Setup(a => a.HttpContext).Returns(context.Object); contextAccessor.Setup(a => a.HttpContext).Returns(context.Object);
var roleManager = MockHelpers.MockRoleManager<TestRole>(); var roleManager = MockHelpers.MockRoleManager<TestRole>();
var identityOptions = new IdentityOptions(); var identityOptions = new IdentityOptions();
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
IdentityOptions.ApplicationCookieAuthenticationType = authenticationType; IdentityOptions.ApplicationCookieAuthenticationScheme = authenticationScheme;
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object); var claimsFactory = new Mock<UserClaimsPrincipalFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object);
var logStore = new StringBuilder(); var logStore = new StringBuilder();
var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore); var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore);
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object, logger.Object); var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object, logger.Object);
@ -532,10 +526,10 @@ namespace Microsoft.AspNet.Identity.Test
helper.SignOut(); helper.SignOut();
// Assert // Assert
context.VerifyAll(); context.Verify();
response.VerifyAll(); response.Verify();
contextAccessor.VerifyAll(); contextAccessor.Verify();
claimsFactory.VerifyAll(); claimsFactory.Verify();
} }
[Fact] [Fact]
@ -543,12 +537,10 @@ namespace Microsoft.AspNet.Identity.Test
{ {
// Setup // Setup
var user = new TestUser { UserName = "Foo" }; var user = new TestUser { UserName = "Foo" };
var manager = MockHelpers.MockUserManager<TestUser>(); var manager = SetupUserManager(user);
manager.Setup(m => m.SupportsUserLockout).Returns(true).Verifiable(); manager.Setup(m => m.SupportsUserLockout).Returns(true).Verifiable();
manager.Setup(m => m.IsLockedOutAsync(user)).ReturnsAsync(false).Verifiable(); manager.Setup(m => m.IsLockedOutAsync(user)).ReturnsAsync(false).Verifiable();
manager.Setup(m => m.FindByNameAsync(user.UserName)).ReturnsAsync(user).Verifiable();
manager.Setup(m => m.CheckPasswordAsync(user, "bogus")).ReturnsAsync(false).Verifiable(); manager.Setup(m => m.CheckPasswordAsync(user, "bogus")).ReturnsAsync(false).Verifiable();
manager.Setup(m => m.GetUserIdAsync(user)).ReturnsAsync(user.Id.ToString()).Verifiable();
var context = new Mock<HttpContext>(); var context = new Mock<HttpContext>();
var contextAccessor = new Mock<IHttpContextAccessor>(); var contextAccessor = new Mock<IHttpContextAccessor>();
contextAccessor.Setup(a => a.HttpContext).Returns(context.Object); contextAccessor.Setup(a => a.HttpContext).Returns(context.Object);
@ -556,7 +548,7 @@ namespace Microsoft.AspNet.Identity.Test
var identityOptions = new IdentityOptions(); var identityOptions = new IdentityOptions();
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object); var claimsFactory = new Mock<UserClaimsPrincipalFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object);
var logStore = new StringBuilder(); var logStore = new StringBuilder();
var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore); var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore);
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object, logger.Object); var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object, logger.Object);
@ -567,9 +559,9 @@ namespace Microsoft.AspNet.Identity.Test
// Assert // Assert
Assert.False(result.Succeeded); Assert.False(result.Succeeded);
Assert.NotEqual(-1, logStore.ToString().IndexOf(expected)); Assert.NotEqual(-1, logStore.ToString().IndexOf(expected));
manager.VerifyAll(); manager.Verify();
context.VerifyAll(); context.Verify();
contextAccessor.VerifyAll(); contextAccessor.Verify();
} }
[Fact] [Fact]
@ -585,7 +577,7 @@ namespace Microsoft.AspNet.Identity.Test
var identityOptions = new IdentityOptions(); var identityOptions = new IdentityOptions();
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object); var claimsFactory = new Mock<UserClaimsPrincipalFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object);
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object); var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object);
// Act // Act
@ -593,9 +585,9 @@ namespace Microsoft.AspNet.Identity.Test
// Assert // Assert
Assert.False(result.Succeeded); Assert.False(result.Succeeded);
manager.VerifyAll(); manager.Verify();
context.VerifyAll(); context.Verify();
contextAccessor.VerifyAll(); contextAccessor.Verify();
} }
[Fact] [Fact]
@ -603,7 +595,7 @@ namespace Microsoft.AspNet.Identity.Test
{ {
// Setup // Setup
var user = new TestUser { UserName = "Foo" }; var user = new TestUser { UserName = "Foo" };
var manager = MockHelpers.MockUserManager<TestUser>(); var manager = SetupUserManager(user);
var lockedout = false; var lockedout = false;
manager.Setup(m => m.AccessFailedAsync(user)).Returns(() => manager.Setup(m => m.AccessFailedAsync(user)).Returns(() =>
{ {
@ -612,7 +604,6 @@ namespace Microsoft.AspNet.Identity.Test
}).Verifiable(); }).Verifiable();
manager.Setup(m => m.SupportsUserLockout).Returns(true).Verifiable(); manager.Setup(m => m.SupportsUserLockout).Returns(true).Verifiable();
manager.Setup(m => m.IsLockedOutAsync(user)).Returns(() => Task.FromResult(lockedout)); manager.Setup(m => m.IsLockedOutAsync(user)).Returns(() => Task.FromResult(lockedout));
manager.Setup(m => m.FindByNameAsync(user.UserName)).ReturnsAsync(user).Verifiable();
manager.Setup(m => m.CheckPasswordAsync(user, "bogus")).ReturnsAsync(false).Verifiable(); manager.Setup(m => m.CheckPasswordAsync(user, "bogus")).ReturnsAsync(false).Verifiable();
var context = new Mock<HttpContext>(); var context = new Mock<HttpContext>();
var contextAccessor = new Mock<IHttpContextAccessor>(); var contextAccessor = new Mock<IHttpContextAccessor>();
@ -621,7 +612,7 @@ namespace Microsoft.AspNet.Identity.Test
var identityOptions = new IdentityOptions(); var identityOptions = new IdentityOptions();
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object); var claimsFactory = new Mock<UserClaimsPrincipalFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object);
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object); var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object);
// Act // Act
@ -630,7 +621,7 @@ namespace Microsoft.AspNet.Identity.Test
// Assert // Assert
Assert.False(result.Succeeded); Assert.False(result.Succeeded);
Assert.True(result.IsLockedOut); Assert.True(result.IsLockedOut);
manager.VerifyAll(); manager.Verify();
} }
[Theory] [Theory]
@ -640,20 +631,19 @@ namespace Microsoft.AspNet.Identity.Test
{ {
// Setup // Setup
var user = new TestUser { UserName = "Foo" }; var user = new TestUser { UserName = "Foo" };
var manager = MockHelpers.MockUserManager<TestUser>(); var manager = SetupUserManager(user);
manager.Setup(m => m.IsEmailConfirmedAsync(user)).ReturnsAsync(confirmed).Verifiable(); manager.Setup(m => m.IsEmailConfirmedAsync(user)).ReturnsAsync(confirmed).Verifiable();
if (confirmed) if (confirmed)
{ {
manager.Setup(m => m.CheckPasswordAsync(user, "password")).ReturnsAsync(true).Verifiable(); manager.Setup(m => m.CheckPasswordAsync(user, "password")).ReturnsAsync(true).Verifiable();
} }
manager.Setup(m => m.GetUserIdAsync(user)).ReturnsAsync(user.Id.ToString()).Verifiable();
var context = new Mock<HttpContext>(); var context = new Mock<HttpContext>();
var response = new Mock<HttpResponse>(); var response = new Mock<HttpResponse>();
if (confirmed) if (confirmed)
{ {
manager.Setup(m => m.CheckPasswordAsync(user, "password")).ReturnsAsync(true).Verifiable(); manager.Setup(m => m.CheckPasswordAsync(user, "password")).ReturnsAsync(true).Verifiable();
context.Setup(c => c.Response).Returns(response.Object).Verifiable(); context.Setup(c => c.Response).Returns(response.Object).Verifiable();
response.Setup(r => r.SignIn(It.Is<AuthenticationProperties>(v => v.IsPersistent == false), It.IsAny<ClaimsIdentity>())).Verifiable(); SetupSignIn(response);
} }
var contextAccessor = new Mock<IHttpContextAccessor>(); var contextAccessor = new Mock<IHttpContextAccessor>();
contextAccessor.Setup(a => a.HttpContext).Returns(context.Object); contextAccessor.Setup(a => a.HttpContext).Returns(context.Object);
@ -662,7 +652,7 @@ namespace Microsoft.AspNet.Identity.Test
identityOptions.SignIn.RequireConfirmedEmail = true; identityOptions.SignIn.RequireConfirmedEmail = true;
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object); var claimsFactory = new Mock<UserClaimsPrincipalFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object);
var logStore = new StringBuilder(); var logStore = new StringBuilder();
var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore); var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore);
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object, logger.Object); var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object, logger.Object);
@ -676,10 +666,19 @@ namespace Microsoft.AspNet.Identity.Test
Assert.Equal(confirmed, result.Succeeded); Assert.Equal(confirmed, result.Succeeded);
Assert.NotEqual(confirmed, result.IsNotAllowed); Assert.NotEqual(confirmed, result.IsNotAllowed);
Assert.NotEqual(-1, logStore.ToString().IndexOf(expected)); Assert.NotEqual(-1, logStore.ToString().IndexOf(expected));
manager.VerifyAll(); manager.Verify();
context.VerifyAll(); context.Verify();
response.VerifyAll(); response.Verify();
contextAccessor.VerifyAll(); contextAccessor.Verify();
}
private static void SetupSignIn(Mock<HttpResponse> response, string userId = null, bool? isPersistent = null, string loginProvider = null)
{
response.Setup(r => r.SignIn(IdentityOptions.ApplicationCookieAuthenticationScheme,
It.Is<ClaimsPrincipal>(id =>
(userId == null || id.FindFirstValue(ClaimTypes.NameIdentifier) == userId) &&
(loginProvider == null || id.FindFirstValue(ClaimTypes.AuthenticationMethod) == loginProvider)),
It.Is<AuthenticationProperties>(v => isPersistent == null || v.IsPersistent == isPersistent))).Verifiable();
} }
[Theory] [Theory]
@ -689,16 +688,15 @@ namespace Microsoft.AspNet.Identity.Test
{ {
// Setup // Setup
var user = new TestUser { UserName = "Foo" }; var user = new TestUser { UserName = "Foo" };
var manager = MockHelpers.MockUserManager<TestUser>(); var manager = SetupUserManager(user);
manager.Setup(m => m.IsPhoneNumberConfirmedAsync(user)).ReturnsAsync(confirmed).Verifiable(); manager.Setup(m => m.IsPhoneNumberConfirmedAsync(user)).ReturnsAsync(confirmed).Verifiable();
manager.Setup(m => m.GetUserIdAsync(user)).ReturnsAsync(user.Id.ToString()).Verifiable();
var context = new Mock<HttpContext>(); var context = new Mock<HttpContext>();
var response = new Mock<HttpResponse>(); var response = new Mock<HttpResponse>();
if (confirmed) if (confirmed)
{ {
manager.Setup(m => m.CheckPasswordAsync(user, "password")).ReturnsAsync(true).Verifiable(); manager.Setup(m => m.CheckPasswordAsync(user, "password")).ReturnsAsync(true).Verifiable();
context.Setup(c => c.Response).Returns(response.Object).Verifiable(); context.Setup(c => c.Response).Returns(response.Object).Verifiable();
response.Setup(r => r.SignIn(It.Is<AuthenticationProperties>(v => v.IsPersistent == false), It.IsAny<ClaimsIdentity>())).Verifiable(); SetupSignIn(response);
} }
var contextAccessor = new Mock<IHttpContextAccessor>(); var contextAccessor = new Mock<IHttpContextAccessor>();
@ -708,7 +706,7 @@ namespace Microsoft.AspNet.Identity.Test
identityOptions.SignIn.RequireConfirmedPhoneNumber = true; identityOptions.SignIn.RequireConfirmedPhoneNumber = true;
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object); var claimsFactory = new Mock<UserClaimsPrincipalFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object);
var logStore = new StringBuilder(); var logStore = new StringBuilder();
var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore); var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore);
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object, logger.Object); var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object, logger.Object);
@ -721,11 +719,10 @@ namespace Microsoft.AspNet.Identity.Test
Assert.Equal(confirmed, result.Succeeded); Assert.Equal(confirmed, result.Succeeded);
Assert.NotEqual(confirmed, result.IsNotAllowed); Assert.NotEqual(confirmed, result.IsNotAllowed);
Assert.NotEqual(-1, logStore.ToString().IndexOf(expected)); Assert.NotEqual(-1, logStore.ToString().IndexOf(expected));
manager.VerifyAll(); manager.Verify();
context.VerifyAll(); context.Verify();
response.VerifyAll(); response.Verify();
contextAccessor.VerifyAll(); contextAccessor.Verify();
} }
} }
} }

View File

@ -4,15 +4,14 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Security.Claims; using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Framework.OptionsModel;
using Moq; using Moq;
using Xunit; using Xunit;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Identity.Test namespace Microsoft.AspNet.Identity.Test
{ {
public class ClaimsIdentityFactoryTest public class UserClaimsPrincipalFactoryTest
{ {
[Fact] [Fact]
public async Task CreateIdentityNullChecks() public async Task CreateIdentityNullChecks()
@ -21,10 +20,10 @@ namespace Microsoft.AspNet.Identity.Test
var roleManager = MockHelpers.MockRoleManager<TestRole>().Object; var roleManager = MockHelpers.MockRoleManager<TestRole>().Object;
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
Assert.Throws<ArgumentNullException>("optionsAccessor", Assert.Throws<ArgumentNullException>("optionsAccessor",
() => new ClaimsIdentityFactory<TestUser, TestRole>(userManager, roleManager, options.Object)); () => new UserClaimsPrincipalFactory<TestUser, TestRole>(userManager, roleManager, options.Object));
var identityOptions = new IdentityOptions(); var identityOptions = new IdentityOptions();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
var factory = new ClaimsIdentityFactory<TestUser, TestRole>(userManager, roleManager, options.Object); var factory = new UserClaimsPrincipalFactory<TestUser, TestRole>(userManager, roleManager, options.Object);
await Assert.ThrowsAsync<ArgumentNullException>("user", await Assert.ThrowsAsync<ArgumentNullException>("user",
async () => await factory.CreateAsync(null)); async () => await factory.CreateAsync(null));
} }
@ -74,14 +73,16 @@ namespace Microsoft.AspNet.Identity.Test
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
var identityOptions = new IdentityOptions(); var identityOptions = new IdentityOptions();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Options).Returns(identityOptions);
var factory = new ClaimsIdentityFactory<TestUser, TestRole>(userManager.Object, roleManager.Object, options.Object); var factory = new UserClaimsPrincipalFactory<TestUser, TestRole>(userManager.Object, roleManager.Object, options.Object);
// Act // Act
var identity = await factory.CreateAsync(user); var principal = await factory.CreateAsync(user);
var identity = principal.Identities.First();
// Assert // Assert
var manager = userManager.Object; var manager = userManager.Object;
Assert.NotNull(identity); Assert.NotNull(identity);
Assert.Equal(1, principal.Identities.Count());
Assert.Equal(IdentityOptions.ApplicationCookieAuthenticationType, identity.AuthenticationType); Assert.Equal(IdentityOptions.ApplicationCookieAuthenticationType, identity.AuthenticationType);
var claims = identity.Claims.ToList(); var claims = identity.Claims.ToList();
Assert.NotNull(claims); Assert.NotNull(claims);