but I need to be able to impersonate a tenant user from the host.
This is not supported by default, can you share your code?
hi
This is an unknown problem, We will release a new 6.0 patch version.
https://github.com/abpframework/abp/pull/14306
After connecting to the company vpn, I cannot access abp.io
How about other websites?
nuget.org myget.org etc?
You can try to abp login
before connecting the vpn.
hi
You can use UserManager<Volo.Abp.Identity.IdentityUser>
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.identity.usermanager-1.getloginsasync?view=aspnetcore-6.0
hi
You can try to reach the abp.io
in your computer browser.
hi
Unable to get the email of external user!
Try to debug the MapClaimsToExternalLoginUserInfoAsync
method. share the values of claims
Configure<AbpIdentityOptions>(options =>
{
options.ExternalLoginProviders.RemoveAll(x => x.Key == "OAuth");
options.ExternalLoginProviders.Add<MyOAuthExternalLoginProvider>(MyOAuthExternalLoginProvider.Name);
});
public class MyOAuthExternalLoginProvider : OAuthExternalLoginProvider
{
public const string Name = "OAuth";
public ILogger<OAuthExternalLoginProvider> Logger { get; set; }
protected OAuthExternalLoginManager OAuthExternalLoginManager { get; }
protected ISettingProvider SettingProvider { get; }
protected IFeatureChecker FeatureChecker { get; }
protected AbpOAuthExternalLoginProviderOptions Options { get; }
public MyOAuthExternalLoginProvider(
IGuidGenerator guidGenerator,
ICurrentTenant currentTenant,
IdentityUserManager userManager,
IIdentityUserRepository identityUserRepository,
IOptions<IdentityOptions> identityOptions,
OAuthExternalLoginManager oAuthExternalLoginManager,
ISettingProvider settingProvider,
IFeatureChecker featureChecker,
IOptions<AbpOAuthExternalLoginProviderOptions> options)
: base(guidGenerator, currentTenant, userManager, identityUserRepository, identityOptions, oAuthExternalLoginManager, settingProvider, featureChecker, options)
{
}
protected override Task<ExternalLoginUserInfo> MapClaimsToExternalLoginUserInfoAsync(IEnumerable<Claim> claims)
{
var claimsArray = claims as Claim[] ?? claims.ToArray();
var email = claimsArray.FirstOrDefault(x => x.Type == Options.EmailClaimType);
if(email == null)
{
throw new Exception("Unable to get the email of external user!");
}
var userInfo = new ExternalLoginUserInfo(email.Value)
{
Name = claimsArray.FirstOrDefault(x => x.Type == Options.NameClaimType)?.Value,
Surname = claimsArray.FirstOrDefault(x => x.Type == Options.SurnameClaimType)?.Value,
EmailConfirmed = claimsArray.FirstOrDefault(x => x.Type == Options.EmailConfirmedClaimType)?.Value.To<bool>() ?? false,
PhoneNumber = claimsArray.FirstOrDefault(x => x.Type == Options.PhoneNumberClaimType)?.Value,
PhoneNumberConfirmed = claimsArray.FirstOrDefault(x => x.Type == Options.PhoneNumberConfirmedClaimType)?.Value.To<bool>() ?? false,
ProviderKey = claimsArray.FirstOrDefault(x => x.Type == Options.ProviderKeyClaimType)?.Value
};
return Task.FromResult(userInfo);
}
}
hi
You can refer to Identity Server documentation, ABP framework has not changed its behavior.
hi
Can you try to use Configure
?
Configure<OpenIddictServerAspNetCoreBuilder>(configure =>
{
configure.DisableTransportSecurityRequirement();
});
hi
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.Replace(ServiceDescriptor.Transient<IUserClaimsPrincipalFactory<IdentityUser>, MyUserClaimsFactory<IdentityUser>>());
}
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading.Tasks;
using IdentityModel;
using Microsoft.AspNetCore.Identity;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Security.Claims;
using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace AbpApplicationTemplate;
public class MyUserClaimsFactory<TUser> : IUserClaimsPrincipalFactory<TUser>
where TUser : class
{
private readonly IObjectAccessor<IUserClaimsPrincipalFactory<TUser>> _inner;
private readonly UserManager<TUser> _userManager;
private readonly ICurrentPrincipalAccessor _currentPrincipalAccessor;
private readonly IAbpClaimsPrincipalFactory _abpClaimsPrincipalFactory;
public MyUserClaimsFactory(IObjectAccessor<IUserClaimsPrincipalFactory<TUser>> inner,
UserManager<TUser> userManager, ICurrentPrincipalAccessor currentPrincipalAccessor, IAbpClaimsPrincipalFactory abpClaimsPrincipalFactory)
{
_inner = inner;
_userManager = userManager;
_currentPrincipalAccessor = currentPrincipalAccessor;
_abpClaimsPrincipalFactory = abpClaimsPrincipalFactory;
}
public async Task<ClaimsPrincipal> CreateAsync(TUser user)
{
var principal = await _inner.Value.CreateAsync(user);
var identity = principal.Identities.First();
if (!identity.HasClaim(x => x.Type == JwtClaimTypes.Subject))
{
var sub = await _userManager.GetUserIdAsync(user);
identity.AddIfNotContains(new Claim(JwtClaimTypes.Subject, sub));
}
var username = await _userManager.GetUserNameAsync(user);
var usernameClaim = identity.FindFirst(claim =>
claim.Type == _userManager.Options.ClaimsIdentity.UserNameClaimType && claim.Value == username);
if (usernameClaim != null)
{
identity.RemoveClaim(usernameClaim);
identity.AddIfNotContains(new Claim(JwtClaimTypes.PreferredUserName, username));
//https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/1627
//https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/05e02b5e0383be40e45c667c12f6667d38e33fcc/src/System.IdentityModel.Tokens.Jwt/ClaimTypeMapping.cs#L52
identity.AddIfNotContains(new Claim(JwtRegisteredClaimNames.UniqueName, username));
}
if (!identity.HasClaim(x => x.Type == JwtClaimTypes.Name))
{
identity.AddIfNotContains(new Claim(JwtClaimTypes.Name, username));
}
if (_userManager.SupportsUserEmail)
{
var email = await _userManager.GetEmailAsync(user);
if (!string.IsNullOrWhiteSpace(email))
{
identity.AddIfNotContains(new Claim(JwtClaimTypes.Email, email));
identity.AddIfNotContains(new Claim(JwtClaimTypes.EmailVerified,
await _userManager.IsEmailConfirmedAsync(user) ? "true" : "false", ClaimValueTypes.Boolean));
}
}
if (_userManager.SupportsUserPhoneNumber)
{
var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
if (!string.IsNullOrWhiteSpace(phoneNumber))
{
identity.AddIfNotContains(new Claim(JwtClaimTypes.PhoneNumber, phoneNumber));
identity.AddIfNotContains(new Claim(JwtClaimTypes.PhoneNumberVerified,
await _userManager.IsPhoneNumberConfirmedAsync(user) ? "true" : "false",
ClaimValueTypes.Boolean));
}
}
if (user is IdentityUser identityUser)
{
if (!identityUser.Name.IsNullOrEmpty())
{
identity.AddIfNotContains(new Claim(JwtClaimTypes.GivenName, identityUser.Name));
}
if (!identityUser.Surname.IsNullOrEmpty())
{
identity.AddIfNotContains(new Claim(JwtClaimTypes.FamilyName, identityUser.Surname));
}
}
using (_currentPrincipalAccessor.Change(identity))
{
await _abpClaimsPrincipalFactory.CreateAsync(principal);
}
return principal;
}
}
hi
You need to depend on AbpIdentityDomainModule
& AbpIdentityEntityFrameworkCoreModule
and then inject OrganizationUnitManager
.