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?
OWIN (Open Web Interface for . NET) is a standard for an interface between . NET Web applications and Web servers. It is a community-owned open-source project. The OAuth authorization framework enables a third-party application to obtain limited access to a HTTP service.
Each group has a set of permissions. For role-based authorization, the customer is responsible for providing the user ID, any optional attributes, and all mandatory user attributes necessary to define the user to Payment Feature Services. The customer must also define the roles that are assigned to the user.
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); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With