How do I make and use JWT role based authentication? - asp.net

I follow the tutorial link below.
https://fullstackmark.com/post/13/jwt-authentication-with-aspnet-core-2-web-api-angular-5-net-core-identity-and-facebook-login
I am trying to understand how it works and I want to use role-based authentication using this token. so I made another policy in the Startup.cs file as below.
And I tried to use it like [Authorize(Policy = "admin")] or [Authorize(Policy = "ApiUser")]in the controller but every time I try I get unauthenticated using postman.
What am I missing? how to make roles-based authentication based on the tutorial?
Startup
services.AddAuthorization(options =>
{
options.AddPolicy("ApiUser", policy => policy.RequireClaim(Constants.Strings.JwtClaimIdentifiers.Rol, Constants.Strings.JwtClaims.ApiAccess));
});
services.AddAuthorization(options =>
options.AddPolicy("admin", policy => policy.RequireRole("admin"))
);
Auth Controller
// POST api/auth/login
[HttpPost("login")]
public async Task<IActionResult> Post([FromBody]CredentialsViewModel credentials)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var identity = await GetClaimsIdentity(credentials.UserName, credentials.Password);
if (identity == null)
{
//return null;
return BadRequest(Error.AddErrorToModelState("login_failure", "Invalid username or password.", ModelState));
}
var id = identity.Claims.Single(c => c.Type == "id").Value;
var user = await _userManager.FindByIdAsync(id);
IList<string> role = await _userManager.GetRolesAsync(user);
var jwt = await Tokens.GenerateJwt(identity, role[0], _jwtFactory, credentials.UserName, _jwtOptions, new JsonSerializerSettings { Formatting = Formatting.Indented });
return new OkObjectResult(jwt);
}
I tried with all method and none of them working
[Authorize(Policy = "ApiUser")]
[HttpGet("getPolicy")]
public string GetPolicy()
{
return "policyWorking";
}
[Authorize(Roles = "admin")]
[HttpGet("getAdmin")]
public string GetAdmin()
{
return "adminWorking";
}
[Authorize ]
[HttpGet("getAuthorize")]
public string GetAuthorize()
{
return "normal authorize Working";
}

Firstly,be sure you have add json string in your appsettings.json otherwise you would always get 401 unauthorized:
"JwtIssuerOptions": {
"Issuer": "webApi",
"Audience": "http://localhost:5000/"
}
What am I missing? how to make roles-based authentication based on the tutorial?
1.If you want to use the following way to register the service:
services.AddAuthorization(options =>
options.AddPolicy("admin", policy => policy.RequireRole("admin"))
);
The authorize attribute should be like below:
[Authorize(Policy = "admin")]
2.If you want to use the following way:
[Authorize(Roles = "admin")]
You need to remove the service from Startup.cs:
//services.AddAuthorization(options =>
// options.AddPolicy("admin", policy => policy.RequireRole("admin"))
//);
Then,don't forget to add claim with role in JwtFactory.GenerateEncodedToken like below:
public async Task<string> GenerateEncodedToken(string userName, ClaimsIdentity identity)
{
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, userName),
new Claim(JwtRegisteredClaimNames.Jti, await _jwtOptions.JtiGenerator()),
new Claim(JwtRegisteredClaimNames.Iat, ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(), ClaimValueTypes.Integer64),
identity.FindFirst(Helpers.Constants.Strings.JwtClaimIdentifiers.Rol),
identity.FindFirst(Helpers.Constants.Strings.JwtClaimIdentifiers.Id),
new Claim(ClaimTypes.Role,"admin")
};
//...
}

I've made mine using this tutorial.
It also works with .Net Core 3.1.
#Update
I'm using policies for that:
services.AddAuthorization(options => {
options.AddPolicy(Policies.RequireAny, policy =>
policy.RequireClaim(JwtClaimTypes.Role, Enum.GetNames(typeof(AvailableRoles))));
options.AddPolicy(Policies.RequireAdmin, policy =>
policy.RequireClaim(JwtClaimTypes.Role,
AvailableRoles.Admin.ToString()));
});
And in Controller
[HttpDelete("{id:int:min(1)}")]
[Authorize(Policy = Policies.RequireAdmin)]
public async Task<IActionResult> Delete(int id) {
// CODE
return Ok();
}
and in creating JWT Token:
// Other claims and code...
claims.Add(new Claim(JwtClaimTypes.Role, roles[0]))
var token = new JwtSecurityToken(
issuer:_appSettings.AppUrl,
audience:_appSettings.AppUrl,
claims: claims,
expires: expires,
signingCredentials: credentials
);
return new JwtSecurityTokenHandler().WriteToken(token);

