Security stamp validator. Removed more references to ASP.NET Identity 2
This commit is contained in:
@@ -33,7 +33,7 @@
|
||||
<dependency id="LightInject.Mvc" version="[2.0.0,2.999999)" />
|
||||
<dependency id="LightInject.WebApi" version="[2.0.0,2.999999)" />
|
||||
<dependency id="Markdown" version="[2.2.1,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Identity.Owin" version="[2.2.2,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Identity.Core" version="[2.2.2,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Mvc" version="[5.2.7,5.999999)" />
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.4.0,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi" version="[5.2.7,5.999999)" />
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Umbraco.Core.Models.Identity;
|
||||
|
||||
namespace Umbraco.Web.Models.Identity
|
||||
@@ -13,7 +12,7 @@ namespace Umbraco.Web.Models.Identity
|
||||
/// This class normally exists inside of the EntityFramework library, not sure why MS chose to explicitly put it there but we don't want
|
||||
/// references to that so we will create our own here
|
||||
/// </remarks>
|
||||
public class IdentityUser<TKey, TLogin, TRole, TClaim> : IUser<TKey>
|
||||
public class IdentityUser<TKey, TLogin, TRole, TClaim>
|
||||
where TLogin : IIdentityUserLogin
|
||||
//NOTE: Making our role id a string
|
||||
where TRole : IdentityUserRole<string>
|
||||
|
||||
@@ -147,15 +147,14 @@ namespace Umbraco.Web.Security
|
||||
|
||||
authOptions.Provider = new BackOfficeCookieAuthenticationProvider(userService, runtimeState, globalSettings, ioHelper, umbracoSettingsSection)
|
||||
{
|
||||
// TODO: SB: SecurityStampValidator
|
||||
// Enables the application to validate the security stamp when the user
|
||||
// logs in. This is a security feature which is used when you
|
||||
// change a password or add an external login to your account.
|
||||
/*OnValidateIdentity = SecurityStampValidator
|
||||
.OnValidateIdentity<BackOfficeUserManager, BackOfficeIdentityUser, int>(
|
||||
TimeSpan.FromMinutes(30),
|
||||
(manager, user) => manager.GenerateUserIdentityAsync(user),
|
||||
identity => identity.GetUserId<int>()),*/
|
||||
OnValidateIdentity = UmbracoSecurityStampValidator
|
||||
.OnValidateIdentity<BackOfficeUserManager, BackOfficeIdentityUser>(
|
||||
TimeSpan.FromMinutes(3),
|
||||
(signInManager, manager, user) => signInManager.CreateUserIdentityAsync(user),
|
||||
identity => identity.GetUserId()),
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace Umbraco.Web.Security
|
||||
options.Password.RequireDigit = passwordConfiguration.RequireDigit;
|
||||
options.Password.RequireLowercase = passwordConfiguration.RequireLowercase;
|
||||
options.Password.RequireUppercase = passwordConfiguration.RequireUppercase;
|
||||
|
||||
|
||||
// Ensure Umbraco security stamp claim type is used
|
||||
options.ClaimsIdentity.UserIdClaimType = ClaimTypes.NameIdentifier;
|
||||
options.ClaimsIdentity.UserNameClaimType = ClaimTypes.Name;
|
||||
@@ -202,7 +202,7 @@ namespace Umbraco.Web.Security
|
||||
protected virtual IPasswordHasher<T> GetDefaultPasswordHasher(IPasswordConfiguration passwordConfiguration)
|
||||
{
|
||||
//we can use the user aware password hasher (which will be the default and preferred way)
|
||||
return new UserAwarePasswordHasher2<T>(new PasswordSecurity(passwordConfiguration));
|
||||
return new UserAwarePasswordHasher<T>(new PasswordSecurity(passwordConfiguration));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Net.Mail;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="IIdentityMessageService"/> implementation for Umbraco
|
||||
/// </summary>
|
||||
public class EmailService : IIdentityMessageService
|
||||
{
|
||||
private readonly string _notificationEmailAddress;
|
||||
private readonly IEmailSender _defaultEmailSender;
|
||||
|
||||
public EmailService(string notificationEmailAddress, IEmailSender defaultEmailSender)
|
||||
{
|
||||
_notificationEmailAddress = notificationEmailAddress;
|
||||
_defaultEmailSender = defaultEmailSender;
|
||||
}
|
||||
|
||||
|
||||
public async Task SendAsync(IdentityMessage message)
|
||||
{
|
||||
var mailMessage = new MailMessage(
|
||||
_notificationEmailAddress,
|
||||
message.Destination,
|
||||
message.Subject,
|
||||
message.Body)
|
||||
{
|
||||
IsBodyHtml = message.Body.IsNullOrWhiteSpace() == false
|
||||
&& message.Body.Contains("<") && message.Body.Contains("</")
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
//check if it's a custom message and if so use it's own defined mail sender
|
||||
var umbMsg = message as UmbracoEmailMessage;
|
||||
if (umbMsg != null)
|
||||
{
|
||||
await umbMsg.MailSender.SendAsync(mailMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _defaultEmailSender.SendAsync(mailMessage);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
mailMessage.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using Microsoft.AspNet.Identity;
|
||||
|
||||
namespace Umbraco.Core.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// A custom implementation for IdentityMessage that allows the customization of how an email is sent
|
||||
/// </summary>
|
||||
internal class UmbracoEmailMessage : IdentityMessage
|
||||
{
|
||||
public IEmailSender MailSender { get; private set; }
|
||||
|
||||
public UmbracoEmailMessage(IEmailSender mailSender)
|
||||
{
|
||||
MailSender = mailSender;
|
||||
}
|
||||
}
|
||||
}
|
||||
86
src/Umbraco.Web/Security/UmbracoSecurityStampValidator.cs
Normal file
86
src/Umbraco.Web/Security/UmbracoSecurityStampValidator.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Owin.Security.Cookies;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.Models.Identity;
|
||||
|
||||
namespace Umbraco.Web.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// Adapted from Microsoft.AspNet.Identity.Owin.SecurityStampValidator
|
||||
/// </summary>
|
||||
public class UmbracoSecurityStampValidator
|
||||
{
|
||||
public static Func<CookieValidateIdentityContext, Task> OnValidateIdentity<TManager, TUser>(
|
||||
TimeSpan validateInterval,
|
||||
Func<BackOfficeSignInManager, TManager, TUser, Task<ClaimsIdentity>> regenerateIdentityCallback,
|
||||
Func<ClaimsIdentity, string> getUserIdCallback)
|
||||
where TManager : BackOfficeUserManager<TUser>
|
||||
where TUser : BackOfficeIdentityUser
|
||||
{
|
||||
if (getUserIdCallback == null) throw new ArgumentNullException(nameof(getUserIdCallback));
|
||||
|
||||
return async context =>
|
||||
{
|
||||
var currentUtc = DateTimeOffset.UtcNow;
|
||||
if (context.Options != null && context.Options.SystemClock != null)
|
||||
{
|
||||
currentUtc = context.Options.SystemClock.UtcNow;
|
||||
}
|
||||
|
||||
var issuedUtc = context.Properties.IssuedUtc;
|
||||
|
||||
// Only validate if enough time has elapsed
|
||||
var validate = issuedUtc == null;
|
||||
if (issuedUtc != null)
|
||||
{
|
||||
var timeElapsed = currentUtc.Subtract(issuedUtc.Value);
|
||||
validate = timeElapsed > validateInterval;
|
||||
}
|
||||
|
||||
if (validate)
|
||||
{
|
||||
var manager = context.OwinContext.Get<TManager>();
|
||||
var signInManager = context.OwinContext.GetBackOfficeSignInManager();
|
||||
|
||||
var userId = getUserIdCallback(context.Identity);
|
||||
|
||||
if (manager != null && userId != null)
|
||||
{
|
||||
var user = await manager.FindByIdAsync(userId);
|
||||
var reject = true;
|
||||
|
||||
// Refresh the identity if the stamp matches, otherwise reject
|
||||
if (user != null && manager.SupportsUserSecurityStamp)
|
||||
{
|
||||
var securityStamp = context.Identity.FindFirst(Constants.Web.SecurityStampClaimType)?.Value;
|
||||
if (securityStamp == await manager.GetSecurityStampAsync(user))
|
||||
{
|
||||
reject = false;
|
||||
// Regenerate fresh claims if possible and resign in
|
||||
if (regenerateIdentityCallback != null)
|
||||
{
|
||||
var identity = await regenerateIdentityCallback.Invoke(signInManager, manager, user);
|
||||
if (identity != null)
|
||||
{
|
||||
// Fix for regression where this value is not updated
|
||||
// Setting it to null so that it is refreshed by the cookie middleware
|
||||
context.Properties.IssuedUtc = null;
|
||||
context.Properties.ExpiresUtc = null;
|
||||
context.OwinContext.Authentication.SignIn(context.Properties, identity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (reject)
|
||||
{
|
||||
context.RejectIdentity();
|
||||
context.OwinContext.Authentication.SignOut(context.Options.AuthenticationType);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,12 @@ using Umbraco.Web.Models.Identity;
|
||||
|
||||
namespace Umbraco.Web.Security
|
||||
{
|
||||
public class UserAwarePasswordHasher2<T> : IPasswordHasher<T>
|
||||
public class UserAwarePasswordHasher<T> : IPasswordHasher<T>
|
||||
where T : BackOfficeIdentityUser
|
||||
{
|
||||
private readonly PasswordSecurity _passwordSecurity;
|
||||
|
||||
public UserAwarePasswordHasher2(PasswordSecurity passwordSecurity)
|
||||
public UserAwarePasswordHasher(PasswordSecurity passwordSecurity)
|
||||
{
|
||||
_passwordSecurity = passwordSecurity;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
@@ -205,7 +205,6 @@
|
||||
<Compile Include="Security\BackOfficeUserStore.cs" />
|
||||
<Compile Include="Security\BackOfficeUserValidator.cs" />
|
||||
<Compile Include="Security\ConfiguredPasswordValidator.cs" />
|
||||
<Compile Include="Security\EmailService.cs" />
|
||||
<Compile Include="Security\IUserSessionStore.cs" />
|
||||
<Compile Include="Security\MembershipProviderBase.cs" />
|
||||
<Compile Include="Security\MembershipProviderExtensions.cs" />
|
||||
@@ -213,9 +212,9 @@
|
||||
<Compile Include="Security\OwinDataProtectorTokenProvider.cs" />
|
||||
<Compile Include="Security\PasswordSecurity.cs" />
|
||||
<Compile Include="Security\UmbracoBackOfficeIdentity.cs" />
|
||||
<Compile Include="Security\UmbracoEmailMessage.cs" />
|
||||
<Compile Include="Security\UmbracoMembershipProviderBase.cs" />
|
||||
<Compile Include="Security\UserAwarePasswordHasher2.cs" />
|
||||
<Compile Include="Security\UmbracoSecurityStampValidator.cs" />
|
||||
<Compile Include="Security\UserAwarePasswordHasher.cs" />
|
||||
<Compile Include="StringExtensions.cs" />
|
||||
<Compile Include="Trees\TreeCollectionBuilder.cs" />
|
||||
<Compile Include="UmbracoContext.cs" />
|
||||
|
||||
Reference in New Issue
Block a user