I'm trying to implement Microsoft Active Directory External Auth for my Backoffice user in Umbraco version 10.2.0 following the documentations (https://our.umbraco.com/documentation/Reference/Security/Authenticate-with-Active-Directory/ and https://our.umbraco.com/documentation/Reference/Security/Auto-linking/) the implementation works when the user already exists and I did manual linking, however when when user doesn't exist the site becomes blank on redirect from authenticating and when I check console the following error occurred:
[07:29:43 ERR] An unhandled exception has occurred while executing the request. System.ArgumentNullException: Value cannot be null. (Parameter 'culture') at Umbraco.Cms.Core.Services.LocalizedTextService.GetAllStoredValues(CultureInfo culture) at Umbraco.Cms.Web.BackOffice.Controllers.BackOfficeController.LocalizedText(String culture) at lambda_method57(Closure , Object ) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Umbraco.Cms.Web.Common.Middleware.BasicAuthenticationMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<b__1>d.MoveNext() --- End of stack trace from previous location --- at Umbraco.Cms.Web.BackOffice.Middleware.BackOfficeExternalLoginProviderErrorMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<b__1>d.MoveNext() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at SixLabors.ImageSharp.Web.Middleware.ImageSharpMiddleware.Invoke(HttpContext httpContext, Boolean retry) at StackExchange.Profiling.MiniProfilerMiddleware.Invoke(HttpContext context) in C:\projects\dotnet\src\MiniProfiler.AspNetCore\MiniProfilerMiddleware.cs:line 121 at Umbraco.Cms.Web.Common.Middleware.UmbracoRequestMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) at Umbraco.Cms.Web.Common.Middleware.UmbracoRequestMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<b__1>d.MoveNext() --- End of stack trace from previous location --- at Umbraco.Cms.Web.Common.Middleware.PreviewAuthenticationMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<b__1>d.MoveNext() --- End of stack trace from previous location --- at Umbraco.Cms.Web.Common.Middleware.UmbracoRequestLoggingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<b__1>d.MoveNext() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
My implementation is as follows:
- OpenIdConnectBackOfficeExternalLoginProviderOptions.cs
  public class OpenIdConnectBackOfficeExternalLoginProviderOptions : IConfigureNamedOptions<BackOfficeExternalLoginProviderOptions>
    {
        public const string SchemeName = "OpenIdConnect";
        /// <summary>
        ///     Configures an instance of <see cref="OpenIdConnectBackOfficeExternalLoginProviderOptions"/> class
        /// </summary>
        /// <param name="name">
        ///     A <see cref="string"/> representing a name of the scheme
        /// </param>
        /// <param name="options">
        ///     A <see cref="BackOfficeExternalLoginProviderOptions"/> representing the options to configure
        /// </param>
        public void Configure(string name, BackOfficeExternalLoginProviderOptions options)
        {
            if (name != "Umbraco." + SchemeName)
            {
                return;
            }
            Configure(options);
        }
        /// <summary>
        ///     Configures an instance of <see cref="OpenIdConnectBackOfficeExternalLoginProviderOptions"/> class
        /// </summary>
        /// <param name="options">
        ///     A <see cref="BackOfficeExternalLoginProviderOptions"/> representing the options to configure
        /// </param>
        public void Configure(BackOfficeExternalLoginProviderOptions options)
        {
            options.ButtonStyle = "btn-danger";
            options.Icon = "fa fa-windows";
            options.AutoLinkOptions = new ExternalSignInAutoLinkOptions(
                autoLinkExternalAccount: true,
                defaultUserGroups: new[] { Constants.Security.EditorGroupAlias },
                defaultCulture: "en-US",
                allowManualLinking: false
            )
            {
                OnAutoLinking = (autoLinkUser, loginInfo) =>
                {
                    autoLinkUser.IsApproved = true;
                },
                OnExternalLogin = (user, loginInfo) =>
                {
                    return true;
                }
            };
            options.DenyLocalLogin = false;
            options.AutoRedirectLoginToExternalProvider = false;
        }  
- MicrosoftIdentityExtensions.cs
 public static class MicrosoftIdentityExtensions
    {
        /// <summary>
        ///     Adds Microsoft Authentication configuration <see cref="AddMicrosoftIdentity" />.
        /// </summary>
        /// <param name="builder">
        ///     Umbraco builder builds initializes services for umbraco
        /// </param>
        /// <param name="config">
        ///     Config has the options to configure Google Authentication
        /// </param>
        public static IUmbracoBuilder AddMicrosoftIdentity(this IUmbracoBuilder builder, IConfiguration config)
        {
            //TODO: to follow-up on the issue logged in Umbraco for Auto-Linking not working correctly: https://our.umbraco.com/forum/using-umbraco-and-getting-started//110241-value-cannot-be-null-parameter-culture-on-ms-aad-external-auth-auto-linking
            builder.Services.ConfigureOptions<OpenIdConnectBackOfficeExternalLoginProviderOptions>();
            builder.AddBackOfficeExternalLogins(logins =>
            {
                const string schema = MicrosoftAccountDefaults.AuthenticationScheme;
                logins.AddBackOfficeLogin(backOfficeAuthenticationBuilder =>
                {
                    backOfficeAuthenticationBuilder.AddMicrosoftAccount(backOfficeAuthenticationBuilder.SchemeForBackOffice(schema),
                        options =>
                        {
                            options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                            options.AuthorizationEndpoint = config.GetValue<string>("AuthProviders:AzureAD:auth_url");
                            options.TokenEndpoint = config.GetValue<string>("AuthProviders:AzureAD:token_uri");
                            options.ClientId = config.GetValue<string>("AuthProviders:AzureAD:client_id");
                            options.ClientSecret = config.GetValue<string>("AuthProviders:AzureAD:client_secret");
                            options.CallbackPath = config.GetValue<string>("AuthProviders:AzureAD:callback_path");
                            options.ClaimActions.MapJsonKey(ClaimTypes.Role, "role");
                            options.SaveTokens = true;
                            options.Scope.Add("openid");
                            options.Scope.Add("email");
                            options.Scope.Add("profile");
                            options.UsePkce = true;
                        });
                });
            });
            return builder;
        }
    }
 
    

