问题
I am trying to work with Jwt auth and Identity in ASP Net Core 2.1
In my Startup.cs I have:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = AuthOptions.ISSUER,
ValidateAudience = true,
ValidAudience = AuthOptions.AUDIENCE,
ValidateLifetime = true,
IssuerSigningKey = AuthOptions.GetSymmetricSecurityKey(),
ValidateIssuerSigningKey = true,
};
});
var builder = services.AddIdentityCore<User>(options =>
{
// Password settings
...
// Lockout settings
...
// User settings
options.User.RequireUniqueEmail = true;
}).AddEntityFrameworkStores<ApplicationDbContext>();
builder = new IdentityBuilder(builder.UserType, typeof(IdentityRole), builder.Services);
Then in SecurityService.cs I am trying to get roles by using this statement
var roles = await _userManager.GetRolesAsync(user);
And its throwing the following exception:
NotSupportedException: Store does not implement IUserRoleStore
Microsoft.AspNetCore.Identity.UserManager.GetUserRoleStore()
I found it because of AddIdentityCore: If I use
AddIdentity<User, IdentityRole> instead it works, but then [Authorize] doesn't work
Does anybody faced similar situation, or why it can happen?
回答1:
When you use AddIdentity<TUser, TRole>, that call configures the default authentication scheme, like so (source):
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
In your Startup.ConfigureServices, you have the following, which also sets the default authentication scheme:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
Because of the order this is defined (AddIdentity is after AddAuthentication), the default is changing from Jwt to Identity, so that when you use [Authorize], the authentication process is now expecting to use Identity rather than Jwt.
To resolve this, the simplest option is to switch the order of AddIdentity and AddAuthentication, so the JwtBearer call comes last and therefore "wins". You'll also need to be more explicit and set both DefaultAuthenticateScheme and DefaultChallengeScheme:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(...);
Another option is to be explicit in the [Authorize] attribute, calling out which authentication scheme you want to use, like either of the following two lines:
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[Authorize(AuthenticationSchemes = IdentityConstants.ApplicationScheme)]
It seems the first option would be most appropriate for your use-case, but it's good to know that this second option exists should you need it as you go further with Identity (there are more - e.g. using policies).
来源:https://stackoverflow.com/questions/52206742/asp-core-2-1-jwt-identity-usermanager-store-does-not-implement-iuserrolestore