diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs index d07cca857f..01e0dd7ae9 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs @@ -3,11 +3,15 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.OAuth.Claims; using Microsoft.AspNetCore.Authentication.OpenIdConnect; +using Microsoft.AspNetCore.Localization; +using Microsoft.AspNetCore.RequestLocalization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Protocols.OpenIdConnect; +using Volo.Abp; using Volo.Abp.AspNetCore.Authentication.OpenIdConnect; using Volo.Abp.AspNetCore.MultiTenancy; +using Volo.Abp.Localization; using Volo.Abp.Security.Claims; namespace Microsoft.Extensions.DependencyInjection; @@ -52,6 +56,7 @@ public static class AbpOpenIdConnectExtensions options.Events.OnTokenValidated = async (context) => { + var logger = context.HttpContext.RequestServices.GetRequiredService>(); var client = context.HttpContext.RequestServices.GetRequiredService(); try { @@ -59,8 +64,28 @@ public static class AbpOpenIdConnectExtensions } catch (Exception ex) { - var logger = context.HttpContext.RequestServices.GetService>(); - logger?.LogException(ex); + logger.LogException(ex); + } + + var culture = context.ProtocolMessage.GetParameter("culture"); + var uiCulture = context.ProtocolMessage.GetParameter("ui-culture"); + if (CultureHelper.IsValidCultureCode(culture) && CultureHelper.IsValidCultureCode(uiCulture)) + { + context.Response.OnStarting(() => + { + logger.LogInformation($"Setting culture and ui-culture to the response. culture: {culture}, ui-culture: {uiCulture}"); + + AbpRequestCultureCookieHelper.SetCultureCookie( + context.HttpContext, + new RequestCulture(culture, uiCulture) + ); + + return Task.CompletedTask; + }); + } + else + { + logger.LogWarning($"Invalid culture or ui-culture parameter in the OpenIdConnect response. culture: {culture}, ui-culture: {uiCulture}"); } }; diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs index 23f41900b5..1b8fb5d39c 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs @@ -5,6 +5,7 @@ using OpenIddict.Server; using Volo.Abp.AspNetCore.MultiTenancy; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; using Volo.Abp.Modularity; +using Volo.Abp.OpenIddict.Globalization; using Volo.Abp.OpenIddict.Scopes; using Volo.Abp.OpenIddict.WildcardDomains; using Volo.Abp.Security.Claims; @@ -135,6 +136,7 @@ public class AbpOpenIddictAspNetCoreModule : AbpModule builder.AddEventHandler(RemoveClaimsFromClientCredentialsGrantType.Descriptor); builder.AddEventHandler(AttachScopes.Descriptor); + builder.AddEventHandler(AttachCultureInfo.Descriptor); services.ExecutePreConfiguredActions(builder); }); diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictOptions.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictOptions.cs index 475c13e447..84149e9b0b 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictOptions.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictOptions.cs @@ -15,4 +15,9 @@ public class AbpOpenIddictAspNetCoreOptions /// Default: true. /// public bool AddDevelopmentEncryptionAndSigningCertificate { get; set; } = true; + + /// + /// Attach auth server current culture info to response. + /// + public bool AttachCultureInfo { get; set; } = true; } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Globalization/AttachCultureInfo.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Globalization/AttachCultureInfo.cs new file mode 100644 index 0000000000..5bc093244d --- /dev/null +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Globalization/AttachCultureInfo.cs @@ -0,0 +1,43 @@ +using System.Globalization; +using System.Threading.Tasks; +using Microsoft.Extensions.Options; +using OpenIddict.Server; + +namespace Volo.Abp.OpenIddict.Globalization; + +public class AttachCultureInfo : IOpenIddictServerHandler +{ + public static OpenIddictServerHandlerDescriptor Descriptor { get; } + = OpenIddictServerHandlerDescriptor.CreateBuilder() + .UseSingletonHandler() + .SetOrder(OpenIddictServerHandlers.Authentication.AttachIssuer.Descriptor.Order + 1_000) + .SetType(OpenIddictServerHandlerType.Custom) + .Build(); + + protected IOptions Options { get; } + + public AttachCultureInfo(IOptions options) + { + Options = options; + } + + public ValueTask HandleAsync(OpenIddictServerEvents.ApplyAuthorizationResponseContext context) + { + Check.NotNull(context, nameof(context)); + + if (Options.Value.AttachCultureInfo) + { + if (!context.Response.HasParameter("culture")) + { + context.Response.SetParameter("culture", CultureInfo.CurrentCulture.Name); + } + + if (!context.Response.HasParameter("ui-culture")) + { + context.Response.SetParameter("ui-culture", CultureInfo.CurrentUICulture.Name); + } + } + + return default; + } +}