Browse Source

Resolved #4985: Change AbpResourceOwnerPasswordValidator to support the external login system.

pull/5022/head
Halil İbrahim Kalkan 6 years ago
parent
commit
4d53c3fd97
  1. 7
      modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpIdentityAspNetCoreOptions.cs
  2. 4
      modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs
  3. 12
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityOptions.cs
  4. 2
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs
  5. 5
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderDictionary.cs
  6. 2
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderInfo.cs
  7. 4
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginUserInfo.cs
  8. 2
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProvider.cs
  9. 3
      modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/AbpIdentityAspNetCoreTestModule.cs
  10. 2
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.csproj.DotSettings
  11. 91
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs

7
modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpIdentityAspNetCoreOptions.cs

@ -6,12 +6,5 @@
/// Default: true. /// Default: true.
/// </summary> /// </summary>
public bool ConfigureAuthentication { get; set; } = true; public bool ConfigureAuthentication { get; set; } = true;
public ExternalLoginProviderDictionary ExternalLoginProviders { get; }
public AbpIdentityAspNetCoreOptions()
{
ExternalLoginProviders = new ExternalLoginProviderDictionary();
}
} }
} }

4
modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs

@ -10,7 +10,7 @@ namespace Volo.Abp.Identity.AspNetCore
{ {
public class AbpSignInManager : SignInManager<IdentityUser> public class AbpSignInManager : SignInManager<IdentityUser>
{ {
protected AbpIdentityAspNetCoreOptions AbpOptions { get; } protected AbpIdentityOptions AbpOptions { get; }
public AbpSignInManager( public AbpSignInManager(
IdentityUserManager userManager, IdentityUserManager userManager,
@ -20,7 +20,7 @@ namespace Volo.Abp.Identity.AspNetCore
ILogger<SignInManager<IdentityUser>> logger, ILogger<SignInManager<IdentityUser>> logger,
IAuthenticationSchemeProvider schemes, IAuthenticationSchemeProvider schemes,
IUserConfirmation<IdentityUser> confirmation, IUserConfirmation<IdentityUser> confirmation,
IOptions<AbpIdentityAspNetCoreOptions> options IOptions<AbpIdentityOptions> options
) : base( ) : base(
userManager, userManager,
contextAccessor, contextAccessor,

12
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityOptions.cs

@ -0,0 +1,12 @@
namespace Volo.Abp.Identity
{
public class AbpIdentityOptions
{
public ExternalLoginProviderDictionary ExternalLoginProviders { get; }
public AbpIdentityOptions()
{
ExternalLoginProviders = new ExternalLoginProviderDictionary();
}
}
}

2
modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/ExternalLoginProviderBase.cs → modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs

@ -6,7 +6,7 @@ using Volo.Abp.Domain.Repositories;
using Volo.Abp.Guids; using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Identity.AspNetCore namespace Volo.Abp.Identity
{ {
public abstract class ExternalLoginProviderBase : IExternalLoginProvider public abstract class ExternalLoginProviderBase : IExternalLoginProvider
{ {

5
modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/ExternalLoginProviderDictionary.cs → modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderDictionary.cs

@ -1,8 +1,7 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using JetBrains.Annotations; using JetBrains.Annotations;
namespace Volo.Abp.Identity.AspNetCore namespace Volo.Abp.Identity
{ {
public class ExternalLoginProviderDictionary : Dictionary<string, ExternalLoginProviderInfo> public class ExternalLoginProviderDictionary : Dictionary<string, ExternalLoginProviderInfo>
{ {

2
modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/ExternalLoginProviderInfo.cs → modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderInfo.cs

@ -1,7 +1,7 @@
using System; using System;
using JetBrains.Annotations; using JetBrains.Annotations;
namespace Volo.Abp.Identity.AspNetCore namespace Volo.Abp.Identity
{ {
public class ExternalLoginProviderInfo public class ExternalLoginProviderInfo
{ {

4
modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/ExternalLoginUserInfo.cs → modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginUserInfo.cs

@ -1,6 +1,6 @@
using JetBrains.Annotations; using JetBrains.Annotations;
namespace Volo.Abp.Identity.AspNetCore namespace Volo.Abp.Identity
{ {
public class ExternalLoginUserInfo public class ExternalLoginUserInfo
{ {
@ -28,7 +28,7 @@ namespace Volo.Abp.Identity.AspNetCore
[CanBeNull] [CanBeNull]
public string ProviderKey { get; set; } public string ProviderKey { get; set; }
public ExternalLoginUserInfo([System.Diagnostics.CodeAnalysis.NotNull] string email) public ExternalLoginUserInfo([NotNull] string email)
{ {
Email = Check.NotNullOrWhiteSpace(email, nameof(email)); Email = Check.NotNullOrWhiteSpace(email, nameof(email));
} }

2
modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/IExternalLoginProvider.cs → modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProvider.cs

@ -1,6 +1,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Volo.Abp.Identity.AspNetCore namespace Volo.Abp.Identity
{ {
public interface IExternalLoginProvider public interface IExternalLoginProvider
{ {

3
modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/AbpIdentityAspNetCoreTestModule.cs

@ -1,7 +1,6 @@
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc.ApplicationParts; using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.TestBase; using Volo.Abp.AspNetCore.TestBase;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
@ -26,7 +25,7 @@ namespace Volo.Abp.Identity.AspNetCore
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
Configure<AbpIdentityAspNetCoreOptions>(options => Configure<AbpIdentityOptions>(options =>
{ {
options.ExternalLoginProviders.Add<FakeExternalLoginProvider>(FakeExternalLoginProvider.Name); options.ExternalLoginProviders.Add<FakeExternalLoginProvider>(FakeExternalLoginProvider.Name);
}); });

2
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.csproj.DotSettings

@ -1,2 +0,0 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp71</s:String></wpf:ResourceDictionary>

91
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs

@ -1,4 +1,6 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims; using System.Security.Claims;
using System.Threading.Tasks; using System.Threading.Tasks;
using IdentityModel; using IdentityModel;
@ -8,8 +10,11 @@ using IdentityServer4.Models;
using IdentityServer4.Services; using IdentityServer4.Services;
using IdentityServer4.Validation; using IdentityServer4.Validation;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Identity; using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.Localization; using Volo.Abp.IdentityServer.Localization;
using Volo.Abp.Security.Claims; using Volo.Abp.Security.Claims;
@ -27,6 +32,8 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity
protected IdentitySecurityLogManager IdentitySecurityLogManager { get; } protected IdentitySecurityLogManager IdentitySecurityLogManager { get; }
protected ILogger<ResourceOwnerPasswordValidator<IdentityUser>> Logger { get; } protected ILogger<ResourceOwnerPasswordValidator<IdentityUser>> Logger { get; }
protected IStringLocalizer<AbpIdentityServerResource> Localizer { get; } protected IStringLocalizer<AbpIdentityServerResource> Localizer { get; }
protected IHybridServiceScopeFactory ServiceScopeFactory { get; }
protected AbpIdentityOptions AbpIdentityOptions { get; }
public AbpResourceOwnerPasswordValidator( public AbpResourceOwnerPasswordValidator(
UserManager<IdentityUser> userManager, UserManager<IdentityUser> userManager,
@ -34,7 +41,9 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity
IdentitySecurityLogManager identitySecurityLogManager, IdentitySecurityLogManager identitySecurityLogManager,
IEventService events, IEventService events,
ILogger<ResourceOwnerPasswordValidator<IdentityUser>> logger, ILogger<ResourceOwnerPasswordValidator<IdentityUser>> logger,
IStringLocalizer<AbpIdentityServerResource> localizer) IStringLocalizer<AbpIdentityServerResource> localizer,
IOptions<AbpIdentityOptions> abpIdentityOptions,
IHybridServiceScopeFactory serviceScopeFactory)
{ {
UserManager = userManager; UserManager = userManager;
SignInManager = signInManager; SignInManager = signInManager;
@ -42,6 +51,8 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity
Events = events; Events = events;
Logger = logger; Logger = logger;
Localizer = localizer; Localizer = localizer;
ServiceScopeFactory = serviceScopeFactory;
AbpIdentityOptions = abpIdentityOptions.Value;
} }
/// <summary> /// <summary>
@ -52,35 +63,71 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity
[UnitOfWork] [UnitOfWork]
public virtual async Task ValidateAsync(ResourceOwnerPasswordValidationContext context) public virtual async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{ {
using var scope = ServiceScopeFactory.CreateScope();
await ReplaceEmailToUsernameOfInputIfNeeds(context); await ReplaceEmailToUsernameOfInputIfNeeds(context);
var user = await UserManager.FindByNameAsync(context.UserName);
string errorDescription; IdentityUser user = null;
if (user != null)
async Task SetSuccessResultAsync()
{ {
var result = await SignInManager.CheckPasswordSignInAsync(user, context.Password, true); var sub = await UserManager.GetUserIdAsync(user);
if (result.Succeeded)
{
var sub = await UserManager.GetUserIdAsync(user);
Logger.LogInformation("Credentials validated for username: {username}", context.UserName); Logger.LogInformation("Credentials validated for username: {username}", context.UserName);
await Events.RaiseAsync(new UserLoginSuccessEvent(context.UserName, sub, context.UserName, interactive: false)); await Events.RaiseAsync(new UserLoginSuccessEvent(context.UserName, sub, context.UserName, interactive: false));
var additionalClaims = new List<Claim>(); var additionalClaims = new List<Claim>();
await AddCustomClaimsAsync(additionalClaims, user, context); await AddCustomClaimsAsync(additionalClaims, user, context);
context.Result = new GrantValidationResult( context.Result = new GrantValidationResult(
sub, sub,
OidcConstants.AuthenticationMethods.Password, OidcConstants.AuthenticationMethods.Password,
additionalClaims.ToArray() additionalClaims.ToArray()
); );
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() await IdentitySecurityLogManager.SaveAsync(
new IdentitySecurityLogContext
{ {
Identity = IdentityServerSecurityLogIdentityConsts.IdentityServer, Identity = IdentityServerSecurityLogIdentityConsts.IdentityServer,
Action = result.ToIdentitySecurityLogAction(), Action = IdentityServerSecurityLogActionConsts.LoginSucceeded
}); }
);
}
if (AbpIdentityOptions.ExternalLoginProviders.Any())
{
foreach (var externalLoginProviderInfo in AbpIdentityOptions.ExternalLoginProviders.Values)
{
var externalLoginProvider = (IExternalLoginProvider) scope.ServiceProvider
.GetRequiredService(externalLoginProviderInfo.Type);
if (await externalLoginProvider.TryAuthenticateAsync(context.UserName, context.Password))
{
user = await UserManager.FindByNameAsync(context.UserName);
if (user == null)
{
user = await externalLoginProvider.CreateUserAsync(context.UserName, externalLoginProviderInfo.Name);
}
else
{
await externalLoginProvider.UpdateUserAsync(user, externalLoginProviderInfo.Name);
}
await SetSuccessResultAsync();
return;
}
}
}
user = await UserManager.FindByNameAsync(context.UserName);
string errorDescription;
if (user != null)
{
var result = await SignInManager.CheckPasswordSignInAsync(user, context.Password, true);
if (result.Succeeded)
{
await SetSuccessResultAsync();
return; return;
} }
else if (result.IsLockedOut) else if (result.IsLockedOut)
@ -102,7 +149,7 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity
errorDescription = Localizer["InvalidUserNameOrPassword"]; errorDescription = Localizer["InvalidUserNameOrPassword"];
} }
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext
{ {
Identity = IdentityServerSecurityLogIdentityConsts.IdentityServer, Identity = IdentityServerSecurityLogIdentityConsts.IdentityServer,
Action = result.ToIdentitySecurityLogAction(), Action = result.ToIdentitySecurityLogAction(),

Loading…
Cancel
Save