Search code examples
asp.net-coreasp.net-core-identityasp.net-core-localization

CustomRequestCultureProvider: context.User.Identity.IsAuthenticated is always false


I'm trying to implement a CustomRequestCultureProvider in my localization pipeline, to retrieve the user culture from the database. To identify the user, I need the ClaimsPrincipal, but for some reason, even though the user is authenticated, context.User.Identity.IsAuthenticated is always false.

Here's the relevant code (truncated to highlight my issue: authentication is already working; localization code is based on the localization tutorial).

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<RequestLocalizationOptions>(options =>
        {
            var supportedCultures = new[]
            {
                new CultureInfo("fr"),
                new CultureInfo("en"),
            };

            options.DefaultRequestCulture = new RequestCulture("fr");
            options.SupportedCultures = supportedCultures;
            options.SupportedUICultures = supportedCultures;

            // we insert at 2, because we want to first check the query, then the cookie, then the DB, then the headers
            options.RequestCultureProviders.Insert(2, new CustomRequestCultureProvider(async context =>
            {
                // ----->> ISSUE IS HERE: this is always false!
                if (context.User.Identity.IsAuthenticated)
                    return new ProviderCultureResult("en");

                return null;
            }));
        });

        services
            .AddLocalization(options => options.ResourcesPath = "Resources")
            .AddMvc()
            .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
            ;

        return services;
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        app.UseRequestLocalization();
        app.UseStaticFiles();
        app.UseAuthentication();
        app.UseMvcWithDefaultRoute();
        return app;
    }
}

What should I do to retrieve the ClaimsPrincipal in my CustomRequestCultureProvider?

Note: changing the registration order (calling app.UseAuthentification before app.UseRequestLocalization doesn't fix the issue).


Solution

  • I managed to make it work by manually calling the authentication pipeline. I suspect I need to do that because the Authorize attribute is triggered later in the middleware pipeline, and thus it's too early to retrieve the ClaimsPrincipal (I might be wrong).

    In any case, here's how I modified my CustomRequestCultureProvider:

    // we insert at 2, because we want to first check the query, then the cookie, then the DB, then the headers
    options.RequestCultureProviders.Insert(2, new CustomRequestCultureProvider(async context =>
    {
        // retrieve the ClaimsPrincipal from the cookies
        // note: this is dependent on how your authentication is set up
        var authResult = await context.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
        if (!authResult.Succeeded)
            return null;
    
        var user = authResult.Principal;
        if (user != null)
            return new ProviderCultureResult("en");
    
        return null;
    }));