weeksdev
weeksdev

Reputation: 4355

Custom `AuthenticationStateProvider` Authentication Failing

I have created a custom ApiAuthenticationStateProvider that after returning an AuthenticationState is still stating

info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      Authorization failed.

Here is a simplified version of my ApiAuthenticationStateProvider that is failing:

public class ApiAuthenticationStateProvider : AuthenticationStateProvider
{
   public override Task<AuthenticationState> GetAuthenticationStateAsync()
   {
       Console.WriteLine("Getting auth state...");
               
       var claims = new[] { new Claim(ClaimTypes.Name, "[email protected]") };
       var authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(claims));
       var authState = Task.FromResult(new AuthenticationState(authenticatedUser));

       return Task.FromResult(authState);
   }
}

I can tell from the Console.WriteLine that is using my custom provider but to provide full details, here is the code i used to add that in Program.cs:

builder.Services.AddScoped<AuthenticationStateProvider, ApiAuthenticationStateProvider>();

Upvotes: 3

Views: 1884

Answers (3)

Umair
Umair

Reputation: 5471

For this to work on Blazor you will have to add authenticationType parameter value with ClaimsIdentity so your code will be changed to:

public class ApiAuthenticationStateProvider : AuthenticationStateProvider
{
   public override Task<AuthenticationState> GetAuthenticationStateAsync()
   {
       Console.WriteLine("Getting auth state...");
               
       var claims = new[] { new Claim(ClaimTypes.Name, "[email protected]") };
       var authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(claims, AuthenticationTypes.Password));
       var authState = Task.FromResult(new AuthenticationState(authenticatedUser));

       return Task.FromResult(authState);
   }
}

Notice the AuthenticationTypes.Password parameter for ClaimsIdentity.

This should be same in all places where ClaimsIdentity is constructed.

Update: As per this comment, the value of authentication type should be one of the values defined in AuthenticationTypes class. Updated the above code to use this class instead of a random auth type name.

Upvotes: 2

kltft
kltft

Reputation: 3793

https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsidentity.-ctor?view=netcore-3.1

your ClaimsIdentity() object instantiated with just the array of claims you create above appears correct in the documenation but providing a string of claim type (also in the documenation above) seems to actually be what is required

var authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(claims, "Needs Auth Type Here"));

Upvotes: 1

Niederee
Niederee

Reputation: 4295

The issue can be resolved in this answer. https://stackoverflow.com/a/20254797/2682662

Basically when constructing the ClaimsIdentity you need to provide a string value for the authentication type.

var authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(claims, "Needs Auth Type Here"));

Upvotes: 3

Related Questions