diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/ClaimDestinations/AbpDefaultOpenIddictClaimDestinationsProvider.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/ClaimDestinations/AbpDefaultOpenIddictClaimDestinationsProvider.cs
index 7f54cd81aa..a9db913286 100644
--- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/ClaimDestinations/AbpDefaultOpenIddictClaimDestinationsProvider.cs
+++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/ClaimDestinations/AbpDefaultOpenIddictClaimDestinationsProvider.cs
@@ -2,6 +2,7 @@
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
+using Microsoft.IdentityModel.JsonWebTokens;
using OpenIddict.Abstractions;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Security.Claims;
@@ -35,6 +36,14 @@ public class AbpDefaultOpenIddictClaimDestinationsProvider : IAbpOpenIddictClaim
}
break;
+ case JwtRegisteredClaimNames.UniqueName:
+ claim.SetDestinations(OpenIddictConstants.Destinations.AccessToken);
+ if (context.Principal.HasScope(OpenIddictConstants.Scopes.Profile))
+ {
+ claim.SetDestinations(OpenIddictConstants.Destinations.AccessToken, OpenIddictConstants.Destinations.IdentityToken);
+ }
+ break;
+
case OpenIddictConstants.Claims.Email:
claim.SetDestinations(OpenIddictConstants.Destinations.AccessToken);
if (context.Principal.HasScope(OpenIddictConstants.Scopes.Email))
diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/OpenIddictClaimsPrincipalContributor.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/OpenIddictClaimsPrincipalContributor.cs
new file mode 100644
index 0000000000..9a4c027f97
--- /dev/null
+++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/OpenIddictClaimsPrincipalContributor.cs
@@ -0,0 +1,35 @@
+using System.Linq;
+using System.Security.Claims;
+using System.Security.Principal;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using Microsoft.IdentityModel.JsonWebTokens;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Security.Claims;
+
+namespace Volo.Abp.OpenIddict;
+
+///
+/// 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
+///
+public class OpenIddictClaimsPrincipalContributor : IAbpClaimsPrincipalContributor, ITransientDependency
+{
+ public Task ContributeAsync(AbpClaimsPrincipalContributorContext context)
+ {
+ var identity = context.ClaimsPrincipal.Identities.FirstOrDefault();
+ if (identity != null)
+ {
+ var options = context.ServiceProvider.GetRequiredService>().Value;
+ var usernameClaim = identity.FindFirst(options.ClaimsIdentity.UserNameClaimType);
+ if (usernameClaim != null)
+ {
+ identity.AddIfNotContains(new Claim(JwtRegisteredClaimNames.UniqueName, usernameClaim.Value));
+ }
+ }
+
+ return Task.CompletedTask;
+ }
+}