3

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>();

3 Answers 3

3

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"));
Sign up to request clarification or add additional context in comments.

1 Comment

this answer appears to be most correct and links to an explanation of why the string 'auth type' is needed.
2

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.

Comments

1

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"));

Comments

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.