Browse Source

Merge pull request #9301 from abpframework/maliming/impersonation

Add Impersonation infrastructure.
pull/9371/head
İsmail ÇAĞDAŞ 5 years ago
committed by GitHub
parent
commit
cfc648bc65
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentUserDto.cs
  2. 2
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs
  3. 117
      framework/src/Volo.Abp.Security/System/Security/Principal/AbpClaimsIdentityExtensions.cs
  4. 10
      framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimTypes.cs
  5. 33
      framework/src/Volo.Abp.Security/Volo/Abp/Users/CurrentUserExtensions.cs
  6. 2
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpClaimsService.cs
  7. 2
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs
  8. 152
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/LinkLoginExtensionGrantValidator.cs

4
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentUserDto.cs

@ -11,6 +11,10 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
public Guid? TenantId { get; set; }
public Guid? ImpersonatorUserId { get; set; }
public Guid? ImpersonatorTenantId { get; set; }
public string UserName { get; set; }
public string Name { get; set; }

2
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs

@ -127,6 +127,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
IsAuthenticated = _currentUser.IsAuthenticated,
Id = _currentUser.Id,
TenantId = _currentUser.TenantId,
ImpersonatorUserId = _currentUser.FindImpersonatorUserId(),
ImpersonatorTenantId = _currentUser.FindImpersonatorTenantId(),
UserName = _currentUser.UserName,
SurName = _currentUser.SurName,
Name = _currentUser.Name,

117
framework/src/Volo.Abp.Security/System/Security/Principal/AbpClaimsIdentityExtensions.cs

@ -17,10 +17,12 @@ namespace System.Security.Principal
{
return null;
}
if (Guid.TryParse(userIdOrNull.Value, out Guid result))
if (Guid.TryParse(userIdOrNull.Value, out Guid guid))
{
return result;
return guid;
}
return null;
}
@ -36,7 +38,12 @@ namespace System.Security.Principal
return null;
}
return Guid.Parse(userIdOrNull.Value);
if (Guid.TryParse(userIdOrNull.Value, out var guid))
{
return guid;
}
return null;
}
public static Guid? FindTenantId([NotNull] this ClaimsPrincipal principal)
@ -49,7 +56,12 @@ namespace System.Security.Principal
return null;
}
return Guid.Parse(tenantIdOrNull.Value);
if (Guid.TryParse(tenantIdOrNull.Value, out var guid))
{
return guid;
}
return null;
}
public static Guid? FindTenantId([NotNull] this IIdentity identity)
@ -64,7 +76,12 @@ namespace System.Security.Principal
return null;
}
return Guid.Parse(tenantIdOrNull.Value);
if (Guid.TryParse(tenantIdOrNull.Value, out var guid))
{
return guid;
}
return null;
}
public static string FindClientId([NotNull] this ClaimsPrincipal principal)
@ -105,7 +122,12 @@ namespace System.Security.Principal
return null;
}
return Guid.Parse(editionIdOrNull.Value);
if (Guid.TryParse(editionIdOrNull.Value, out var guid))
{
return guid;
}
return null;
}
public static Guid? FindEditionId([NotNull] this IIdentity identity)
@ -120,7 +142,88 @@ namespace System.Security.Principal
return null;
}
return Guid.Parse(editionIdOrNull.Value);
if (Guid.TryParse(editionIdOrNull.Value, out var guid))
{
return guid;
}
return null;
}
public static Guid? FindImpersonatorTenantId([NotNull] this ClaimsPrincipal principal)
{
Check.NotNull(principal, nameof(principal));
var impersonatorTenantIdOrNull = principal.Claims?.FirstOrDefault(c => c.Type == AbpClaimTypes.ImpersonatorTenantId);
if (impersonatorTenantIdOrNull == null || impersonatorTenantIdOrNull.Value.IsNullOrWhiteSpace())
{
return null;
}
if (Guid.TryParse(impersonatorTenantIdOrNull.Value, out var guid))
{
return guid;
}
return null;
}
public static Guid? FindImpersonatorTenantId([NotNull] this IIdentity identity)
{
Check.NotNull(identity, nameof(identity));
var claimsIdentity = identity as ClaimsIdentity;
var impersonatorTenantIdOrNull = claimsIdentity?.Claims?.FirstOrDefault(c => c.Type == AbpClaimTypes.ImpersonatorTenantId);
if (impersonatorTenantIdOrNull == null || impersonatorTenantIdOrNull.Value.IsNullOrWhiteSpace())
{
return null;
}
if (Guid.TryParse(impersonatorTenantIdOrNull.Value, out var guid))
{
return guid;
}
return null;
}
public static Guid? FindImpersonatorUserId([NotNull] this ClaimsPrincipal principal)
{
Check.NotNull(principal, nameof(principal));
var impersonatorUserIdOrNull = principal.Claims?.FirstOrDefault(c => c.Type == AbpClaimTypes.ImpersonatorUserId);
if (impersonatorUserIdOrNull == null || impersonatorUserIdOrNull.Value.IsNullOrWhiteSpace())
{
return null;
}
if (Guid.TryParse(impersonatorUserIdOrNull.Value, out var guid))
{
return guid;
}
return null;
}
public static Guid? FindImpersonatorUserId([NotNull] this IIdentity identity)
{
Check.NotNull(identity, nameof(identity));
var claimsIdentity = identity as ClaimsIdentity;
var impersonatorUserIdOrNull = claimsIdentity?.Claims?.FirstOrDefault(c => c.Type == AbpClaimTypes.ImpersonatorUserId);
if (impersonatorUserIdOrNull == null || impersonatorUserIdOrNull.Value.IsNullOrWhiteSpace())
{
return null;
}
if (Guid.TryParse(impersonatorUserIdOrNull.Value, out var guid))
{
return guid;
}
return null;
}
public static ClaimsIdentity AddIfNotContains(this ClaimsIdentity claimsIdentity, Claim claim)