Related

Cannot access HttpContextAccessor User Claims on OnActionExecuting

I'm using .net core with JWT for authentication. And I'm trying to access user claims from HttpContextAccessor in my custom attribute. From within the app, I have a UserService.cs (code below) where I can do this. But on OnActionExecuting in my custom attribute, the claims come as an empty error. Even if I call the function from my user service, the claims aren't there.
My ultimate objective is to get the user's id to check if the user has admin access. I don't wanna store the admin access status on the token.
UserService.cs
public AuthenticatedUserClaims AuthenticatedUser()
{
var userClaims = new AuthenticatedUserClaims();
var claims = _contextAccessor.HttpContext.User.Claims;
var enumerable = claims as Claim[] ?? claims.ToArray();
var userId = enumerable.SingleOrDefault(x => x.Type == "UserId")?.Value;
userClaims.UserName = enumerable.SingleOrDefault(x => x.Type == "UserName")?.Value;
userClaims.FullName = enumerable.SingleOrDefault(x => x.Type == "FullName")?.Value;
if (userId != null && !string.IsNullOrEmpty(userId)) userClaims.UserId = int.Parse(userId);
return userClaims;
}
My Custom Attribute
[AttributeUsage(AttributeTargets.Class| AttributeTargets.Method)]
public class PermissionsRequiredAttribute: ActionFilterAttribute
{
private readonly IHttpContextAccessor _contextAccessor;
public PermissionsRequiredAttribute(IHttpContextAccessor contextAccessor)
{
_contextAccessor = contextAccessor;
}
public override void OnActionExecuting(ActionExecutingContext context)
{
var claims = _contextAccessor.HttpContext.User.Claims;
var claimsList = claims as Claim[] ?? claims.ToArray();
// claimsList = Claims[0]??
// context.Result = new UnauthorizedResult();
base.OnActionExecuting(context);
}
}
Attribute Usage
[HttpGet("{id}")]
[ServiceFilter(typeof(PermissionsRequiredAttribute))]
public async Task<ActionResult<Beneficiary>> GetBeneficiary([FromRoute] int id) { //... }
ConfigureServices on Startup.cs
services.AddTransient<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<PermissionsRequiredAttribute>();
Thanks in advance :)
I found a "hackaround" based on this answer, but I still don't know why my user HttpContext is empty.
[AttributeUsage(AttributeTargets.Class| AttributeTargets.Method)]
public class PermissionsRequiredAttribute: ActionFilterAttribute
{
private readonly IUser _user;
public PermissionsRequiredAttribute(IUser user)
{
_user = user;
}
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
bool headers = context.HttpContext.Request.Headers.TryGetValue("Authorization", out var tokens);
string token = tokens.FirstOrDefault()?.Split(" ")[1];
if (string.IsNullOrEmpty(token))
context.Result = new UnauthorizedResult();
var handler = new JwtSecurityTokenHandler();
JwtSecurityToken securityToken = (JwtSecurityToken) handler.ReadToken(token);
IEnumerable<Claim> claims = securityToken.Payload.Claims;
string userId = claims.SingleOrDefault(c => c.Type == "UserId")?.Value;
if (!string.IsNullOrEmpty(userId))
context.Result = new UnauthorizedResult();
var currentUser = await _user.GetUser(int.Parse(userId ?? throw new UnauthorizedAccessException()));
if (!currentUser.isAdmin)
context.Result = new UnauthorizedResult();
await base.OnActionExecutionAsync(context, next);
}
}
EDIT: 16-10-2021
I found a solution I'm happy with, it looks like I just needed to add the line in Startup.cs in ConfigureServices(IServiceCollection services)
services.AddHttpContextAccessor();
And now the line below has values Claims
var claims = _contextAccessor.HttpContext.User.Claims;

ASP.NET Core 2.0 Bearer Auth without Identity

