Removed use of Microsoft.AspNet.Identity.Owin, but had to port across some OWIN extensions
This commit is contained in:
@@ -88,7 +88,6 @@
|
||||
<PackageReference Include="ClientDependency-Mvc5" Version="1.9.3" />
|
||||
<PackageReference Include="ImageProcessor.Web" Version="4.10.0.100" />
|
||||
<PackageReference Include="ImageProcessor.Web.Config" Version="2.5.0.100" />
|
||||
<PackageReference Include="Microsoft.AspNet.Identity.Owin" Version="2.2.2" />
|
||||
<PackageReference Include="Microsoft.AspNet.Mvc" Version="5.2.7" />
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi" Version="5.2.7" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="2.10.0" />
|
||||
|
||||
@@ -374,7 +374,7 @@ namespace Umbraco.Web.Editors
|
||||
return await ExternalSignInAsync(loginInfo, externalSignInResponse);
|
||||
}
|
||||
|
||||
private async Task<ActionResult> ExternalSignInAsync(ExternalLoginInfo2 loginInfo, Func<ActionResult> response)
|
||||
private async Task<ActionResult> ExternalSignInAsync(ExternalLoginInfo loginInfo, Func<ActionResult> response)
|
||||
{
|
||||
if (loginInfo == null) throw new ArgumentNullException("loginInfo");
|
||||
if (response == null) throw new ArgumentNullException("response");
|
||||
@@ -437,7 +437,7 @@ namespace Umbraco.Web.Editors
|
||||
return response();
|
||||
}
|
||||
|
||||
private async Task<bool> AutoLinkAndSignInExternalAccount(ExternalLoginInfo2 loginInfo, ExternalSignInAutoLinkOptions autoLinkOptions)
|
||||
private async Task<bool> AutoLinkAndSignInExternalAccount(ExternalLoginInfo loginInfo, ExternalSignInAutoLinkOptions autoLinkOptions)
|
||||
{
|
||||
if (autoLinkOptions == null)
|
||||
return false;
|
||||
|
||||
@@ -21,6 +21,7 @@ using Umbraco.Core.Hosting;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Runtime;
|
||||
using Umbraco.Core.WebAssets;
|
||||
using Umbraco.Web.Security;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ using Umbraco.Web.Composing;
|
||||
using Umbraco.Web.Editors;
|
||||
using Umbraco.Web.Features;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Web.Security;
|
||||
using Umbraco.Web.Trees;
|
||||
using Umbraco.Web.WebAssets;
|
||||
|
||||
|
||||
@@ -90,6 +90,12 @@ namespace Umbraco.Web
|
||||
return context.Get<T>(GetKey(typeof(T)));
|
||||
}
|
||||
|
||||
public static IOwinContext Set<T>(this IOwinContext context, T value)
|
||||
{
|
||||
if (context == null) throw new ArgumentNullException(nameof(context));
|
||||
return context.Set(GetKey(typeof(T)), value);
|
||||
}
|
||||
|
||||
private static string GetKey(Type t)
|
||||
{
|
||||
return "AspNet.Identity.Owin:" + t.AssemblyQualifiedName;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Threading;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Owin;
|
||||
using Microsoft.Owin.Extensions;
|
||||
using Microsoft.Owin.Logging;
|
||||
using Microsoft.Owin.Security;
|
||||
@@ -14,11 +15,8 @@ using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Hosting;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Mapping;
|
||||
using Umbraco.Core.Models.Identity;
|
||||
using Umbraco.Net;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Composing;
|
||||
using Umbraco.Web.Models.Identity;
|
||||
@@ -421,5 +419,41 @@ namespace Umbraco.Web.Security
|
||||
|
||||
return authOptions;
|
||||
}
|
||||
public static IAppBuilder CreatePerOwinContext<T>(this IAppBuilder app, Func<T> createCallback)
|
||||
where T : class, IDisposable
|
||||
{
|
||||
return CreatePerOwinContext<T>(app, (options, context) => createCallback());
|
||||
}
|
||||
|
||||
public static IAppBuilder CreatePerOwinContext<T>(this IAppBuilder app,
|
||||
Func<IdentityFactoryOptions<T>, IOwinContext, T> createCallback) where T : class, IDisposable
|
||||
{
|
||||
if (app == null)
|
||||
{
|
||||
throw new ArgumentNullException("app");
|
||||
}
|
||||
return app.CreatePerOwinContext(createCallback, (options, instance) => instance.Dispose());
|
||||
}
|
||||
|
||||
public static IAppBuilder CreatePerOwinContext<T>(this IAppBuilder app,
|
||||
Func<IdentityFactoryOptions<T>, IOwinContext, T> createCallback,
|
||||
Action<IdentityFactoryOptions<T>, T> disposeCallback) where T : class, IDisposable
|
||||
{
|
||||
if (app == null) throw new ArgumentNullException(nameof(app));
|
||||
if (createCallback == null) throw new ArgumentNullException(nameof(createCallback));
|
||||
if (disposeCallback == null) throw new ArgumentNullException(nameof(disposeCallback));
|
||||
|
||||
app.Use(typeof(IdentityFactoryMiddleware<T, IdentityFactoryOptions<T>>),
|
||||
new IdentityFactoryOptions<T>
|
||||
{
|
||||
DataProtectionProvider = app.GetDataProtectionProvider(),
|
||||
Provider = new IdentityFactoryProvider<T>
|
||||
{
|
||||
OnCreate = createCallback,
|
||||
OnDispose = disposeCallback
|
||||
}
|
||||
});
|
||||
return app;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Microsoft.Owin.Security;
|
||||
using UserLoginInfo = Microsoft.AspNetCore.Identity.UserLoginInfo;
|
||||
|
||||
namespace Umbraco.Web.Security
|
||||
{
|
||||
public static class AuthenticationManagerExtensions
|
||||
{
|
||||
private static ExternalLoginInfo2 GetExternalLoginInfo(AuthenticateResult result)
|
||||
private static ExternalLoginInfo GetExternalLoginInfo(AuthenticateResult result)
|
||||
{
|
||||
if (result == null || result.Identity == null)
|
||||
{
|
||||
@@ -27,7 +29,7 @@ namespace Umbraco.Web.Security
|
||||
}
|
||||
|
||||
var email = result.Identity.FindFirst(ClaimTypes.Email)?.Value;
|
||||
return new ExternalLoginInfo2
|
||||
return new ExternalLoginInfo
|
||||
{
|
||||
ExternalIdentity = result.Identity,
|
||||
Login = new UserLoginInfo(idClaim.Issuer, idClaim.Value, idClaim.Issuer),
|
||||
@@ -47,7 +49,7 @@ namespace Umbraco.Web.Security
|
||||
/// dictionary
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public static async Task<ExternalLoginInfo2> GetExternalLoginInfoAsync(this IAuthenticationManager manager,
|
||||
public static async Task<ExternalLoginInfo> GetExternalLoginInfoAsync(this IAuthenticationManager manager,
|
||||
string authenticationType,
|
||||
string xsrfKey, string expectedValue)
|
||||
{
|
||||
@@ -74,7 +76,7 @@ namespace Umbraco.Web.Security
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="authenticationType"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<ExternalLoginInfo2> GetExternalLoginInfoAsync(this IAuthenticationManager manager, string authenticationType)
|
||||
public static async Task<ExternalLoginInfo> GetExternalLoginInfoAsync(this IAuthenticationManager manager, string authenticationType)
|
||||
{
|
||||
if (manager == null)
|
||||
{
|
||||
@@ -82,9 +84,25 @@ namespace Umbraco.Web.Security
|
||||
}
|
||||
return GetExternalLoginInfo(await manager.AuthenticateAsync(authenticationType));
|
||||
}
|
||||
|
||||
public static IEnumerable<AuthenticationDescription> GetExternalAuthenticationTypes(this IAuthenticationManager manager)
|
||||
{
|
||||
if (manager == null) throw new ArgumentNullException(nameof(manager));
|
||||
return manager.GetAuthenticationTypes(d => d.Properties != null && d.Properties.ContainsKey("Caption"));
|
||||
}
|
||||
|
||||
public static ClaimsIdentity CreateTwoFactorRememberBrowserIdentity(this IAuthenticationManager manager, string userId)
|
||||
{
|
||||
if (manager == null) throw new ArgumentNullException(nameof(manager));
|
||||
|
||||
var rememberBrowserIdentity = new ClaimsIdentity(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
|
||||
rememberBrowserIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, userId));
|
||||
|
||||
return rememberBrowserIdentity;
|
||||
}
|
||||
}
|
||||
|
||||
public class ExternalLoginInfo2
|
||||
public class ExternalLoginInfo
|
||||
{
|
||||
/// <summary>Associated login data</summary>
|
||||
public UserLoginInfo Login { get; set; }
|
||||
|
||||
@@ -31,13 +31,13 @@ namespace Umbraco.Web.Security
|
||||
/// <summary>
|
||||
/// A callback executed during account auto-linking and before the user is persisted
|
||||
/// </summary>
|
||||
public Action<BackOfficeIdentityUser, ExternalLoginInfo2> OnAutoLinking { get; set; }
|
||||
public Action<BackOfficeIdentityUser, ExternalLoginInfo> OnAutoLinking { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A callback executed during every time a user authenticates using an external login.
|
||||
/// returns a boolean indicating if sign in should continue or not.
|
||||
/// </summary>
|
||||
public Func<BackOfficeIdentityUser, ExternalLoginInfo2, bool> OnExternalLogin { get; set; }
|
||||
public Func<BackOfficeIdentityUser, ExternalLoginInfo, bool> OnExternalLogin { get; set; }
|
||||
|
||||
|
||||
/// <summary>B
|
||||
@@ -46,7 +46,7 @@ namespace Umbraco.Web.Security
|
||||
/// <param name="umbracoContext"></param>
|
||||
/// <param name="loginInfo"></param>
|
||||
/// <returns></returns>
|
||||
public string[] GetDefaultUserGroups(IUmbracoContext umbracoContext, ExternalLoginInfo2 loginInfo)
|
||||
public string[] GetDefaultUserGroups(IUmbracoContext umbracoContext, ExternalLoginInfo loginInfo)
|
||||
{
|
||||
return _defaultUserGroups;
|
||||
}
|
||||
@@ -59,7 +59,7 @@ namespace Umbraco.Web.Security
|
||||
///
|
||||
/// For public auth providers this should always be false!!!
|
||||
/// </summary>
|
||||
public bool ShouldAutoLinkExternalAccount(IUmbracoContext umbracoContext, ExternalLoginInfo2 loginInfo)
|
||||
public bool ShouldAutoLinkExternalAccount(IUmbracoContext umbracoContext, ExternalLoginInfo loginInfo)
|
||||
{
|
||||
return _autoLinkExternalAccount;
|
||||
}
|
||||
@@ -69,7 +69,7 @@ namespace Umbraco.Web.Security
|
||||
/// <summary>
|
||||
/// The default Culture to use for auto-linking users
|
||||
/// </summary>
|
||||
public string GetDefaultCulture(IUmbracoContext umbracoContext, ExternalLoginInfo2 loginInfo)
|
||||
public string GetDefaultCulture(IUmbracoContext umbracoContext, ExternalLoginInfo loginInfo)
|
||||
{
|
||||
return _defaultCulture;
|
||||
}
|
||||
|
||||
117
src/Umbraco.Web/Security/IdentityFactoryMiddleware.cs
Normal file
117
src/Umbraco.Web/Security/IdentityFactoryMiddleware.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Owin;
|
||||
using Microsoft.Owin.Security.DataProtection;
|
||||
|
||||
namespace Umbraco.Web.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// Adapted from Microsoft.AspNet.Identity.Owin.IdentityFactoryMiddleware
|
||||
/// </summary>
|
||||
public class IdentityFactoryMiddleware<TResult, TOptions> : OwinMiddleware
|
||||
where TResult : class, IDisposable
|
||||
where TOptions : IdentityFactoryOptions<TResult>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="next">The next middleware in the OWIN pipeline to invoke</param>
|
||||
/// <param name="options">Configuration options for the middleware</param>
|
||||
public IdentityFactoryMiddleware(OwinMiddleware next, TOptions options)
|
||||
: base(next)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException("options");
|
||||
}
|
||||
if (options.Provider == null)
|
||||
{
|
||||
throw new ArgumentNullException("options.Provider");
|
||||
}
|
||||
Options = options;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configuration options
|
||||
/// </summary>
|
||||
public TOptions Options { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Create an object using the Options.Provider, storing it in the OwinContext and then disposes the object when finished
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task Invoke(IOwinContext context)
|
||||
{
|
||||
var instance = Options.Provider.Create(Options, context);
|
||||
try
|
||||
{
|
||||
context.Set(instance);
|
||||
if (Next != null)
|
||||
{
|
||||
await Next.Invoke(context);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Options.Provider.Dispose(Options, instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class IdentityFactoryOptions<T> where T : class, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to configure the data protection provider
|
||||
/// </summary>
|
||||
public IDataProtectionProvider DataProtectionProvider { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Provider used to Create and Dispose objects
|
||||
/// </summary>
|
||||
public IdentityFactoryProvider<T> Provider { get; set; }
|
||||
}
|
||||
|
||||
public class IdentityFactoryProvider<T> where T : class, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public IdentityFactoryProvider()
|
||||
{
|
||||
OnDispose = (options, instance) => { };
|
||||
OnCreate = (options, context) => null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A delegate assigned to this property will be invoked when the related method is called
|
||||
/// </summary>
|
||||
public Func<IdentityFactoryOptions<T>, IOwinContext, T> OnCreate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A delegate assigned to this property will be invoked when the related method is called
|
||||
/// </summary>
|
||||
public Action<IdentityFactoryOptions<T>, T> OnDispose { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Calls the OnCreate Delegate
|
||||
/// </summary>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public virtual T Create(IdentityFactoryOptions<T> options, IOwinContext context)
|
||||
{
|
||||
return OnCreate(options, context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls the OnDispose delegate
|
||||
/// </summary>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="instance"></param>
|
||||
public virtual void Dispose(IdentityFactoryOptions<T> options, T instance)
|
||||
{
|
||||
OnDispose(options, instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,7 +77,7 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="LightInject.WebApi" Version="2.0.0" />
|
||||
<PackageReference Include="Markdown" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.AspNet.Identity.Owin" Version="2.2.2" />
|
||||
<PackageReference Include="Microsoft.AspNet.Identity.Core" Version="2.2.3" />
|
||||
<PackageReference Include="Microsoft.AspNet.Mvc" Version="5.2.7" />
|
||||
<PackageReference Include="Microsoft.AspNet.SignalR.Core" Version="2.4.0" />
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi" Version="5.2.7" />
|
||||
@@ -147,6 +147,7 @@
|
||||
<Compile Include="Compose\BackOfficeUserAuditEventsComposer.cs" />
|
||||
<Compile Include="Composing\CompositionExtensions\Installer.cs" />
|
||||
<Compile Include="Composing\LightInject\LightInjectContainer.cs" />
|
||||
<Compile Include="Security\IdentityFactoryMiddleware.cs" />
|
||||
<Compile Include="WebAssets\CDF\ClientDependencyRuntimeMinifier.cs" />
|
||||
<Compile Include="Models\NoNodesViewModel.cs" />
|
||||
<Compile Include="Mvc\RenderNoContentController.cs" />
|
||||
|
||||
Reference in New Issue
Block a user