10
framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimTypes.cs

@ -67,5 +67,15 @@ namespace Volo.Abp.Security.Claims
/// Default: "client_id".
/// </summary>
public static string ClientId { get; set; } = "client_id";
/// <summary>
/// Default: "impersonator_tenantid".
/// </summary>
public static string ImpersonatorTenantId { get; set; } = "impersonator_tenantid";
/// <summary>
/// Default: "impersonator_userid".
/// </summary>
public static string ImpersonatorUserId { get; set; } = "impersonator_userid";
}
}

33
framework/src/Volo.Abp.Security/Volo/Abp/Users/CurrentUserExtensions.cs

@ -1,6 +1,7 @@
using System;
using System.Diagnostics;
using JetBrains.Annotations;
using Volo.Abp.Security.Claims;
namespace Volo.Abp.Users
{
@ -30,5 +31,35 @@ namespace Volo.Abp.Users
return currentUser.Id.Value;
}
public static Guid? FindImpersonatorTenantId([NotNull] this ICurrentUser currentUser)
{
var impersonatorTenantId = currentUser.FindClaimValue(AbpClaimTypes.ImpersonatorTenantId);
if (impersonatorTenantId == null || impersonatorTenantId.IsNullOrWhiteSpace())
{
return null;
}
if (Guid.TryParse(impersonatorTenantId, out var guid))
{
return guid;
}
return null;
}
public static Guid? FindImpersonatorUserId([NotNull] this ICurrentUser currentUser)
{
var impersonatorUserId = currentUser.FindClaimValue(AbpClaimTypes.ImpersonatorUserId);
if (impersonatorUserId == null || impersonatorUserId.IsNullOrWhiteSpace())
{
return null;
}
if (Guid.TryParse(impersonatorUserId, out var guid))
{
return guid;
}
return null;
}
}
}
}

2
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpClaimsService.cs

@ -16,6 +16,8 @@ namespace Volo.Abp.IdentityServer
private static readonly string[] AdditionalOptionalClaimNames =
{
AbpClaimTypes.TenantId,
AbpClaimTypes.ImpersonatorTenantId,
AbpClaimTypes.ImpersonatorUserId,
AbpClaimTypes.Name,
AbpClaimTypes.SurName,
JwtClaimTypes.PreferredUserName,

2
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs

@ -107,8 +107,6 @@ namespace Volo.Abp.IdentityServer
identityServerBuilder.AddInMemoryApiResources(configuration.GetSection("IdentityServer:ApiResources"));
identityServerBuilder.AddInMemoryIdentityResources(configuration.GetSection("IdentityServer:IdentityResources"));
}
identityServerBuilder.AddExtensionGrantValidator<LinkLoginExtensionGrantValidator>();
}
public override void PostConfigureServices(ServiceConfigurationContext context)