I thought I had a pretty simple goal in mind when I set out a day ago to implement a self-contained bearer auth webapi on .NET core 2.0, but I have yet to get anything remotely working. Here's a list of what I'm trying to do:
Implement a bearer token protected webapi
Issue tokens & refresh tokens from an endpoint in the same project
Use the [Authorize] attribute to control access to api surface
Not use ASP.Net Identity (I have much lighter weight user/membership reqs)
I'm totally fine with building identity/claims/principal in login and adding that to request context, but I've not seen a single example on how to issue and consume auth/refresh tokens in a Core 2.0 webapi without Identity. I've seen the 1.x MSDN example of cookies without Identity, but that didn't get me far enough in understanding to meet the requirements above.
I feel like this might be a common scenario and it shouldn't be this hard (maybe it's not, maybe just lack of documentation/examples?). As far as I can tell, IdentityServer4 is not compatible with Core 2.0 Auth, opendiddict seems to require Identity. I also don't want to host the token endpoint in a separate process, but within the same webapi instance.
Can anyone point me to a concrete example, or at least give some guidance as to what best steps/options are?
Did an edit to make it compatible with ASP.NET Core 2.0.
Firstly, some Nuget packages:
Microsoft.AspNetCore.Authentication.JwtBearer
Microsoft.AspNetCore.Identity
System.IdentityModel.Tokens.Jwt
System.Security.Cryptography.Csp
Then some basic data transfer objects.
// Presumably you will have an equivalent user account class with a user name.
public class User
{
public string UserName { get; set; }
}
public class JsonWebToken
{
public string access_token { get; set; }
public string token_type { get; set; } = "bearer";
public int expires_in { get; set; }
public string refresh_token { get; set; }
}
Getting into the proper functionality, you'll need a login/token web method to actually send the authorization token to the user.
[Route("api/token")]
public class TokenController : Controller
{
private ITokenProvider _tokenProvider;
public TokenController(ITokenProvider tokenProvider) // We'll create this later, don't worry.
{
_tokenProvider = tokenProvider;
}
public JsonWebToken Get([FromQuery] string grant_type, [FromQuery] string username, [FromQuery] string password, [FromQuery] string refresh_token)
{
// Authenticate depending on the grant type.
User user = grant_type == "refresh_token" ? GetUserByToken(refresh_token) : GetUserByCredentials(username, password);
if (user == null)
throw new UnauthorizedAccessException("No!");
int ageInMinutes = 20; // However long you want...
DateTime expiry = DateTime.UtcNow.AddMinutes(ageInMinutes);
var token = new JsonWebToken {
access_token = _tokenProvider.CreateToken(user, expiry),
expires_in = ageInMinutes * 60
};
if (grant_type != "refresh_token")
token.refresh_token = GenerateRefreshToken(user);
return token;
}
private User GetUserByToken(string refreshToken)
{
// TODO: Check token against your database.
if (refreshToken == "test")
return new User { UserName = "test" };
return null;
}
private User GetUserByCredentials(string username, string password)
{
// TODO: Check username/password against your database.
if (username == password)
return new User { UserName = username };
return null;
}
private string GenerateRefreshToken(User user)
{
// TODO: Create and persist a refresh token.
return "test";
}
}
You probably noticed the token creation is still just "magic" passed through by some imaginary ITokenProvider. Define the token provider interface.
public interface ITokenProvider
{
string CreateToken(User user, DateTime expiry);
// TokenValidationParameters is from Microsoft.IdentityModel.Tokens
TokenValidationParameters GetValidationParameters();
}
I implemented the token creation with an RSA security key on a JWT. So...
public class RsaJwtTokenProvider : ITokenProvider
{
private RsaSecurityKey _key;
private string _algorithm;
private string _issuer;
private string _audience;
public RsaJwtTokenProvider(string issuer, string audience, string keyName)
{
var parameters = new CspParameters { KeyContainerName = keyName };
var provider = new RSACryptoServiceProvider(2048, parameters);
_key = new RsaSecurityKey(provider);
_algorithm = SecurityAlgorithms.RsaSha256Signature;
_issuer = issuer;
_audience = audience;
}
public string CreateToken(User user, DateTime expiry)
{
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
ClaimsIdentity identity = new ClaimsIdentity(new GenericIdentity(user.UserName, "jwt"));
// TODO: Add whatever claims the user may have...
SecurityToken token = tokenHandler.CreateJwtSecurityToken(new SecurityTokenDescriptor
{
Audience = _audience,
Issuer = _issuer,
SigningCredentials = new SigningCredentials(_key, _algorithm),
Expires = expiry.ToUniversalTime(),
Subject = identity
});
return tokenHandler.WriteToken(token);
}
public TokenValidationParameters GetValidationParameters()
{
return new TokenValidationParameters
{
IssuerSigningKey = _key,
ValidAudience = _audience,
ValidIssuer = _issuer,
ValidateLifetime = true,
ClockSkew = TimeSpan.FromSeconds(0) // Identity and resource servers are the same.
};
}
}
So you're now generating tokens. Time to actually validate them and wire it up. Go to your Startup.cs.
In ConfigureServices()
var tokenProvider = new RsaJwtTokenProvider("issuer", "audience", "mykeyname");
services.AddSingleton<ITokenProvider>(tokenProvider);
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options => {
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = tokenProvider.GetValidationParameters();
});
// This is for the [Authorize] attributes.
services.AddAuthorization(auth => {
auth.DefaultPolicy = new AuthorizationPolicyBuilder()
.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
.RequireAuthenticatedUser()
.Build();
});
Then Configure()
public void Configure(IApplicationBuilder app)
{
app.UseAuthentication();
// Whatever else you're putting in here...
app.UseMvc();
}
That should be about all you need. Hopefully I haven't missed anything.
The happy result is...
[Authorize] // Yay!
[Route("api/values")]
public class ValuesController : Controller
{
// ...
}
Following on #Mitch answer: Auth stack changed quite a bit moving to .NET Core 2.0. Answer below is just using the new implementation.
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
namespace JwtWithoutIdentity
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(cfg =>
{
cfg.RequireHttpsMetadata = false;
cfg.SaveToken = true;
cfg.TokenValidationParameters = new TokenValidationParameters()
{
ValidIssuer = "me",
ValidAudience = "you",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("rlyaKithdrYVl6Z80ODU350md")) //Secret
};
});
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UseMvc();
}
}
}
Token Controller
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using JwtWithoutIdentity.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
namespace JwtWithoutIdentity.Controllers
{
public class TokenController : Controller
{
[AllowAnonymous]
[Route("api/token")]
[HttpPost]
public async Task<IActionResult> Token(LoginViewModel model)
{
if (!ModelState.IsValid) return BadRequest("Token failed to generate");
var user = (model.Password == "password" && model.Username == "username");
if (!user) return Unauthorized();
//Add Claims
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.UniqueName, "data"),
new Claim(JwtRegisteredClaimNames.Sub, "data"),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("rlyaKithdrYVl6Z80ODU350md")); //Secret
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken("me",
"you",
claims,
expires: DateTime.Now.AddMinutes(30),
signingCredentials: creds);
return Ok(new JsonWebToken()
{
access_token = new JwtSecurityTokenHandler().WriteToken(token),
expires_in = 600000,
token_type = "bearer"
});
}
}
}
Values Controller
using System.Collections.Generic;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace JwtWithoutIdentity.Controllers
{
[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET api/values
[Authorize]
[HttpGet]
public IEnumerable<string> Get()
{
var name = User.Identity.Name;
var claims = User.Claims;
return new string[] { "value1", "value2" };
}
}
}
Hope this helps!

