This is the forth part of Building Simple Membership system using ASP.NET Identity 2.1, ASP.NET Web API 2.2 and AngularJS. The topics we’ll cover are:
- Configure ASP.NET Identity with ASP.NET Web API (Accounts Management) – Part 1.
- ASP.NET Identity 2.1 Accounts Confirmation, and Password/User Policy Configuration – Part 2.
- Implement JSON Web Tokens Authentication in ASP.NET Web API and Identity 2.1 – Part 3.
- ASP.NET Identity 2.1 Roles Based Authorization with ASP.NET Web API – (This Post)
- ASP.NET Web API Claims Authorization with ASP.NET Identity 2.1 – Part 5.
- AngularJS Authentication and Authorization with ASP.NET Web API and Identity 2.1 – Part 6
The source code for this tutorial is available on GitHub.
ASP.NET Identity 2.1 Roles Based Authorization with ASP.NET Web API
In the previous post we saw how we can authenticate individual users using the [Authorize] attribute in a very basic form, but there is some limitation with the previous approach where any authenticated user can perform sensitive actions such as deleting any user in the system, getting list of all users in the system, etc… where those actions should be executed only by subset of users with higher privileges (Admins only).
In this post we’ll see how we can enhance the authorization mechanism to give finer grained control over how users can execute actions based on role membership, and how those roles will help us in differentiate between authenticated users.
The nice thing here that ASP.NET Identity 2.1 provides support for managing Roles (create, delete, update, assign users to a role, remove users from role, etc…) by using the RoleManager<T> class, so let’s get started by adding support for roles management in our Web API.
Step 1: Add the Role Manager Class
The Role Manager class will be responsible to manage instances of the Roles class, the class will derive from “RoleManager<T>” where T will represent our “IdentityRole” class, once it derives from the “IdentityRole” class a set of methods will be available, those methods will facilitate managing roles in our Identity system, some of the exposed methods we’ll use from the “RoleManager” during this tutorial are:
Method Name | Usage |
---|---|
FindByIdAsync(id) | Find role object based on its unique identifier |
Roles | Returns an enumeration of the roles in the system |
FindByNameAsync(Rolename) | Find roled based on its name |
CreateAsync(IdentityRole) | Creates a new role |
DeleteAsync(IdentityRole) | Delete role |
RoleExistsAsync(RoleName) | Returns true if role already exists |
Now to implement the “RoleManager” class, add new file named “ApplicationRoleManager” under folder “Infrastructure” and paste the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class ApplicationRoleManager : RoleManager<IdentityRole> { public ApplicationRoleManager(IRoleStore<IdentityRole, string> roleStore) : base(roleStore) { } public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context) { var appRoleManager = new ApplicationRoleManager(new RoleStore<IdentityRole>(context.Get<ApplicationDbContext>())); return appRoleManager; } } |
Notice how the “Create” method will use the Owin middleware to create instances for each request where
Identity data is accessed, this will help us to hide the details of how role data is stored throughout the
application.
Step 2: Assign the Role Manager Class to Owin Context
Now we want to add a single instance of the Role Manager class to each request using the Owin context, to do so open file “Startup” and paste the code below inside method “ConfigureOAuthTokenGeneration”:
1 2 3 4 5 6 7 8 9 10 |
private void ConfigureOAuthTokenGeneration(IAppBuilder app) { // Configure the db context and user manager to use a single instance per request //Rest of code is removed for brevity app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create); //Rest of code is removed for brevity } |
Now a single instance of class “ApplicationRoleManager” will be available for each request, we’ll use this instance in different controllers, so it is better to create a helper property in class “BaseApiController” which all other controllers inherits from, so open file “BaseApiController” and add the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class BaseApiController : ApiController { //Code removed from brevity private ApplicationRoleManager _AppRoleManager = null; protected ApplicationRoleManager AppRoleManager { get { return _AppRoleManager ?? Request.GetOwinContext().GetUserManager<ApplicationRoleManager>(); } } } |
Step 3: Add Roles Controller
Now we’ll add the controller which will be responsible to manage roles in the system (add new roles, delete existing ones, getting single role by id, etc…), but this controller should only be accessed by users in “Admin” role because it doesn’t make sense to allow any authenticated user to delete or create roles in the system, so we will see how we will use the [Authorize] attribute along with the Roles to control this.
Now add new file named “RolesController” under folder “Controllers” and paste the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
[Authorize(Roles="Admin")] [RoutePrefix("api/roles")] public class RolesController : BaseApiController { [Route("{id:guid}", Name = "GetRoleById")] public async Task<IHttpActionResult> GetRole(string Id) { var role = await this.AppRoleManager.FindByIdAsync(Id); if (role != null) { return Ok(TheModelFactory.Create(role)); } return NotFound(); } [Route("", Name = "GetAllRoles")] public IHttpActionResult GetAllRoles() { var roles = this.AppRoleManager.Roles; return Ok(roles); } [Route("create")] public async Task<IHttpActionResult> Create(CreateRoleBindingModel model) { if (!ModelState.IsValid) { return BadRequest(ModelState); } var role = new IdentityRole { Name = model.Name }; var result = await this.AppRoleManager.CreateAsync(role); if (!result.Succeeded) { return GetErrorResult(result); } Uri locationHeader = new Uri(Url.Link("GetRoleById", new { id = role.Id })); return Created(locationHeader, TheModelFactory.Create(role)); } [Route("{id:guid}")] public async Task<IHttpActionResult> DeleteRole(string Id) { var role = await this.AppRoleManager.FindByIdAsync(Id); if (role != null) { IdentityResult result = await this.AppRoleManager.DeleteAsync(role); if (!result.Succeeded) { return GetErrorResult(result); } return Ok(); } return NotFound(); } [Route("ManageUsersInRole")] public async Task<IHttpActionResult> ManageUsersInRole(UsersInRoleModel model) { var role = await this.AppRoleManager.FindByIdAsync(model.Id); if (role == null) { ModelState.AddModelError("", "Role does not exist"); return BadRequest(ModelState); } foreach (string user in model.EnrolledUsers) { var appUser = await this.AppUserManager.FindByIdAsync(user); if (appUser == null) { ModelState.AddModelError("", String.Format("User: {0} does not exists", user)); continue; } if (!this.AppUserManager.IsInRole(user, role.Name)) { IdentityResult result = await this.AppUserManager.AddToRoleAsync(user, role.Name); if (!result.Succeeded) { ModelState.AddModelError("", String.Format("User: {0} could not be added to role", user)); } } } foreach (string user in model.RemovedUsers) { var appUser = await this.AppUserManager.FindByIdAsync(user); if (appUser == null) { ModelState.AddModelError("", String.Format("User: {0} does not exists", user)); continue; } IdentityResult result = await this.AppUserManager.RemoveFromRoleAsync(user, role.Name); if (!result.Succeeded) { ModelState.AddModelError("", String.Format("User: {0} could not be removed from role", user)); } } if (!ModelState.IsValid) { return BadRequest(ModelState); } return Ok(); } } |
What we have implemented in this lengthy controller code is the following:
- We have attribute the controller with [Authorize(Roles=”Admin”)] which allows only authenticated users who belong to “Admin” role only to execute actions in this controller, the “Roles” property accepts comma separated values so you can add multiple roles if needed. In other words the user who will have an access to this controller should have valid JSON Web Token which contains claim of type “Role” and value of “Admin”.
- The method “GetRole(Id)” will return a single role based on it is identifier, this will happen when we call the method “FindByIdAsync”, this method returns object of type “RoleReturnModel” which we’ll create in the next step.
- The method “GetAllRoles()” returns all the roles defined in the system.
- The method “Create(CreateRoleBindingModel model)” will be responsible of creating new roles in the system, it will accept model of type “CreateRoleBindingModel” where we’ll create it the next step. This method will call “CreateAsync” and will return response of type “RoleReturnModel”.
- The method “DeleteRole(string Id)” will delete existing role by passing the unique id of the role then calling the method “DeleteAsync”.
- Lastly the method “ManageUsersInRole” is proprietary for the AngularJS app which we’ll build in the coming posts, this method will accept a request body containing an object of type “UsersInRoleModel” where the application will add or remove users from a specified role.
Step 4: Add Role Binding Models
Now we’ll add the models used in the previous step, the first class to add will be named “RoleBindingModels” under folder “Models”, so add this file and paste the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class CreateRoleBindingModel { [Required] [StringLength(256, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 2)] [Display(Name = "Role Name")] public string Name { get; set; } } public class UsersInRoleModel { public string Id { get; set; } public List<string> EnrolledUsers { get; set; } public List<string> RemovedUsers { get; set; } } |
Now we’ll adjust the “ModelFactory” class to include the method which returns the response of type “RoleReturnModel”, so open file “ModelFactory” and paste the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public class ModelFactory { //Code removed for brevity public RoleReturnModel Create(IdentityRole appRole) { return new RoleReturnModel { Url = _UrlHelper.Link("GetRoleById", new { id = appRole.Id }), Id = appRole.Id, Name = appRole.Name }; } } public class RoleReturnModel { public string Url { get; set; } public string Id { get; set; } public string Name { get; set; } } |
Step 5: Allow Admin to Manage Single User Roles
Until now the system doesn’t have an endpoint which allow users in Admin role to manage the roles for a selected user, this endpoint will be needed in the AngularJS app, in order to add it open “AccountsController” class and paste the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
[Authorize(Roles="Admin")] [Route("user/{id:guid}/roles")] [HttpPut] public async Task<IHttpActionResult> AssignRolesToUser([FromUri] string id, [FromBody] string[] rolesToAssign) { var appUser = await this.AppUserManager.FindByIdAsync(id); if (appUser == null) { return NotFound(); } var currentRoles = await this.AppUserManager.GetRolesAsync(appUser.Id); var rolesNotExists = rolesToAssign.Except(this.AppRoleManager.Roles.Select(x => x.Name)).ToArray(); if (rolesNotExists.Count() > 0) { ModelState.AddModelError("", string.Format("Roles '{0}' does not exixts in the system", string.Join(",", rolesNotExists))); return BadRequest(ModelState); } IdentityResult removeResult = await this.AppUserManager.RemoveFromRolesAsync(appUser.Id, currentRoles.ToArray()); if (!removeResult.Succeeded) { ModelState.AddModelError("", "Failed to remove user roles"); return BadRequest(ModelState); } IdentityResult addResult = await this.AppUserManager.AddToRolesAsync(appUser.Id, rolesToAssign); if (!addResult.Succeeded) { ModelState.AddModelError("", "Failed to add user roles"); return BadRequest(ModelState); } return Ok(); } |
What we have implemented in this method is the following:
- This method can be accessed only by authenticated users who belongs to “Admin” role, that’s why we have added the attribute [Authorize(Roles=”Admin”)]
- The method accepts the UserId in its URI and array of the roles this user Id should be enrolled in.
- The method will validates that this array of roles exists in the system, if not, HTTP Bad response will be sent indicating which roles doesn’t exist.
- The system will delete all the roles assigned for the user then will assign only the roles sent in the request.
Step 6: Protect the existing end points with [Authorize(Roles=”Admin”)] Attribute
Now we’ll visit all the end points we have created earlier in the previous posts and mainly in “AccountsController” class. We’ll add add “Roles=Admin” to the Authorize attribute for all the end points the should be accessed only by users in Admin role.
The end points are:
– GetUsers, GetUser, GetUserByName, and DeleteUser should be accessed by users enrolled in “Admin” role. The code change will be as simple as the below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
[Authorize(Roles="Admin")] [Route("users")] public IHttpActionResult GetUsers() {} [Authorize(Roles="Admin")] [Route("user/{id:guid}", Name = "GetUserById")] public async Task<IHttpActionResult> GetUser(string Id) {} [Authorize(Roles="Admin")] [Route("user/{username}")] public async Task<IHttpActionResult> GetUserByName(string username) {} [Authorize(Roles="Admin")] [Route("user/{id:guid}")] public async Task<IHttpActionResult> DeleteUser(string id) {} |
Step 7: Update the DB Migration File
Last change we need to do here before testing the changes, is to create a default user and assign it to Admin role when the application runs for the first time. To implement this we need to introduce a change to the file “Configuration” under folder “Infrastructure”, so open the files and paste the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
internal sealed class Configuration : DbMigrationsConfiguration<AspNetIdentity.WebApi.Infrastructure.ApplicationDbContext> { public Configuration() { AutomaticMigrationsEnabled = false; } protected override void Seed(AspNetIdentity.WebApi.Infrastructure.ApplicationDbContext context) { // This method will be called after migrating to the latest version. var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())); var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext())); var user = new ApplicationUser() { UserName = "SuperPowerUser", Email = "taiseer.joudeh@gmail.com", EmailConfirmed = true, FirstName = "Taiseer", LastName = "Joudeh", Level = 1, JoinDate = DateTime.Now.AddYears(-3) }; manager.Create(user, "MySuperP@ss!"); if (roleManager.Roles.Count() == 0) { roleManager.Create(new IdentityRole { Name = "SuperAdmin" }); roleManager.Create(new IdentityRole { Name = "Admin"}); roleManager.Create(new IdentityRole { Name = "User"}); } var adminUser = manager.FindByName("SuperPowerUser"); manager.AddToRoles(adminUser.Id, new string[] { "SuperAdmin", "Admin" }); } } |
What we have implemented here is simple, we created a default user named “SuperPowerUser”, then created there roles in the system (SuperAdmin, Admin, and User), then we assigned this user to two roles (SuperAdmin, Admin).
In order to fire the “Seed()” method, we have to drop the exiting database, then from package manager console you type update-database which will create the database on our SQL server based on the connection string we specified earlier and runs the code inside the seed method and creates the user and roles in the system.
Step 7: Test the Role Authorization
Now the code is ready to be tested, first thing to do is to obtain a JWT token for the user “SuperPowerUser”, after you obtain this JWT and if you try to decode it using JWT.io you will notice that this token contains claim of type “Role” as the below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
{ "nameid": "29e21f3d-08e0-49b5-b523-3d68cf623fd5", "unique_name": "SuperPowerUser", "http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider": "ASP.NET Identity", "AspNet.Identity.SecurityStamp": "832d5f6b-e71c-4c31-9fde-07fe92f5ddfd", "role": [ "Admin", "SuperAdmin" ], "Phone": "123456782", "Gender": "Male", "iss": "http://localhost:59822", "aud": "414e1927a3884f68abc79f7283837fd1", "exp": 1426115380, "nbf": 1426028980 } |
Those claims will allow this user to access any endpoint attribute with [Authorize] attribute and locked for users in Roles (Admin or SuperAdmin).
To test this out we’ll create new role named “Supervisor” by issuing HTTP Post to the endpoint (/api/roles/create), and as we stated before this endpoint should be accessed by users in “Admin” role, so we will pass the JWT token in the Authorization header using Bearer scheme as usual, the request will be as the image below:
If all is valid we’ll revive HTTP status 201 Created.
In the next post we’ll see how we’ll implement Authorization access using Claims.
Hey Taiseer, kudos on this terrific project… I can’t wait for the other two posts…
Thank you Miguel, glad you liked the series 🙂
Thanks, got so excited for the next part when I checked this morning!
You are welcome, glad that you liked the post.
Not all good programmer are good teachers, Not all teachers can make good documentations, Believe me Taiseer, You are a good teacher, goods programmers, good mentors. Thank you so much.
Thanks for your nice words Askinsanya, really happy to hear that my posts are useful to learn from 🙂
I agree with you 100%
Same here.. i really appreciate your contribution specially for beginner like me.
Thank you very much, I was eagerly waiting for this, and the one for claims based is eagerly awaited. Once again thank you very much.
You are welcome Bilal, glad you find it useful.
You’re awsome! Thanks for the great work!
You are welcome, glad you liked it 🙂
Great Post, i’m always learning something new reading your posts.
You are welcome, glad you liked them Luis 🙂
Awesome Articles , I really love them and they’re really helpful , and I’m proud of such a Jordanian talent , I was just wondering if the coming posts are coming anytime soon according to a schedule or you’ll continue writing in spare time?
You are welcome Yazan, glad you liked it, part 5 should be next Monday, so keep tuned 🙂
I’m so excited for the next installment!
Just for anyone else caught out by this: The IdentityRole class and a couple of the other Role-based objects are actually EF-specific. If you are using your own UserStore or using Identity 2.1 without EntityFramework, most of this tutorial won’t work as advertised..
Awesome Articles , I’m new with Angular, have you also a Front-End Angular Sample ?
Glad it was helpful, the last post is about AngularJS front-end app.
Great post and very informative. I’m impatiently waiting for the remaining posts.Good job.
Thanks for your comment, next post coming on Monday.
Monday past, no new post. Me sad 🙁
Sorry about this, it was crazy week 🙁 will do my best to publish it ASAP and thanks for your message, you are one of my loyal readers 🙂
Tnx. Of course we understand that but I also wanted to let you know how eagerly we’re awaiting your new posts! I’m writing ‘we’ because I’m sure this goes for all of your readers.
Can’t wait like Joost said 🙂
This sentence was a little bit odd “the first class to add will be named “RoleBindingModels” under folder “Models”, so add this file and paste the code below:” Because the file is called RoleBindingModels.cs, but you have the class RoleBindingModel in it. I’m not sure how but from the last tutorial, I also ended up with AcccountBindingModel instead of AccountBindingModels. I made the change and put my ChangePasswordBindingModel into it. Not a big deal.
Hi Taiseer, thanks for a great series of post. I am having an issue when testing the application after this post, I get an “Unable to connect to SQL Server database.” but only when I hit the roles api, i can authenticate, change password, but get user and all the roles call gives me that db error. any ideas what I could be doing wrong?
Hi,
If you are not able to connect to the database as the message states then you should not be able to authenticate or change password, that’s strange, I can’t think of reason for this issue, if you solved please share it here so I update the post if there is something missing.
Hi,
I am looked at it again today and it seen like the issue happens only on functions or classes that has “[Authorize(Roles = “Admin”)]”. After searching around I found this: “http://stackoverflow.com/questions/14521003/mvc4-userisinrole-unable-to-connect-to-sql-server-database”
I added and now it works. I am not exactly sure why though.
I have the issue too, and it is solved by adding in the web.config file. Many thanks to Taiseer and staphill 🙂
Eagerly awaiting part 5 and 6 – One request, you can add decouple the resource server and Authorisation server in part 7 to make this ultimate tutorial.
Hi Bilal, Part 5 is almost ready, regarding decoupling them it should be easy process and I have blogged about it earlier here, you maybe be interested in forking the repo and implement it and will be happy to refresh your repo too.
ohh, I followed the old version of your post and got the api. I managed move the orders controller to resource server. Api acces was successful but could not access Orders via Angular client, it was still looking for ordersController in authorisation server and returned 404.
I need to to learn Github as well 🙂 — I am an accountant by the way.
Hi Taiseer, thank you by share with us your knowledge.
I have some questions:
a) Can I add social logins and refresh token a this approach?, like you explained in ASP.NET Web API 2 external logins with Facebook and Google in AngularJS app.
b) Can I implement dependency injection using Ninject?, like you explained in Building ASP.Net Web API RESTful Service – Part 4, or it is not necessary?, because I want to have a single instance of database context object shared by all objects created via the kernel for that HTTP request. Until now I’m following ASP.NET Web API Claims Authorization with ASP.NET Identity 2.1 – from Part 1 to Part 4.
Thank you very much for this excellent tutorial.
Kind regards,
Raul
Hi Raul, sure you can use any IoC container, but I prefer to app.CreatePerOwinContext() to create DB instance per owin request. Regarding the social logins I guess it should work even with JWT tokens, I didn’t do it before but it should work.
Found Some strange security behavior after implementing this article.
after running your last command that created the “Supervisor” I’ve done the following :
1.Calling the “assignRolesToUser” endpoint (http://localhost:60672/api/Account/user/id/roles) with the string array
[‘Supervisor’] as the body -> this should remove the Admin Role and assign a Supervisor role according the the logic implemented in that endpoint (removing all and then adding).
2. now , a second call to this endpoint should not succeed since my user is no longer in Admin Role and the endpoint
has [Authorize(Roles = “Admin”)] attribute.
3. But it does -> Very strange ! anyhow , just before the call I’ve opened the DB to make sure the user has only 1 role (‘Supervisor’) and it has.
so why am I given access to the endpoint if the user is no longer the admin ?
is it spooky Owin /Context magic ?
please verify it yourself by following my scenario.
GREAT POST !
In point 2, did you obtain a new token for the new created supervisor user? I doubt that you kept using the same admin access token.
correct. it is the old token.
but still… it means that for the period of 30 minutes (or the time the access token was provisioned), no changes in the role affect the resource server access policy.
I found it to be problematic.
I would have expect that this will re-create the SecurityStamp field in the user table and revoke the access token
Which is not whats happening since the SecurityStamp field only changes for user/password change.
This is how access tokens work, any change on claims will be reflected on your next access to the system.
Hi Taiseer,
I am having a problem with routing here, did you adjust the default routing in WebApiConfig?
When testing the create role api call, I get the following error:
{“Message”:”An error has occurred.”,”ExceptionMessage”:”Multiple actions were found that match the request: \r\nCreate …
Hi,
I’m using attributes routing here, double check how you attribute your controller using RoutePrefix attribute as well how you attribute you action methods using Route attribute.
Thanks for your reply, I managed to fix the issue, I had “using System.Web.Mvc” included which was conflicting with “System.Web.Http” classes for routing. Removing System.Web.Mvc fixed the problem.
Great post Taiseer! How would I get a list of users in a role? If I get a role from AppRoleManager.FindByIdAsync(guid_id) it returns the role but the users collection inside the role is empty.
Hi Fred,
You need to query this and do a modification on the “ModelFactory” class, I do not have access to the source code now but as far as I remember there is method that you can provide the role id for it and it gets a the users in this role.
Did you figure this out in the end?
Hello Taiseer ,
Thanks for this amazing tutorials!!
My question is about getting resources only created by his owner.
Imagine that we have a table with several “orders” (created by millions of users) and we only should see our “orders”.
How I solve this problem based on your JWT authentication?
Best
Hi Hugo, you can get the user name from the provided token by reading the claim of type “sub”, then based on this you can use it to filter your orders records.
Just a minor correction: The null-coalescing operator (??) will not assign any value to _AppRoleManager, leaving it null at all times. The getter for AppUserManager/AppRoleManager should be either:
//Same behaviour as now
get { return Request.GetOwinContext().GetUserManager(); }
//What you probably want
get { _AppRoleManager ?? (_AppRoleManager = Request.GetOwinContext().GetUserManager()); }
Great series, though I wish you would have separated the Authorization from the Resource server from the start. It is easier to put them in one project than it is to separate them afterwards.
Thanks!
Hi Troels,
Thanks for your comment, I agree with you but it will add more complexity for learning purposes.
Hello once again.
Microsoft has another API product in Preview called Azure APP Service API (www.)
I wonder if the Identity 2.0 approach presented in this series will be valid for this new Service.
the official documentation says you can use Azure Active Directory for Authentication ,and that it supports oAuth 2.0
but the Visual Studio template comes rather empty and I wonder if all customization we are talking about will be valid/necessary in the new service.
Thanks !
sorry forgot the link , its https://azure.microsoft.com/en-gb/documentation/articles/app-service-api-dotnet-add-authentication/
I’m using jwt.io to debug the generated jwt token and I can’t get the green sign of “Signature Verified”. What i’m doing wrong? The “secret” is the AudienceSecret, right? (with secret base64 encoded checked)
Solved!
Hugo, I have the same issue, but cannot solve it. Is it because my provider is localhost? Can you shed some light on what you found?
Thanks
Excellent article! Just a one question. If a user with lower privileges tries to access restricted action,
the response comes as 401 which is Unauthorized and not as 403 Forbidden. This might be a bit pain for the frontend
when distinguishing why the resource cannot be accessed …
Hmm I agree with you here, and this is the default implementation for the [Authorize attribute], you can override this attribute and return the desired status code.
just in case someone will have a same problem … to override your Authorize attribute
protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
{
HttpResponseMessage response;
if (actionContext.RequestContext.Principal.Identity.IsAuthenticated)
{
response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Forbidden, “insufficient_scope”);
response.Headers.Add(“WWW-Authenticate”, “Bearer error=\”insufficient_scope\””);
}
else
{
response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, “Unauthorized”);
}
actionContext.Response = response;
}
as per
http://leastprivilege.com/2014/10/02/401-vs-403/
and
https://github.com/IdentityModel/Thinktecture.IdentityModel/blob/master/source/WebApi.ScopeAuthorization/ScopeAuthorizeAttribute.cs
My application returns null on property protected ApplicationRoleManager AppRoleManager (return _AppRoleManager ?? Request.GetOwinContext().GetUserManager();)
I’m also getting the crash when trying to add the supervisor role.
I’m having an issue trying to assign roles via the API. The security works fine, but I cannot get the body of the PUT to bind to the rolesToAssign string array in the controller. It comes in empty, which wipes all roles from the user.
here is my request body (raw) JSON:
[
{ “rolesToAssign” : [“Admin”, “SuperAdmin”] }
]
What am I doing wrong.?
I am having the same issue. Has anyone succeeded in assigning role(s) to user?
Strange, please download the repo as it is working at my end with no problems at all.
The request body should be as the below:
[“Dataentry”,”SuperSupervisor”]
Very nice post. Kudos on the great job.
Small correction if you can make..in Step 7: Update the DB Migration File..configuration.cs is in migration folder and not infrastructure
Thanks Manoj for the clarification, will check it and update the post.
Useful series. I notice that you use Postman as a client. Any tips on how we can use the Authorization section in Postman with this template rather than having to append the Authorize header to request headers by hand?
Hi Michael,
Good question that it is an item in my long ToDO list 🙂 I want to try it out and see how I can use it, once I try it I will post the outcome here. If you already did it please share the results.
Hi Taiseer,
I have finished reading Part 5 of your blog and have got the download working from GitHub.
Just wanted to say THANK YOU.
Any idea when you will have Part 6 ready re. AngularJS application which connects all those posts together.
Kind Regards,
Paul
You are most welcome, it’s hard post which I need to finish soon, thanks for your message 🙂
Hi Taiseer,
Kudos for this awesome series. Very eagerly waiting on your next post. Thank you very much!..
You are welcome, thanks for your message.
Hats of to you sir, thanks again!
Hi Taiseer,
First of all Thanks for this great article. I have implemented same in my environment.
I have few queries regarding security.
1. What about session hijacking?
2. If I need to return new refresh token on each subsequent request what changes I need to make?
Hi Vikas,
There is no session established with REST Api, everything is stateless and you are sending token and validating it with each request.
Why you want to generate refresh token with each request? You should not do this at all, you need to get refresh token only once when you get an access token and you store it at the client for future use when the access token expires.
Dear Taiser,
I completed your tutorial, but every Time I try to use the controllers with Role authorization, I get “Authorization has been denied for this request.”. I checked the JWT token, and it contained the required “Admin” role. I downloaded your solution from GitHub, but the result is the same.
Thanks for the articles, they are great, I learned much from them!
Hi Bailnt,
That is strange, I have just tried it and it works fine,If your removed the Authorized attribute with a role and replace it just with [Authorized] this will work? I’m afraid that your JWT token is not accepted by the Api.
The authorize attribute works with roles. I think everyone is making the same mistake which I did. First try just with Authorize Attribute. Then use the same jwt token and change the code to add roles to authorize attribute and try.
When attribute changes, need to get new token. Then with new token, it works perfectly
Yup, claims are stored in the token, so if you changed a role for a user who already owns the token, then the user needs to obtain new one in order to have those claims encoded within the token.
Hi Taiseer,
First, thank you so much for all these great articles. You are the best.
While implementing roles, I got a strange issue where the [Authorize] attribute works just perfectly fine but got error while adding roles. The issue is a connection time out issue while connecting to SQL server. Fixed this by adding
on web.config file. Don’t know how this works but is working. 🙂
Thank you so much once again.
Hi,
I cant see what you addded to the web.config, seems wordpress filter removed it. You should not add anything extra to web.config in order to make roles working.
Excelent Articule ! I have tried angular application pointing to the web api and everything works perfect. The only issue that I have is about [Autorize] attribute. It is working fine adding users, but it is not working (for me) with Roles.
I have used the Seed method in order to add an admin user with three roles, Admin, SuperAdmin, User.
if I login with admin user, I can not access to [Authorize(Roles = “Admin”)] methods. Do I have to assign manually the roles to Context.User. I think that it is done on GrantResourceOwnerCredentials method. But just double checking.
See reference:
http://stackoverflow.com/questions/18807806/authorize-attribute-not-working-with-roles
Hi Leo, thaks for your message.
You do not need to add them manually, those will come from ASP.NEt identity helper method as the code here Can you check the jwt token using jwt.io and make sure you have a claim of type “Role” set to the value “Admin”?
Thanks for your quick answer ! Got it, I think that I found the issue. I am using your previous version called AngularJSAuthentication.API and there you have a method GrantResourceOwnerCredentials and there there is this line that allays asign user Role. “identity.AddClaim(new Claim(ClaimTypes.Role, “user”));”
I have updated that line using ” foreach (var role in user.Roles)
{
identity.AddClaim(new Claim(ClaimTypes.Role, role));
}” and now is working fine. Excellent article !!
I tried to implement the role based solution and it provides proper grant, claims, roles:
I can access resources protected with Authorize attribute only when provide the bearer token.
Unfortunately once I specify role on the Authorize attribute it stops working with some strange “unable to open database error”.
[Authorize(Roles=”Admin”)]
And here my claims when grant is created:
[
{
“subject”: “Admin”,
“type”: “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier”,
“value”: “cf55a34e-ba04-4a12-bb6a-ee9bce5e903f”
},
{
“subject”: “Admin”,
“type”: “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name”,
“value”: “Admin”
},
{
“subject”: “Admin”,
“type”: “http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider”,
“value”: “ASP.NET Identity”
},
{
“subject”: “Admin”,
“type”: “AspNet.Identity.SecurityStamp”,
“value”: “18fd3ecc-40e2-4613-be63-4bae20f9c93b”
},
{
“subject”: “Admin”,
“type”: “http://schemas.microsoft.com/ws/2008/06/identity/claims/role”,
“value”: “Admin”
},
{
“subject”: “Admin”,
“type”: “iss”,
“value”: “http://localhost:1684”
},
{
“subject”: “Admin”,
“type”: “aud”,
“value”: “cca73ab6c73d401ca28b4d306d342647”
},
{
“subject”: “Admin”,
“type”: “exp”,
“value”: “1452597814”
},
{
“subject”: “Admin”,
“type”: “nbf”,
“value”: “1452511414”
}
]
https://www.dropbox.com/s/kb208ssgmbjebup/Screenshot%202016-01-11%2006.48.22.png?dl=0
What could be wrong here?
I just found the answer:
http://stackoverflow.com/questions/23941027/asp-net-identity-authorize-attribute-with-roles-doesnt-work-on-azure
All you need is to disabled default RoleManager:
This is such an amazing series! Helped a lot! Thanks for all the nice effort Taiseer!
You are welcome jothi, happy to help!
Can you please update, some of these methods are depricated in 2.2
I do not think there is any deprecated methods I’m using in 2.1 version, what did you face?
thanks for these articles, they are really great!!
I have just one question:
Wouldn’t it be much simpler to just get all user-roles when the user logs in the system and assign them right to the identity?
with this I wouldn’t need all the AppRoleManager, etc…
Here is my example (most of the code comes from you 😉 )
– I’m using userManager.ClaimsIdentityFactory.CreateAsync
– and assign the role like identity.AddClaim(new Claim(identity.RoleClaimType, “admin”));
this should be enough to handle roles in [Authorize(Roles=”admin”)]
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add(“Access-Control-Allow-Origin”, new[] {“*”});
using (var userManager = CreateUserManager(context.UserName))
{
var user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError(“invalid_grant”, “The user name or password is incorrect.”);
return;
}
var identity = await userManager.ClaimsIdentityFactory.CreateAsync(userManager, user, context.Options.AuthenticationType);
foreach (var role in user.Roles.Select(r => r.RoleId).Distinct().ToList())
{
identity.AddClaim(new Claim(identity.RoleClaimType, role));
}
context.Validated(identity);
//return new GenericPrincipal(null, new string[0])
}
}
Can I use this if I am using Odata. authenticate against a database custom user table and custom role table. We dont use identity tables we have our custom tables for user and roles ?
Hi Ashy,
Sure thing you can use this with OData with your own custom tables. Let me know if you need more details.
Hi Taiseer,
I posted a question in stackoverflow
http://stackoverflow.com/questions/35447730/authentication-and-authorization-asp-net-web-api-and-angularjs-windows-and-for
I am directed back to your blog. You tutorials have so much respect and credibility in the developers world. Great job and keep up the good work.
Can you please help with me with the question on stackoverflow ?
Thank you
Hi Taisser,
I know this question is asked before and I could get any definitive answer.
how to decide odatacontroller vs webapi controller ?
Thank you,
Ashy
Hi ,
I am trying to implement Identity Management in my Application. I am getting below error.
“The entity type IdentityRole is not part of the model for the current context.”
I have below code for RoleManager.
public class ApplicationRoleManager : RoleManager
{
public ApplicationRoleManager(
IRoleStore roleStore)
: base(roleStore)
{
}
public static ApplicationRoleManager Create(
IdentityFactoryOptions options, IOwinContext context)
{
return new ApplicationRoleManager(
new RoleStore(context.Get()));
}
}
And below code for ApplicationUserManager.
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(string connString)
: base(connString)
{
}
public DbSet UserRoles { get; set; }
public DbSet PreviousPasswords { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext(“RPMS”);
}
// public DbSet Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove();
}
}
Can you please advice on as what mistake am I making.
Thanks in advance.
Hi,
I’m not sure what is your issue but this might help.
Hi
Instead using the Identity framework to validate the user credentials I want to use a webservice to validate this user and then generate a token. How can do the same ? The webservice is essentially a layer to access membership users. Please note in my case this webservice to access the users is already present. Do you have any example of this anywhere ?
Hi Amol,
You need to replace the highlighted section here, with a call to your remote web service where you provide credentials and it returns if those credentials are valid or not, and you continue the logic as is.
Hope this help.
Hello Taiseer , i’m sorry about the rush i need an urgent help pleaze , i followed your serie ” Token Based Authentication using ASP.NET Web API 2, Owin, and Identity ” with angular and now i need to add role management so i tried the easiest thing, i added the role on the database and then added [Authorize(Roles=”Superusers”)] in the controller methodes but it’s throwing me 401 unauthorized i don’t know what i am missing.
Hello Meriem,
When you try to decode the JWT using jwt.io do you see a claims of type “Roles”? If not then your JWT doesn’t contain those roles and the Api will never understand them. If you removed the “Roles” from “Authorize” attribute it is working, right?
i am trying to decode but getting an error like invalid signature, this is the json i have
{
“access_token”: “Q7RrQnV0Az_AHpBXGYWEjP6BZBDoNW49e9x-MfD3zIaaglx16DyOALEQSqcrupEVBAD7aO04Z5LrDoNpcD8eMzlErtWblpfsNpR4NfNVlUuncXAmiXG66fIRKrDNDkm7DgAB70uobdQ9_OB0x5o9BiNZryrQx_LvtwpfQ6fCJrrF61DIiPrh_MIyV_ueZg3NJ6MTjBEIZG-zHEp2BfuWi0BQJFd8wVFzR6YsmLg5Aba7pyMFjpFSlYbR4tvg8RgkTa1TgwejLw09_rQaPdQQmVQELa3t8TEzqCu8hBsZ3HkZxb8Y1uJugAGTP9Nw3Ar-B9dbUA”,
“token_type”: “bearer”,
“expires_in”: 1799,
“as:client_id”: “”,
“userName”: “admin9”,
“.issued”: “Wed, 23 Mar 2016 16:50:28 GMT”,
“.expires”: “Wed, 23 Mar 2016 17:20:28 GMT”
}
Hi… Meriem,
Please make following changes to your desired goal,
Prerequisite :
Your database contains one Users Table, one Roles Table, and one UserRoles table
1) Users Table contain your application users
2) Roles table contain your application Roles to be assigned to Users
3) UserRoles table contains mapping of Roles to Users means Role ‘Admin’ to be assigned to ‘ABC’ user.
After that
Open method ‘GrantResourceOwnerCredentials’ that is present in class ‘SimpleAuthorizationServerProvider’ which is inherited from ‘OAuthAuthorizationServerProvider’
Now You see the code like code snippet 1:
code snippet 1:
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
identity.AddClaim(new Claim(ClaimTypes.Role, “user”));
identity.AddClaim(new Claim(“sub”, context.UserName));
Just make following changes:
code snippet 2:
var userRoles = await _authService.GetUserRolesByUserID(UserID);
foreach (var role in userRoles)
{
identity.AddClaim(new Claim(ClaimTypes.Role, role.RoleName.ToString()));
}
This above code snippet 2 is use for retrieving UserRoles from database. for your side you just write a code to retrieve UserRoles from database
What you have to performed here is:
Just comment the 3rd line of code snippet 1,
and copy the code in snippet 2 and paste it instead of 3rd line of code snippet 1 that is look like,
identity.AddClaim(new Claim(ClaimTypes.Role, “user”));
What it actually means:
Here in 3rd line of code snippet 1 contains static role named as ‘user’ so all methods in your controller are accessible for only for the role ‘user’
So by the code snippet 2 you just take all the roles for your desired User’s from your database and assigning these roles in foreach loop…
Have a nice day…
Thanks Sohaib for posting this detailed answer, you are correct, I guess you are missing this highlighted LOC, you can get the roles from the database and you can add many roles for the user. Hope this help.
thanks a lot i can’t be more gratefull since i’m beginner and working on my graduation project. Shoaib may i ask what’s authService for you and UserID has to be extracted right ? but from where because here is all the code before sinippet 1
{
var allowedOrigin = context.OwinContext.Get(“as:clientAllowedOrigin”);
if (allowedOrigin == null) allowedOrigin = “*”;
context.OwinContext.Response.Headers.Add(“Access-Control-Allow-Origin”, new[] { allowedOrigin });
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;
}
}
…
ops sorry i missedd the part saying i have to write it
i am kind of struggling can you help me with the method to extract all roles from the db
Hi Meriem,
This id not a JWT token, this is the default opeque access token, if you would like to know more about JWT, please check this post.
Hi… Taiseer,
As you said in previous post that I’d missed to write the highlighted LOC such as,
identity.AddClaim(new Claim(ClaimTypes.Role, “user”));
but this LOC is actually included in foreach loop of code snippet 2.
the LOC in foreach loop of code snippet 2 is look like:
identity.AddClaim(new Claim(ClaimTypes.Role, role.RoleName.ToString()));
Thanks for your valuable response…
Hi… Meriem,
just find the below snippet in ‘SimpleAuthorizationServerProvider’ class
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;
}
}
In above code when you just type a object name of IdentityUser that is ‘user’ then just type dot(.) then you get the list of properties of IdentityUser class and in that class you find the ‘Id’ property like.
user.Id,
and after that you just pass this user.Id to your method that you get all the UserRoles.
And for simplicity the methos for getting all the roles from database is like..
public List GetRolesByUserBasicID(long UserID)
{
List UserRoleList = new List();
try
{
using (SqlConnection con = new SqlConnection(“Your database connection string that is present in web.config file”))
{
SqlCommand cmd = new SqlCommand(“select RoleName from UserRoles where UserID = “+UserID+””, con);
cmd.CommandType = System.Data.CommandType.Text;
SqlDataReader dr = null;
dr = cmd.ExecuteReader();
if (!dr.IsClosed && dr.HasRows)
{
while (dr.Read())
{
UserRoleList.Add(new UserRoles
{
RoleID = Convert.ToInt32(dr[“RoleName”])
});
}
}
return UserRoleList;
}
}
catch (Exception ex)
{
//error writing code is here
return null;
}
}
thank you again for the help and sorry for the mess, if i understood even if i added claims like identity.AddClaim(new Claim(ClaimTypes.Role, “admin”)); (instead of snippet2) and then added admin as a role (in roles table ) and added its role id to a user it will work and only admins will be able to user the method ?
After trying all the users are able to use the method i’m really confused
Thank you very much shoaib for your generous help, now if i want to do this with angular (like allow one html page to admin and others to users) do you have an idea
Thank you for an article. You’ve proposed CRUD RolesController. My question is: What are Create or delete method for? Even if we create some Role and give it to some User how we can force controller to respect that new Role. Annotation [Authorize(Roles=”SomeRole”)] is constant (source level configured). Is there any way to define which controllers or their methods should respect newly added role dynamically in runtime? If not what is the point of adding or editing Roles?
Hi Mombip,
Using roles to annotate your controllers is no flexible, how about you try looking at claims authorization which gives you better flexibility
Hello Taiseer.
Thank you for reply. I appreciate it. I’ve read an article about Claims you’ve suggested. I understand that Roles are in fact Claims. Claims can be assigned dynamically to logged in user when some conditions are met (dynamic roles). Finally we can analyse claims and make decision to assign another Claim or Roles to the user. But. All Calims and Roles names are hardcoded in source code somewhere. This dynamically assigned Role is already defined in the system. Calims are “calculated” in ExtendedClaimsProvider.GetClaims(user) and Claim name “FTE” is hard-coded in GetCalims method. Role “IncidentResolvers” is also hard-coded in both “OrdersController” and “RolesFromClaims” classes. I still don’t understand what is the point of creating new roles and how they can be used without changing the application source code?
Imagine that I’m an system administrator (no programmer). I’ve added some new role, let say “AdvancedUser” and assigned it to user “mombip”. Ok on the basis of this article it works. My user has totally new role I’ve defined 10 seconds before. What now? How can I define, without writing source code, what that new role is and what kind of privileges “mombip” user got with that new Role. There is no [Authorize(Roles = “AdvancedUser”)] annotation in my code and there is no method which can translate this new Role/Claim to other already existing Role. How can I use newly created roles in already existing system.
First, thank you so much for Excellent articles
I want implement sso by this application
can i do by openID?
please help me
Hi Masha,
My recommendation is to use ThinkTecure Identity server instead of building this from scratch, having SSO from scratch is not an easy process.
I need to send additional data in response like user full name and another data
like that
AuthenticationProperties properties =CreateProperties(user.FirstName,user.UserName);
var ticket = new AuthenticationTicket(oAuthIdentity, properties);
but No data returned
I need to send additional data in response when user login , like user full name and another data
like that
AuthenticationProperties properties =CreateProperties(user.FirstName,user.UserName);
var ticket = new AuthenticationTicket(oAuthIdentity, properties);
but No data returned
Hi Taiseer
Thank you for the article.
I have my Migration related code on the repository layer which is different to the web project layer.
Because of this, i cannot access the ApplicationUser or RoleManager class. Hence i cannot complete the last part of your article where you are creating a default admin account in the seed method. Is it a must that i need to move this migration related code to the web project or is it possible to implement this while having the code in repository layer?
Hello Pawan,
You can keep the migration code in the repository layer for sure, what you are doing is the right way in terms of abstractions. No need to move it to the Web project.
Thanks for these easy to follow series of articles. Could you please update this post by illustrating how the request body should be in the following request (using POSTMAN) ? http://localhost:xxxxx/api/accounts/user/{userid}/roles
Hi Taiseer,
Thank you for sharing such a useful article and code base, I’ve gone through all your tutorials and I found it very straight forward to achieve a great authentication solution.
thanks,
Shane
You are welcome Shane, thanks for your message 🙂
Hi,
When I call GetAllRoles(), the object returned contains an empty Users array. Do you know how I can get it to work so that Users contains an array of user Id’s instead of being empty? FYI there are definitely users assigned to roles.
Thanks,
Rob.
With regard to:
AngularJS Authentication and Authorization with ASP.NET Web API and Identity 2.1 – Part 6
Do you have some source code I can look at, please?
There is no article, so source code would be a good alternative.
hi @Taiseer Joudeh i have try this your blog and i am write
[Authorize(Roles = “Admin”)]
public ActionResult Index(){} in my controller then after i am login as a admin but don’t can’t access this method. i have create “oAuthIdentity.AddClaim(new Claim(ClaimTypes.Role, “Admin”));” like this role in ApplicationOAuthProvider.cs class. so how can do authorize role with login in my demo.can you tell me.
Hi Hiren,
Did you make sure that authenticated user identity has the correct claim value which is “Admin” and the correct claim type which is “Role” after you successfully authenticated?
Thanks for the article. I always enjoy reading your tutorials. Anyway you can write up an article on how to implement permission-based authorization. Where authorization is based on the permissions the user has instead of the roles they are in. User has a role/multiple roles. Roles contain multiple permissions. Application checks if user has such and such permission based on the role they are in.
Thanks again!
Thanks Daniel for your comment, I will defiantly consider this, but If you are in hurry please check this post which might give you a starting idea.
Hello Thanks for the article ..I enjoy it then i would like to ask you about class “CreateRoleBindingModel” in Step4 why we put it ???
Hello Houda, thanks for your comment.
Well this model exists here and I know it contains only a single property but I’m not fan of passing simple data types as params, models will be better approach as well you can befit from the data annotations on model properties.
amazing tutorial! Thankyou!
Hello. I think you have a very good sample here. Nice explaination with source code. Good job. But will you please explain also the next stage? How will we send a request from clients? Do we have to add Authorization header?
Thanks
Hi Taiseer,
Amazing article. Any chance of releasing the AngularJS Authentication and Authorization part of the tutorial? Would be really nice if we could consume the .net core to do the above with angular.
Hi,
Lets say we have a role Lender and add User1 to that role. We then get the token for the user and they have access to [Authorize(Roles = “Lender”)].
Now we remove User1 from Lender.
I found that User1 is still authorized for [Authorize(Roles = “Lender”)] because we haven’t updated the token, at least I don’t. My implementation is from https://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/ so I’m not sure if you are updating the token in this tutorial.
Hello Really Thanks…:)
I have one question. If user has two roles just like above example than how can we manage them especially when you need to flip the Roles based on some criteria?
Hi Taiseer,
Your article is really v helpful. i have followed your article as it is.but authorize[(Roles=”admin”)] is not working.I am putting Authorize attribute on my categorycontroller. but it is returning 401 error. can you help. what wrong i am doing.Thanx for such a wonderful article.
Hi Taiseer,
Just FYI..I have found the answer by myself.i was missing to add authorization header on every api call.Once again thanx for your posts.waiting for your articles on mvc application as a client to call the above apis.
You are welcome, happy to hear posts are useful 🙂
Hi, you said: To implement this we need to introduce a change to the file “Configuration” under folder “Infrastructure”, so open the files and paste the code below … Am i right that we should put these codes in “Migrations” not in “Infrastructure”?
On this line:
[Route(“create”)]
public async Task Create(CreateRoleBindingModel model)
The object CreateRoleBindingModel does not exist. You meant this one instead:RoleBindingModels
When you say
To implement this we need to introduce a change to the file “Configuration” under folder “Infrastructure”,
The file isnot in there, what you meant was the folder Migrations
nice course you made! but need to be finished!
If i give the permission to the users to create the new role.Then what will be the solution.don’t i need recompile the code again?? is this the right approach.??
and also if a controller has 15 type roles permission.
then the code will be
[authorized(“one”,”two”……………”fifteen”)]
is that the right approach??
Hello Taiseer,
Its a great article which helped me in integrating identity and oauth to one of existing application. So far i am using bearer tokens instead of jwt for my application. Everything is working fine except when we call /api/roles api, which is failing with below error.
“message”: “An error has occurred.”,
“exceptionMessage”: “Error getting value from ‘Users’ on ‘System.Data.Entity.DynamicProxies.IdentityRole_’.”,
“innerException”: {
“message”: “An error has occurred.”,
“exceptionMessage”: “An error occurred while executing the command definition. See the inner exception for details.”,
“innerException”: {
“message”: “An error has occurred.”,
“exceptionMessage”: “There is already an open DataReader associated with this Command which must be closed first.”,
All the classes and packages are similar to what we have in your github project. I am not sure what could be the issue. Please help.
Hi Taiseer,
Its a great article to understand the Asp.Net Identity. I have implemented and it works fine when i am calling it from Postman.
I have created a separate Asp.Net MVC Application . From that application when i am trying to call the Web API it is returning “Unauthorized”.
I have investigated the issue and found that the Web API is returning the token correctly to the endpoint(my mvc application). After getting the token when i am making a subsequent call it is throwing “Unauthorized”. I have copied that token and test with Postman and it is not giving any “Unauthorized”.
Could you please help me on this.
Thanks,
Rabbani
Hi Taiseer,
Thanks for the great article.
I have run the source code and call the api from a different asp.net mvc application like below
var client = new RestClient(“http://localhost:59822/”);
var request = new RestRequest(Method.POST);
request.Resource = “oauth/token”;
request.AddHeader(“content-type”, “application/x-www-form-urlencoded”);
request.RequestFormat = DataFormat.Json;
request.AddParameter(“application/json”, “grant_type=password&username=itqinfotech@gmail.com&password=Itq_2018”, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
if (response.StatusCode == HttpStatusCode.OK)
{
var result = JsonConvert.DeserializeObject(response.Content);
string token = result.access_token;
var request1 = new RestRequest();
request1.Resource = “api/accounts/users”;
request1.Method = Method.GET;
request1.AddParameter(“Authorization”, “bearer ” + token, ParameterType.HttpHeader);
request1.Parameters.Clear();
var response2 = client.Execute(request1) as RestResponse;
The token is returning perfectly but when i am calling the “api/accounts/users” Api it is returning “Unauthorized”.
The same token i am using from Postman and it is returning the user data.
Could you please help me on this
Thanks,
Rabbani
hello Taiseer,
this article is amazing
I’m waiting for the sixth part. .
Nice post! Really a nice list is presented by you. In my opinion, this list helps the programmer to understand the .NET programming. I hope to you to present this type of post in the future also.
Thanks for sharing the information.
awesome Post.Thanku so much for sharing your knowledge.