152
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/LinkLoginExtensionGrantValidator.cs

@ -1,152 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using IdentityServer4.Validation;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.Localization;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Security.Claims;
using Volo.Abp.Users;
using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace Volo.Abp.IdentityServer.AspNetIdentity
{
public class LinkLoginExtensionGrantValidator : IExtensionGrantValidator
{
public const string ExtensionGrantType = "LinkLogin";
public string GrantType => ExtensionGrantType;
protected ITokenValidator TokenValidator { get; }
protected IdentityLinkUserManager IdentityLinkUserManager { get; }
protected ICurrentTenant CurrentTenant { get; }
protected ICurrentUser CurrentUser { get; }
protected ICurrentPrincipalAccessor CurrentPrincipalAccessor { get; }
protected IdentityUserManager UserManager { get; }
protected IdentitySecurityLogManager IdentitySecurityLogManager { get; }
protected ILogger<LinkLoginExtensionGrantValidator> Logger { get; }
protected IStringLocalizer<AbpIdentityServerResource> Localizer { get; }
public LinkLoginExtensionGrantValidator(
ITokenValidator tokenValidator,
IdentityLinkUserManager identityLinkUserManager,
ICurrentTenant currentTenant,
ICurrentUser currentUser,
IdentityUserManager userManager,
ICurrentPrincipalAccessor currentPrincipalAccessor,
IdentitySecurityLogManager identitySecurityLogManager,
ILogger<LinkLoginExtensionGrantValidator> logger,
IStringLocalizer<AbpIdentityServerResource> localizer)
{
TokenValidator = tokenValidator;
IdentityLinkUserManager = identityLinkUserManager;
CurrentTenant = currentTenant;
CurrentUser = currentUser;
UserManager = userManager;
CurrentPrincipalAccessor = currentPrincipalAccessor;
IdentitySecurityLogManager = identitySecurityLogManager;
Logger = logger;
Localizer = localizer;
}
public virtual async Task ValidateAsync(ExtensionGrantValidationContext context)
{
var accessToken = context.Request.Raw["access_token"];
if (accessToken.IsNullOrWhiteSpace())
{
context.Result = new GrantValidationResult
{
IsError = true,
Error = "invalid_access_token"
};
return;
}
var result = await TokenValidator.ValidateAccessTokenAsync(accessToken);
if (result.IsError)
{
context.Result = new GrantValidationResult
{
IsError = true,
Error = result.Error,
ErrorDescription = result.ErrorDescription
};
return;
}
using (CurrentPrincipalAccessor.Change(result.Claims))
{
if (!Guid.TryParse(context.Request.Raw["LinkUserId"], out var linkUserId))
{
context.Result = new GrantValidationResult
{
IsError = true,
Error = "invalid_link_user_id"
};
return;
}
Guid? linkTenantId = null;
if (!context.Request.Raw["LinkTenantId"].IsNullOrWhiteSpace())
{
if (!Guid.TryParse(context.Request.Raw["LinkTenantId"], out var parsedGuid))
{
context.Result = new GrantValidationResult
{
IsError = true,
Error = "invalid_link_tenant_id"
};
return;
}
linkTenantId = parsedGuid;
}
var isLinked = await IdentityLinkUserManager.IsLinkedAsync(
new IdentityLinkUserInfo(CurrentUser.GetId(), CurrentTenant.Id),
new IdentityLinkUserInfo(linkUserId, linkTenantId),
true);
if (isLinked)
{
using (CurrentTenant.Change(linkTenantId))
{
var user = await UserManager.GetByIdAsync(linkUserId);
var sub = await UserManager.GetUserIdAsync(user);
var additionalClaims = new List<Claim>();
await AddCustomClaimsAsync(additionalClaims, user, context);
context.Result = new GrantValidationResult(
sub,
GrantType,
additionalClaims.ToArray()
);
}
}
else
{
context.Result = new GrantValidationResult
{
IsError = true,
Error = Localizer["TheTargetUserIsNotLinkedToYou"]
};
}
}
}
protected virtual Task AddCustomClaimsAsync(List<Claim> customClaims, IdentityUser user, ExtensionGrantValidationContext context)
{
if (user.TenantId.HasValue)
{
customClaims.Add(new Claim(AbpClaimTypes.TenantId, user.TenantId?.ToString()));
}
return Task.CompletedTask;
}
}
}
Loading…
Cancel
Save