Angular2 calling facebook login api from asp.net core application

In my ASP.NET Core application I have made facebook login, which works fine. In my Controller there are two methods to make that facebook login
public IActionResult ExternalLogin(string provider, string returnUrl)
public async Task<IActionResult> ExternalLoginCallback(string returnUrl, string remoteError = null)
ExternalLogin makes the request to facebook and opens the approval page. When I click Continue in that approval page ExternalLoginCallback is called.
Now the problem is that I made api calls to these two actions and I am using them in my Angular2 application.
So when I click facebook login button in angular2 app my ExternalLogin action is called and it returns success response, because facebook approval page is opened, but now I can't get ant response from ExternalLoginCallback, which is called automatically. How could I get the wanted response in my facebookLogin method???
[HttpPost]
[AllowAnonymous]
public IActionResult ExternalLogin(string provider, string returnUrl)
{
// Request a redirect to the external login provider.
var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "User", new { ReturnUrl = returnUrl });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return Challenge(properties, provider);
}
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl, string remoteError = null)
{
var info = await _signInManager.GetExternalLoginInfoAsync();
if (!string.IsNullOrEmpty(remoteError))
{
return new StatusCodeResult(401);
}
if (info == null)
{
return new StatusCodeResult(401);
}
// Sign in the user with this external login provider if the user already has a login.
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, false, true);
if (result.Succeeded)
{
return new StatusCodeResult(200);
}
//Register with facebook
var email = info.Principal.FindFirstValue(ClaimTypes.Email);
if (string.IsNullOrEmpty(email))
{
return new StatusCodeResult(401);
}
var user = new User
{
UserName = email,
Email = email
};
var createResult = await _userManager.CreateAsync(user);
if (createResult.Succeeded)
{
createResult = await _userManager.AddLoginAsync(_userManager.Users.First(m => m.Email == user.Email), info);
if (createResult.Succeeded)
{
await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, false, true);
return new StatusCodeResult(200);
}
}
return new StatusCodeResult(401);
}
This is my typescript method of subscribing the api call:
facebookLogin(provider: string, returnUrl: string) {
this.productService.externalLogin(provider, returnUrl).subscribe(x => {
console.log(x);
},
error => {
});
}
And this is my api call:
public externalLogin(provider: string, returnUrl: string) {
var url = 'http://mywebsite.com/api/User/ExternalLogin?Provider=Facebook&ReturnUrl=%2F';
return this.http.post(url, `Provider=${provider}&ReturnUrl=${returnUrl}`);
}

