Reputation: 733
I implemented a token authorization system on ASP.NET Web API with OWIN middleware. I successfully can authenticate with a REST client and obtain an authorization token to call the API. If I put the [Authorize]
attribute on a GET action in my controller it also works correctly. If I don't have a valid token it denies the resource with a 401 message, but if I use [Authorize(Roles="admins")]
with the roles
parameter, it doesn't recognize the user's roles. I verified things in the database and checked that usersinroles
is correctly filled.
This is a code snippet:
[Authorize(Roles = "admins")]
public IEnumerable<CompanyModel> Get()
{
ClaimsPrincipal principal = Request.GetRequestContext().Principal as ClaimsPrincipal;
bool isrole = principal.IsInRole("admins");
I also checked the action without the roles
parameter and the isrole
boolean is always false
. Do I have to enable something?
Upvotes: 23
Views: 27898
Reputation: 4763
You must add in GrantResourceOwnerCredentials method:
identity.AddClaim(new Claim(ClaimTypes.Role, "admins"));
Step by step
In StartUp.cs class, you should have a custom provider, like the line
Provider = new CustomAuthorizationServerProvider()
for example:
public void ConfigureOAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions oAuthServerOptions = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
Provider = new CustomAuthorizationServerProvider()
};
// Token Generation
app.UseOAuthAuthorizationServer(oAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
Then, your CustomAuthorizationServerProvider that inherits from OAuthAuthorizationServerProvider class will override GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context).
Then, after checking that the user has correct UserName and Password, you must add
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
...
// other claims
...
identity.AddClaim(new Claim(ClaimTypes.Role, "admins"));
...
var ticket = new AuthenticationTicket(identity, properties);
context.Validated(ticket);
Edited
You can get user roles from DB instead of using the "admins" harcoded string doing:
var roles = await userManager.GetRolesAsync(userId);
So you can add the following method in your repository:
public async Task<IList<string>> UserRoles(string userId)
{
IList<string> roles = await userManager.GetRolesAsync(userId);
return roles;
}
And then call it from your overrided GrantResourceOwnerCredentials adding:
using (AuthRepository repository = new AuthRepository())
{
IdentityUser user = await repository.FindUser(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect");
return;
}
var roles = repository.UserRoles(user.Id);
}
Upvotes: 48