1

Having upgraded from 3.1 to 5.0, I cannot seem to get past this HttpRequestException error when trying to fetch data from protected api controllers (those not marked [Authorize] are fine).

Although the client app tells me I am authenticated (I have 'hello, [email protected]' up top right for example), I can't seem to be get authenticated with the server. User.Identity just looks like this for example:

enter image description here

I have a few typed HttpClients, the authenticating one looking like so

    public class ApplicationClient
    {
        private readonly HttpClient _httpClient;

        public ApplicationClient(HttpClient httpClient)
        {
            _httpClient = httpClient;
        }

        public async Task<Applicant> GetApplicant() => await _httpClient.GetFromJsonAsync<Applicant>("applicant");
}}

With ApplicationClient being register in Programme.cs on client side as:

public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            builder.RootComponents.Add<App>("app");

            builder.Services.AddHttpClient<ApplicationClient>(client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
                .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
            
            // Supply HttpClient instances that include access tokens when making requests to the server project
            builder.Services.AddTransient(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("Jcc.ServerAPI"));
            builder.Services.AddScoped<ApplicationState>();
            builder.Services.AddBlazoredModal();
            builder.Services.AddApiAuthorization();

            await builder.Build().RunAsync();
        }

And finally a controller,

[Route("[controller]")]
    [ApiController]
    [Authorize]
    public class MyController
    {
        public MyController(...) : base(...)
        {
            ...
        }

        [HttpGet]
        public async Task<ActionResult<Applicant>> GetCurrentApplicant()
        {
            ...
        }

In Startup.cs on Server app (having chopped and changed and tried about every combination of the below plus others) the pertinent bits of ConfigureServices() are:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<JccContext>(options =>
                options.UseNpgsql(
                    Configuration.GetConnectionString("DbContext")));

            services.AddDefaultIdentity<ApplicationUser>(options =>
                {
                    options.SignIn.RequireConfirmedAccount = true;
                    options.User.RequireUniqueEmail = true;
                })
                .AddEntityFrameworkStores<DbContext>();

            services.AddIdentityServer()
            .AddApiAuthorization<ApplicationUser, DbContext>();

            services.AddAuthentication()
                    .AddIdentityServerJwt();

            services.Configure<IdentityOptions>(options =>
                options.ClaimsIdentity.UserIdClaimType = ClaimTypes.NameIdentifier);

            services.Configure<ForwardedHeadersOptions>(options =>
            {
                options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
                                           ForwardedHeaders.XForwardedProto |
                                           ForwardedHeaders.XForwardedHost;
                options.KnownNetworks.Clear();
                options.KnownProxies.Clear();
            });
        

while Configure() goes:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseForwardedHeaders();


            app.UseHttpsRedirection();
            app.UseRouting();

            app.UseIdentityServer();
            app.UseAuthentication();
            app.UseAuthorization();


            app.UseStaticFiles();
            app.UseBlazorFrameworkFiles();


            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
                endpoints.MapDefaultControllerRoute();
                endpoints.MapControllers();
                endpoints.MapFallbackToFile("index.html");
            });
        }

I just don't what's changed since it worked previously. Identity Server seems to generate the token fine:

enter image description here

but I keep seeing this:

enter image description here

enter image description here

It would be nice to not have to revert back to 3.1 :)

I did try

services.AddIdentityServer(opt =>
                        opt.IssuerUri = "https://localhost:5001"
                        )

As per a post a few years back but no dice and I think it was a different issue.

1 Answer 1

1

If you regenerate the signing keys, then the keys in tokens already issued will be invalidated. For production you need to make sure the signing keys is persisted.

you can look at the kid claim in the JWT header of your tokens. It must be found in the /.well-known/openid-configuration/jwks.

Be aware that API's and clients cache the downloaded keys for 24 hours by default.

In production you need to use this method to add the signing key that you want to sign your tokens with

AddSigningCredential

See the documentation here

In production you should not use this method AddDeveloperSigningCredential.

Sign up to request clarification or add additional context in comments.

9 Comments

Thank you, although what do you suggest I change? I've been wrestling with this for about a week so the 24 hours cache is probably not an issue :)
Ah, actually I do only use the developer signing credential in development, I just shortened the environment conditionals for the sake of brevity. It was actually in development that I was having the problem, although, bizarrely, removing the call to AddDeveloperSigningCredential() seems to have solved this for now. Did they change something?!
You should either use AddDeveloperSigningCredential or AddSigningCredential in development. Do you use version 4 or version 5? perhaps you regenerate the key each time you start locally?
In the output, 'Starting IdentityServer4 version 4.1.0'. Using dotnet 5.0. It kinda feels strange that it's working without AddDeveloperSigningCredential() but if it works, what the heck :P
not using AddDeveloperSigningCredential and not using AddSigningCredential sounds wierd, perhaps its added somewhere else? do you get a key in the JWKS endpoint?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.