OAuth bearer token validation by Authorize Attribute

I'm stuck with OAuth token authorization. I have configured OAuth and I have my own OAuth server provider.
Configuration code:
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AuthorizeEndpointPath = new PathString("/authorize"),
AccessTokenExpireTimeSpan = TimeSpan.FromHours(1),
Provider = new SimpleAuthorizationServerProvider()
};
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
Server provider:
public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
using (AuthRepository _repo = new AuthRepository())
{
IdentityUser user = await _repo.FindUser(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
}
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim("sub", context.UserName));
identity.AddClaim(new Claim("role", "user"));
context.Validated(identity);
}
}
When I'm sending: grand_type=password, username=MyUserName, password=MyPassword to the OAuth token endpoint "localhost/token", it's nicely creating my OAuth bearer token. But from here, I have no idea how to use this generated token, where it is stored (how to get it), and how to make a success validation using [Authorize] attribute on ASP.NET MVC controller. I just simply want to use my generated token, when I'm going from one view to another, that has [Authorize] attribute, and pass through it successfully. How can I achive this ?
Add new overriden function in "SimpleAuthorizationServerProvider" class.
public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
{
context.AdditionalResponseParameters.Add(property.Key, property.Value);
}
return Task.FromResult<object>(null);
}
Then you can get token in json object.
Implement the following workflow :
Retrieve an access token via password grant-type
Get user information by passing this access token. Link : http://openid.net/specs/openid-connect-core-1_0.html#UserInfo
Store the claims into the cookie

Identity Authorize Attribute Roles with Web API

I have a small Web API application that uses Identity to manage users using Owin Bearer Tokens. The basics of this implementation work fine: I can register a user, login a user and access Web API end points that are marked with [Authorize].
My next step is to limit Web API endpoints using roles. For example, a controller that only users in the Admin role can access. I've created the Admin user as below and I add them to the Admin role. However when I update my existing controllers from [Authorize] to [Authorize(Roles = "Admin")] and try to access it using the Adim account, I get a 401 Unauthorized.
//Seed on Startup
public static void Seed()
{
var user = await userManager.FindAsync("Admin", "123456");
if (user == null)
{
IdentityUser user = new IdentityUser { UserName = "Admin" };
var createResult = await userManager.CreateAsync(user, "123456");
if (!roleManager.RoleExists("Admin"))
var createRoleResult = roleManager.Create(new IdentityRole("Admin"));
user = await userManager.FindAsync("Admin", "123456");
var addRoleResult = await userManager.AddToRoleAsync(user.Id, "Admin");
}
}
//Works
[Authorize]
public class TestController : ApiController
{
// GET api/<controller>
public bool Get()
{
return true;
}
}
//Doesn't work
[Authorize(Roles = "Admin")]
public class TestController : ApiController
{
// GET api/<controller>
public bool Get()
{
return true;
}
}
Q: What is the correct way to set up and use roles?
How do you set the claims for the users when they login I believe you are missing this line of code in method GrantResourceOwnerCredentials
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
identity.AddClaim(new Claim(ClaimTypes.Role, "Admin"));
identity.AddClaim(new Claim(ClaimTypes.Role, "Supervisor"));
And if you want to create the identity from DB use the below:
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
// Add custom user claims here
return userIdentity;
}
Then in GrantResourceOwnerCredentials do the below:
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, OAuthDefaults.AuthenticationType);

Resources