This is the fifth 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 – Part 4.
- ASP.NET Web API Claims Authorization with ASP.NET Identity 2.1 – (This Post)
- 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 Web API Claims Authorization with ASP.NET Identity 2.1
In the previous post we have implemented a finer grained way to control authorization based on the Roles assigned for the authenticated user, this was done by assigning users to a predefined Roles in our system and then attributing the protected controllers or actions by the [Authorize(Roles = “Role(s) Name”)] attribute.
Using Roles Based Authorization for controlling user access will be efficient in scenarios where your Roles do not change too much and the users permissions do not change frequently.
In some applications controlling user access on system resources is more complicated, and having users assigned to certain Roles is not enough for managing user access efficiently, you need more dynamic way to to control access based on certain information related to the authenticated user, this will lead us to control user access using Claims, or in another word using Claims Based Authorization.
But before we dig into the implementation of Claims Based Authorization we need to understand what Claims are!
Note: It is not mandatory to use Claims for controlling user access, if you are happy with Roles Based Authorization and you have limited number of Roles then you can stick to this.
What is a Claim?
Claim is a statement about the user makes about itself, it can be user name, first name, last name, gender, phone, the roles user assigned to, etc… Yes the Roles we have been looking at are transformed to Claims at the end, and as we saw in the previous post; in ASP.NET Identity those Roles have their own manager (ApplicationRoleManager) and set of APIs to manage them, yet you can consider them as a Claim of type Role.
As we saw before, any authenticated user will receive a JSON Web Token (JWT) which contains a set of claims inside it, what we’ll do now is to create a helper end point which returns the claims encoded in the JWT for an authenticated user.
To do this we will create a new controller named “ClaimsController” which will contain a single method responsible to unpack the claims in the JWT and return them, to do this add new controller named “ClaimsController” 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 |
[RoutePrefix("api/claims")] public class ClaimsController : BaseApiController { [Authorize] [Route("")] public IHttpActionResult GetClaims() { var identity = User.Identity as ClaimsIdentity; var claims = from c in identity.Claims select new { subject = c.Subject.Name, type = c.Type, value = c.Value }; return Ok(claims); } } |
The code we have implemented above is straight forward, we are getting the Identity of the authenticated user by calling “User.Identity” which returns “ClaimsIdentity” object, then we are iterating over the IEnumerable Claims property and return three properties which they are (Subject, Type, and Value).
To execute this endpoint we need to issue HTTP GET request to the end point “http://localhost/api/claims” and do not forget to pass a valid JWT in the Authorization header, the response for this end point will contain the below JSON object:
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 |
[ { "subject": "Hamza", "type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", "value": "cd93945e-fe2c-49c1-b2bb-138a2dd52928" }, { "subject": "Hamza", "type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", "value": "Hamza" }, { "subject": "Hamza", "type": "http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "value": "ASP.NET Identity" }, { "subject": "Hamza", "type": "AspNet.Identity.SecurityStamp", "value": "a77594e2-ffa0-41bd-a048-7398c01c8948" }, { "subject": "Hamza", "type": "iss", "value": "http://localhost:59822" }, { "subject": "Hamza", "type": "aud", "value": "414e1927a3884f68abc79f7283837fd1" }, { "subject": "Hamza", "type": "exp", "value": "1427744352" }, { "subject": "Hamza", "type": "nbf", "value": "1427657952" } ] |
As you noticed from the response above, all the claims contain three properties, and those properties represents the below:
- Subject: Represents the identity which those claims belongs to, usually the value for the subject will contain the unique identifier for the user in the system (Username or Email).
- Type: Represents the type of the information contained in the claim.
- Value: Represents the claim value (information) about this claim.
Now to have better understanding of what type of those claims mean let’s take a look the table below:
Subject | Type | Value | Notes |
---|---|---|---|
Hamza | nameidentifier | cd93945e-fe2c-49c1-b2bb-138a2dd52928 | Unique User Id generated from Identity System |
Hamza | name | Hamza | Unique Username |
Hamza | identityprovider | ASP.NET Identity | How user has been authenticated using ASP.NET Identity |
Hamza | SecurityStamp | a77594e2-ffa0-41bd-a048-7398c01c8948 | Unique Id which stays the same until any security related attribute change, i.e. change user password |
Hamza | iss | http://localhost:59822 | Issuer of the Access Token (Authz Server) |
Hamza | aud | 414e1927a3884f68abc79f7283837fd1 | For which system this token is generated |
Hamza | exp | 1427744352 | Expiry time for this access token (Epoch) |
Hamza | nbf | 1427657952 | When this token is issued (Epoch) |
After we have briefly described what claims are, we want to see how we can use them to manage user assess, in this post I will demonstrate three ways of using the claims as the below:
- Assigning claims to the user on the fly based on user information.
- Creating custom Claims Authorization attribute.
- Managing user claims by using the “ApplicationUserManager” APIs.
Method 1: Assigning claims to the user on the fly
Let’s assume a fictional use case where our API will be used in an eCommerce website, where certain users have the ability to issue refunds for orders if there is incident happen and the customer is not happy.
So certain criteria should be met in order to grant our users the privileges to issue refunds, the users should have been working for the company for more than 90 days, and the user should be in “Admin”Role.
To implement this we need to create a new class which will be responsible to read authenticated user information, and based on the information read, it will create a single claim or set of claims and assign then to the user identity.
If you recall from the first post of this series, we have extended the “ApplicationUser” entity and added a property named “JoinDate” which represent the hiring date of the employee, based on the hiring date, we need to assign a new claim named “FTE” (Full Time Employee) for any user who has worked for more than 90 days. To start implementing this let’s add a new class named “ExtendedClaimsProvider” under folder “Infrastructure” 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 |
public static class ExtendedClaimsProvider { public static IEnumerable<Claim> GetClaims(ApplicationUser user) { List<Claim> claims = new List<Claim>(); var daysInWork = (DateTime.Now.Date - user.JoinDate).TotalDays; if (daysInWork > 90) { claims.Add(CreateClaim("FTE", "1")); } else { claims.Add(CreateClaim("FTE", "0")); } return claims; } public static Claim CreateClaim(string type, string value) { return new Claim(type, value, ClaimValueTypes.String); } } |
The implementation is simple, the “GetClaims” method will take ApplicationUser object and returns a list of claims. Based on the “JoinDate” field it will add new claim named “FTE” and will assign a value of “1” if the user has been working for than 90 days, and a value of “0” if the user worked for less than this period. Notice how I’m using the method “CreateClaim” which returns a new instance of the claim.
This class can be used to enforce creating custom claims for the user based on the information related to her, you can add as many claims as you want here, but in our case we will add only a single claim.
Now we need to call the method “GetClaims” so the “FTE” claim will be associated with the authenticated user identity, to do this open class “CustomOAuthProvider” and in method “GrantResourceOwnerCredentials” add the highlighted line (line 7) as the code snippet below:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { //Code removed for brevity ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, "JWT"); oAuthIdentity.AddClaims(ExtendedClaimsProvider.GetClaims(user)); var ticket = new AuthenticationTicket(oAuthIdentity, null); context.Validated(ticket); } |
Notice how the established claims identity object “oAuthIdentity” has a method named “AddClaims” which accepts IEnumerable object of claims, now the new “FTE” claim is assigned to the authenticated user, but this is not enough to satisfy the criteria needed to issue the fictitious refund on orders, we need to make sure that the user is in “Admin” Role too.
To implement this we’ll create a new Role on the fly based on the claims assigned for the user, in other words we’ll create Roles from the Claims user assigned to, this Role will be named “IncidentResolvers”. And as we stated in the beginning of this post, the Roles eventually are considered as a Claim of type Role.
To do this add new class named “RolesFromClaims” under folder “Infrastructure” and paste the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class RolesFromClaims { public static IEnumerable<Claim> CreateRolesBasedOnClaims(ClaimsIdentity identity) { List<Claim> claims = new List<Claim>(); if (identity.HasClaim(c => c.Type == "FTE" && c.Value == "1") && identity.HasClaim(ClaimTypes.Role, "Admin")) { claims.Add(new Claim(ClaimTypes.Role, "IncidentResolvers")); } return claims; } } |
The implementation is self explanatory, we have created a method named “CreateRolesBasedOnClaims” which accepts the established identity object and returns a list of claims.
Inside this method we will check that the established identity for the authenticated user has a claim of type “FTE” with value “1”, as well that the identity contains a claim of type “Role” with value “Admin”, if those 2 conditions are met then; we will create a new claim of Type “Role” and give it a value of “IncidentResolvers”.
Last thing we need to do here is to assign this new set of claims to the established identity, so to do this open class “CustomOAuthProvider” again and in method “GrantResourceOwnerCredentials” add the highlighted line (line 9) as the code snippet below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { //Code removed for brevity ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, "JWT"); oAuthIdentity.AddClaims(ExtendedClaimsProvider.GetClaims(user)); oAuthIdentity.AddClaims(RolesFromClaims.CreateRolesBasedOnClaims(oAuthIdentity)); var ticket = new AuthenticationTicket(oAuthIdentity, null); context.Validated(ticket); } |
Now all the new claims which created on the fly are assigned to the established identity and once we call the method “context.Validated(ticket)”, all claims will get encoded in the JWT token, so to test this out let’s add fictitious controller named “OrdersController” under folder “Controllers” as the code below:
1 2 3 4 5 6 7 8 9 10 11 |
[RoutePrefix("api/orders")] public class OrdersController : ApiController { [Authorize(Roles = "IncidentResolvers")] [HttpPut] [Route("refund/{orderId}")] public IHttpActionResult RefundOrder([FromUri]string orderId) { return Ok(); } } |
Notice how we attribute the action “RefundOrder” with [Authorize(Roles = “IncidentResolvers”)] so only authenticated users with claim of type “Role” and has the value of “IncidentResolvers” can access this end point. To test this out you can issue HTTP PUT request to the URI “http://localhost/api/orders/refund/cxy-4456393” with an empty body.
As you noticed from the first method, we have depended on user information to create claims and kept the authorization more dynamic and flexible.
Keep in mind that you can add your access control business logic, and have finer grained control on authorization by implementing this logic into classes “ExtendedClaimsProvider” and “RolesFromClaims”.
Method 2: Creating custom Claims Authorization attribute
Another way to implement Claims Based Authorization is to create a custom authorization attribute which inherits from “AuthorizationFilterAttribute”, this authorize attribute will check directly the claims value and type for the established identity.
To do this let’s add new class named “ClaimsAuthorizationAttribute” under folder “Infrastructure” 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 |
public class ClaimsAuthorizationAttribute : AuthorizationFilterAttribute { public string ClaimType { get; set; } public string ClaimValue { get; set; } public override Task OnAuthorizationAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken) { var principal = actionContext.RequestContext.Principal as ClaimsPrincipal; if (!principal.Identity.IsAuthenticated) { actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized); return Task.FromResult<object>(null); } if (!(principal.HasClaim(x => x.Type == ClaimType && x.Value == ClaimValue))) { actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized); return Task.FromResult<object>(null); } //User is Authorized, complete execution return Task.FromResult<object>(null); } } |
What we’ve implemented here is the following:
- Created a new class named “ClaimsAuthorizationAttribute” which inherits from “AuthorizationFilterAttribute” and then override method “OnAuthorizationAsync”.
- Defined 2 properties “ClaimType” & “ClaimValue” which will be used as a setters when we use this custom authorize attribute.
- Inside method “OnAuthorizationAsync” we are casting the object “actionContext.RequestContext.Principal” to “ClaimsPrincipal” object and check if the user is authenticated.
- If the user is authenticated we’ll look into the claims established for this identity if it has the claim type and claim value.
- If the identity contains the same claim type and value; then we’ll consider the request authentic and complete the execution, other wist we’ll return 401 unauthorized status.
To test the new custom authorization attribute, we’ll add new method to the “OrdersController” as the code below:
1 2 3 4 5 6 |
[ClaimsAuthorization(ClaimType="FTE", ClaimValue="1")] [Route("")] public IHttpActionResult Get() { return Ok(); } |
Notice how we decorated the “Get()” method with the “[ClaimsAuthorization(ClaimType=”FTE”, ClaimValue=”1″)]” attribute, so any user has the claim “FTE” with value “1” can access this protected end point.
Method 3: Managing user claims by using the “ApplicationUserManager” APIs
The last method we want to explore here is to use the “ApplicationUserManager” claims related API to manage user claims and store them in ASP.NET Identity related tables “AspNetUserClaims”.
In the previous two methods we’ve created claims for the user on the fly, but in method 3 we will see how we can add/remove claims for a certain user.
The “ApplicationUserManager” class comes with a set of predefined APIs which makes dealing and managing claims simple, the APIs that we’ll use in this post are listed in the table below:
Method Name | Usage |
---|---|
AddClaimAsync(id, claim) | Create a new claim for specified user id |
RemoveClaimAsync(id, claim) | Remove claim from specified user if claim type and value match |
GetClaimsAsync(id) | Return IEnumerable of claims based on specified user id |
To use those APIs let’s add 2 new methods to the “AccountsController”, the first method “AssignClaimsToUser” will be responsible to add new claims for specified user, and the second method “RemoveClaimsFromUser” will remove claims from a specified user as 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 |
[Authorize(Roles = "Admin")] [Route("user/{id:guid}/assignclaims")] [HttpPut] public async Task<IHttpActionResult> AssignClaimsToUser([FromUri] string id, [FromBody] List<ClaimBindingModel> claimsToAssign) { if (!ModelState.IsValid) { return BadRequest(ModelState); } var appUser = await this.AppUserManager.FindByIdAsync(id); if (appUser == null) { return NotFound(); } foreach (ClaimBindingModel claimModel in claimsToAssign) { if (appUser.Claims.Any(c => c.ClaimType == claimModel.Type)) { await this.AppUserManager.RemoveClaimAsync(id, ExtendedClaimsProvider.CreateClaim(claimModel.Type, claimModel.Value)); } await this.AppUserManager.AddClaimAsync(id, ExtendedClaimsProvider.CreateClaim(claimModel.Type, claimModel.Value)); } return Ok(); } [Authorize(Roles = "Admin")] [Route("user/{id:guid}/removeclaims")] [HttpPut] public async Task<IHttpActionResult> RemoveClaimsFromUser([FromUri] string id, [FromBody] List<ClaimBindingModel> claimsToRemove) { if (!ModelState.IsValid) { return BadRequest(ModelState); } var appUser = await this.AppUserManager.FindByIdAsync(id); if (appUser == null) { return NotFound(); } foreach (ClaimBindingModel claimModel in claimsToRemove) { if (appUser.Claims.Any(c => c.ClaimType == claimModel.Type)) { await this.AppUserManager.RemoveClaimAsync(id, ExtendedClaimsProvider.CreateClaim(claimModel.Type, claimModel.Value)); } } return Ok(); } |
The implementation for both methods is very identical, as you noticed we are only allowing users in “Admin” role to access those endpoints, then we are specifying the UserId and a list of the claims that will be add or removed for this user.
Then we are making sure that user specified exists in our system before trying to do any operation on the user.
In case we are adding a new claim for the user, we will check if the user has the same claim type before trying to add it, add if it exists before we’ll remove this claim and add it again with the new claim value.
The same applies when we try to remove a claim from the user, notice that methods “AddClaimAsync” and “RemoveClaimAsync” will save the claims permanently in our SQL data-store in table “AspNetUserClaims”.
Do not forget to add the “ClaimBindingModel” under folder “Models” which acts as our POCO class when we are sending the claims from our front-end application, the class will contain the code below:
1 2 3 4 5 6 7 8 9 10 |
public class ClaimBindingModel { [Required] [Display(Name = "Claim Type")] public string Type { get; set; } [Required] [Display(Name = "Claim Value")] public string Value { get; set; } } |
There is no extra steps needed in order to pull those claims from the SQL data-store when establishing the user identity, thanks for the method “CreateIdentityAsync” which is responsible to pull all the claims for the user. We have already implemented this and it can be checked by visiting the highlighted LOC.
To test those methods all you need to do is to issue HTTP PUT request to the URI: “http://localhost:59822/api/accounts/user/{UserId}/assignclaims” and “http://localhost:59822/api/accounts/user/{UserId}/removeclaims” as the request images below:
That’s it for now folks about implementing Authorization using Claims.
In the next post we’ll build a simple AngularJS application which connects all those posts together, this post should be interesting 🙂
Thank you for your tutorials. They’re like crack to me. I’m jones-ing for part 6. I need a fix!
You are welcome.
Hello Joudeh. I have a question. Instead of using ModelFactory it would not be easier to create a generic repository?
You can do this, but do not expose your EF entities to consumers, it is always better to create your own business domain models and send them back to the front end. You can use AutoMapper as well.
Hi Taiseer
Great useful and valuable post .
I have created my application using all the steps.
I have published the application in one server with different subdomains(one for web api, one for angularjs app).
Here comes my issue as after login when i click to different pages via link to view it gives me 401 error! (ex: to view order page and then manage page and then again order page it gives error)
I’ve tried and but couldn’t get idea to resolve it !
Can you please help me.
Thank you.
Hi Kian,
Did you make sure that the token is being sent with each request? You need to start developer tools and watch the requests sent from UI to the API. As well make sure tat you configured CORS correctly.
Let me know if this helps.
Hi Taiseer,
Thank you for your valuable reply.
I have check for each request the token is sent properly.
Do i need to configure CORS for each api controller class ?
I have set the application in single domain but the problem is the same of 401 error.
And also could;t make the call from android app !
any spl changes need to make on server ?
m just clueless why this giving me error of 401 which is not in my local iis publish app
Please help me out.
Thank you.
Hi Taiseer
Great useful and valuable post.
How can I add OrderController with CRUD pattern or Repository pattern?
I try to merge this post with https://bitoftech.net/2013/11/25/applying-repository-pattern-data-access-layer
but it not success.
Could you give me some advise?
Thank you,
Hi thanks for the tutorial , did you make the angular part?
Great stuff these articles! Looking forward to more like this!
You are welcome, happy to hear this!
When will your Angular example be available?
Hi Taiseer. I’ve been following your tutorials and i must say i feel like i went back in time to found my favourite teacher… you explain very well.
I leave this reply because i’ve followed all your steps and everything worked well for me, until i moved the project to another directory. Now seems like my valid JWT token is not being recognized by the Identity middleware.
I tried several times and couldn’t get the token to work, so i rolled back the project to the PART 4 version, where only Roles Based is implemented, but still getting the response Unauthorized with content {“message”:”Authorization has been denied for this request.”} when i try to consume “http://localhost/api/claims”.
When i get another token it works fine consuming “http://localhost/api/accounts/users”, but at the moment i try to consume “http://localhost/api/claims” and get as response Unauthorized {“message”:”Authorization has been denied for this request.”}, all following calls to other endpoints get Unauthorized.
Do you know if this is a bug?
I would like to append that i implemented the ClaimsController, as the beginning of this tutorial.
Thanks.
Hi, happy to hear that posts were clear to implement.
I do not think there is a bug, but I guess the issuer property is not matching the URL for your issuer after you moved it, try to decode the JWT token using jwt.io and check the claims inside it.
Sorry, i forgot to tell that i indeed used JWT.io and iss was ok. By the way i am running the project using inside Visual Studio IIS Express.
Any thoughts why AccountsController accept the JWT and ClaimsController rejects?
Hello Taiseer, Thank you for your work, it really helped me to understand how Authentication works with WebApi. And I believe not only me waiting for the last post ;).
Wish you inspiration for new articles.
Thank you for your sweet comment, happy to help 🙂
Hi Taiseer,
thanks very much for this superb series that shows how to build the API for Claims Authorization with ASP.NET Identity. Everything works fine via PostMan, but now I want to be able to create an Asp.Net web solution that will be able to interface with this AspNetIdentity project to enable users to login (and change password etc.) and for me to then be able to control what is displayed in the aspx pages based on the user’s roles.
I’m unsure as to how I can interact with the API (such as /oauth/token for example) via the code-behind an aspx login page, and how to get the User object as such, and the user’s Roles.
Any help you can provide with this would be much appreciated.
With regards, Ian
Hi Ian,
Happy to hear that posts are useful, you need to use an Http Client so start building http requests and communicate with the Api, this post is really useful and shows how you can authenticate, get data, etc..
Hope this will help!
Hi, compliments for all 5 posts, very very interesting. but….the last (part. 6)? I don’t find it.. 🙁
Sorry about this 🙁
Hi,
The tutorial was brilliant, I’m experiencing an issue where the claims aren’t being written to the DB.
await this.AppUserManager.AddClaimAsync(id, ExtendedClaimsProvider.CreateClaim(claimModel.Type, claimModel.Value));
It passes this line but doesn’t to anything, I’m not sure why it’s not working.
Thanks in advance
I’ve just run the source code and it’s working, I’ll find out whats wrong.
Hi Taiseer,
All the five parts are well explained with the required screenshots. It would be great if you could also show us how to implement the Angular application to consume the API.
Thanks,
Ashwin
Thank you, I’m working on newest tutorial now to use the new ASP.Net Core 1.0
Awesome series of posts on Authentication! Your blog will be a first stop source for me from now on. I’ve followed along and learned a huge amount about WebApi and Authentication that I did not know. I’m trying to put what you’ve so graciously taught into practice, but I have a difficult scenario which isn’t quite covered in your series (at least not that I understood), and I can’t find an example like it anywhere else.
I have a scenario where two totally separate web sites (different machines, domains, etc) have basically a parent – child relationship. Visitors will not be coming to my site, the child in the relationship, directly as there is no public content. If they do come directly, I’ll have to redirect them to the parent immediately. In my scenario, Visitors will visit the parent site, log in, and then get a link to my site. They should then be able to click that link and use my site without having to authenticate. Does that make sense?
I don’t want my site (the child) to have any knowledge about the user except what comes to it in the token. I don’t want to collect credentials and call the other server from my site. I want to get the token that has already been placed there by the parent. Is that even possible, and if so, can you point me in the right direction to do this?
Thanks very, very much for any help you can provide, and again thank you for this series.
Hi Taiseer,
Truly this is a great series. I have been able to follow it step by step and indeed learnt a lot. Where I had challenges your responses on the comments came in handy. I have basic idea of how to create a client to communicate wit the API but for a better understanding am hoping to see your final post on this.
Thanks a lot.
Hi Jeff, you are most welcome. Happy to hear that posts were useful and easy to understand.
Hi Taiseer,
Is there a chance we will see the AngularJS front end in action tih this backend?
🙁 I apologise for not posting this post yet, I will try my best to finalize it soon.
Hey Tarsier, thx for all the work in this very good tutorial. Looking forward to part 6! (can’t wait… 😉
Hi Ron, you are most welcome. Thanks for your message.
Hi Taiseer,
I’m reading Your parts of this tutorial and I must say it is amazing. It is complex, but You write about is in such way I can follow easily.
I’ve noticed that last part is missing, I’d really would like to see how You integrate with Angular.
Hopefully You’ll be able to publish it soon 🙂
Hi Tom, thanks for your message I will do my best to publish it soon. Thank you
This tutorial is so great! I am so happy you decided to use ASP.NET core for part 6 since I am building a project using ASP.NET core too.
Are you going to use Angular2 too?
Hi Roj, I will be working on another series posts cover asp.net core 1.0 and Angular 2 soon.
Hi Taiseer – is the Core series still in the pipeline?
This was an amazing tutorial. I enjoyed it from part 1 to now. Very clear explanations. Keep up the great work!
You are welcome Brent, thanks for your message!
thank you,
i followed your post and when deployed webapi to azure i get issue that the webapi not grant the jwt token send in the request header and always give me “Authorization has been denied for this request”
i coded exp = 120 minutes and then i checked login by postman i always get new toke for every post
i don’t know the reason for that , any help appreciated.
Check that client id, issuer, and secrets are matching. That is the only reason I can think of.
Is it possible to peak in on the magic? What I mean is I want to find out what happens between the time the http request arrives and when my claims attribute gets a crack at it. In the very first line of OnAuthorizationAsync immediately casts “actionContext.RequestContext.Principal” to a ClaimsPrincipal where we find out whether the user “IsAuthorized” and what the claims in the token are. So obviously the token has already been unpacked and the identity of the user has already been confirmed or denied. If the user was denied there is no way for us to learn why. The principal is mostly an empty object with IsAuthorized set to false. So, again, I ask…is there any way to see what happens to the token and why it may have resulted in a failure?
I should add I did find out once that this could happen because I had an audience_id mismatch. You can’t expect the token be decrypted with a different audience_id than was used to encrypt it. That is not what is happening to me now and I have no idea how to _discover_ more information. Any tips would be greatly appreciated! Marcus
Would you say it is not important to be able to see “behind the curtain” to reveal the code that decrypts the token and populates the identity principal? The only way this would not be necessary is if all the problems are traceable to inconsistent “client id, issuer, and secrets”?
Hi Taiseer,
Great tutorial series, I think this is simply the best ASP.NET Identity tutorial on the web.
Will part 6 come any time soon? 🙂
You are welcome. This had been pending for one year 🙁 better to write it using Angular 2 maybe!
The life keeps us really busy sometimes, I totally understand. I’m eager to see your next tutorial. Take care!
You may post Angular 1 version. Not everyone is moving to Angular 2 already 🙂
Hi Taiseer,
What about the requirement to use Windows authentication (but with custom authorization algorithm)? I’d still like to create all services in RESTful way utilizing best practices and avoid using windows/basic authentication in Web API.
Any advice/examples on how to pull this off?
I also vote for a AngularJS 1.5X version for part 6 in this series… partially because my project is currently using this version and partially because I’m more intrigued by Aureila than Angular 2 right now 🙂
Great work – please keep it coming!
Great series. Learned a lot. Any idea when you will post part 6 – AngularJS Authentication and Authorization with ASP.NET Web API and Identity 2.1 ?
Ditto, Would really like to read part 6. I assume that would add support for External Authorization like zapier, microsoft flow, etc.
Great tutorials – thank you.
I have a question regarding the ClaimsAuthorization Action Filter.
What if I need a controller to allow users with multiple claims rather than only one?
For instance if I do this, the user needs to have both Claims to be allowed to use the cotroller, when I only need the user to have one them:
[ClaimsAuthorization(ClaimType=”Role”, ClaimValue=”edit”)]
[ClaimsAuthorization(ClaimType=”Role”, ClaimValue=”view”)]
public class MyController()
{
}
Is there any way around this?
Thanks
You can sent the claim value to and claim type to accept comma separated value and you do the implementation there.
Great tutorials. I have been following your tutorials for a little while now. I have a quick question. I have an asp web api backend with angular front end app from your previous tutorial. Everything works great. I have one specific situation where I need to be able to direct a user from the front end app to a server side mvc view page. Since it is not possible to pass authentication headers on a redirect from javascript, I was wondering how I can configure the customoauthprovider to accept the token from the url. This way I can append the users token http://www.example.com/?token=** to the url and can be authorized to access the one mvc view. It wouldn’t be the end of the world if I allowed anonymous on this mvc view, however I need the user logged in to store data in the user claim. Any thoughts on how I can configure the Custom provider to accept the token from the url for this one request? Thank you in advance, I need help.
Hi, Nice article thanks for that. Is is possible to convert a Form[“Auth”] value to ClaimPrincipal? I have a some scenarios where i can’t set headers in the request. In this case i need to override the claims from HttpContextBase.
Hello, Nice article. I am unable to view the last post of the series. Am I missing something, can anyone forward link please.Thanks!
Hi Taiseer,
I have a question about the claims.Dose these claims will be encrypted into a token and send to client?
If so,How to deal with claims update? Cause some time user’s email or role would change.
Thanks
Hi Lee,
The claims inside the token, and change on the value of any claim means you need to generate new token, You can’t update a token. Unless you are using something called reference tokens not self contained tokens.
Great post, helped a lot but this works great for a small number of claims, what if the claims become too many to include in a token?
For example, if you implement a permission based security, like an Admin role that can do so and so, how would you go about breaking apart your claims?
If you let the api manage that through different permission based endpoints, wouldn’t that defeat the purpose of claims?
Thanks for the reply,
Hi, great article!
I have a question about some of the methods in this project, the ones that receive data like this:
public async Task AssignRolesToUser([FromUri]string id, [FromBody]string[] rolesToAssign)
I can’t for the life of me make rolesToAssign catch and bind the roles, it’s either null or string{0}, I’m using ExtJs ajax calls to test this out but like I mentioned, no luck -_-. The id does catch the value.
Got any ideas?
Here’s how I’m testing it:
var arrayRoles = [‘Admin’, ‘SuperAdmin’];
var val = {
rolesToAssign: arrayRoles
};
Ext.Ajax.request({
method: ‘PUT’,
url: url,
headers: {
‘Content-Type’: ‘application/json’,
‘Accept’: ‘application/json’
},
jsonData: val,
success: function (response) {
},
failure: function (form, result) {
}
});
Hi Raul,
Can you try to use a REST client (POSTMan) at the beginning to shape your request and make sure you are building the desired JSON request which binds to the method. It seems your issue in the ExtJs library. If it didn’t work please drop a question on StackOverflow.
Great post!
I have been following this site since February 11, 2015 –all for this post “AngularJS Authentication and Authorization with ASP.NET Web API and Identity 2.1 – Part 6” –I’ve been waiting for that post for more than 1 year but it seems like the author forgot about it… T_T
Sorry Alex about this. things drafter since the last year. But I’m working now on couple of posts about Azure AD B2C, the new way that Microsoft is using for authentication in modern apps 🙂
Amazing article. I’ve learned so much. Thank you. We’re all eagerly awaiting that final post.
I’m already trying to consume the web Api using MVC 5, which is a new technology to me. I know that the AngularJS project will clarify a lot of things to me and I’m checking everyday if you’ve posted the article.
Can you give us a clue as to when that will be? .. Again, an absolutely brilliant series of articles that you’ve put together.
Another fabulous tutorial from Taiseer. You’re awesome! Thanks for the great work!
You are welcome, thanks for your message 🙂
Thanks to this project. I am trying unsuccessfully to convert Angular 2, now that it was officially released.
You’re going to update the application?
Hi Lorenzo,
I didn’t play with Angular 2, so it is hard for me to convert it. Sorry about this.
I tried your first part, word for word, but I am getting a 404 File not Found error when I try to use your testing links. I am sure I am using the correct localhost port.
I put break points thought out the project and NONE of them get hit when I attempt to call the API though Chrome app Postman.
So what have you missed? Do we need a global.asax file to kick off the API?
Found the problem. Since I added the project to an existing solution, the solutions properties did not have the multiple startup projects set. This is odd since IIS Express showed the port number active from the systray icon, but the project was not starting at all.
Set the Action to start and my breakpoints are getting hit. ARGH!! Noob mistake.
just wondering why this article
AngularJS Authentication and Authorization with ASP.NET Web API and Identity 2.1 – Part 6 never came up as its past
6 months?? not good at all leaving your readers hangup.
from where i can create AudienceSecret value
Hello Salem,
As far as I remember this exists in the Seed Method of the entity framework.
Thanks sir ,
Eagerly waiting for the 6th part . These series are the most popular among developers I saw many stackoverflow developers are referencing your blog. thank you so much again Tai
seer
It’s a very helpful series of posts! You opened my eyes! Thank you very much, Taiseer!!!
As I undersand about AngularJs client, it should be similar you described in one of your previous posts: https://bitoftech.net/2014/06/09/angularjs-token-authentication-using-asp-net-web-api-2-owin-asp-net-identity/
But one issue I can’t understand: Where client has to store ClientId or other sensitive information?
Thank you again!!!
Thank you it help me a lot m but i have problem i upload my API on the GoDaddy server and the token expire too Fast i put token expire After a month and it work fine on the local host but on the server i t take short time minuets
Hi,
It really amazing to see such a great stuff revealed, but I am still unable to find where obtained token are being scanned in resource server. Plz mentioned the name of method/action.
Hello,
thanks for this great tutorial…
For the first time I get a better understanding of the identity system!
But I have some questions about the claims thing…
Clear for me is that these claims are dynamic and I can store any userinformation there.
But why you store a phone number and the gender there? (postman example)
This would be make more sense for saving it in the user table?
And why creating claims for roles, when I can create and assign roles for the specific user?
I know at least these roles and infos are saved in claims to, but why use it directly?
It not more clear to save these things directly?
bye
Markus
Hello Markus, thanks for your comment.
Regarding storing the phone number and gender, this was for demo purposes, you will for sure store those claims in the DB too. I remember in a previous project I worked on that I stored the phone number in the claims as I needed this information in all the requests I sent, so instead of reaching the DB on each request to get the phone number by user id I get the mobile number from the token.
Can you elaborate more on the claims for roles question? I didn’t get that.
Excellent tutorials mate…
Not only they helped me crack some issues but also grab a few new concepts as well.
Looking forward to future ones.
Cheers !!!
You are most welcome Kushal, happy to hear it was that good 🙂
Hello Tayseer Joudeh,
I hope you are doing great!!!
All your posts are awesome, but there are some readers (including me), that are still waiting about the 6th part of this post, it would be really helpfull if you finish it. Again, thanks for all your work, it’s the best!!!
Thank you Alian, I know this has been for a while 🙁 but if you an urgent need for this, there is Plural Sight course which covers this 6 part deeply, I recommend you watching it.
Many thank for your help!
Please can we have the Plural Sight link for this course?
Thank!
Hello Kamsu,
This course and this course will be very useful.
I followed the tutorial to decouple the api and ran into an issue with the custom jwt format. in the resource api I need to be able to implement the unprotect method I believe in order for it to understand the token. Am I right? How can I implement this? I’m at a total road block with this lol
Please disregard. I found a hint that I was on the wrong path and instead moved the ConfigureOAuthTokenConsumption method over to my resource api and boom! happy dances all around. Thank you for the hard work on this. It has taught me well.
You are welcome, happy to hear is its working successfully 🙂
I’ve been following through all 5 parts and they have been very helpful, so many many thanks. This is starting to make sense now. 🙂
I encountered an issue with assigning claims to a user. I can create custom claims for a user that are stored in the Claims table. However when I assign a new set of claims, the claims are not removed from the table and added once again.
Upon debugging I noticed that the call to UserManager.FindByIsAsync(id) does not return any values within the Claims property. So the check to remove existing claims is by-passed.
Any ideas here?
Hi peter,
That is strange, currently, I do not have any ideas on this, but this is related to EF and UserManager, are you sure the claims are not deleted before trying to retrieve them?
Hi Taiseer,
Awesome posts! Helps alot!
But i’m stuck with exactly the same problem as Peter. No claims are retrieved from the database by EF…
Any ideas?
Again thanks you so much sir ,still eagerly waiting for the sixth part Taiseer …
How is it possible to store JWT in cookie?
Excellent set of articles, thank you very much for taking the time to author them. Had no problem following them with the odd reference to the source code project for the correct using statements where there was a namespace ambiguity.
Feel I know a lot more about JWT and OAuth now and looking forward to Part 6
You are welcome Clarkio, happy to hear this was easy to follow with.
Wonderful series. Thank you for putting these all together.
You are welcome, happy to hear this 🙂
Hi Taiseer. Thanks for all these really good guides. They are all very helpful for a rookie webdev as me.
In your last part, cant you add some extra model classes (db tables) with one-to-many and many-to-many relationship with the ApplicationUser class.
Hi John, this is purely related to EF configuration, maybe this post will be useful for your case.
10x for this guide its very helpfull.
is it OK to use this code now ?
most of the nuggets are preety old and may have vulnerabilities ?
*we cant update them its doesnt compile
actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
System.Net.Http.HttpRequestMessage downs not contains CreateResponse
i forget to include using System.Net.Http; now its resolved.
Hi Taiseer,
Thanks for the great write up. I have been following your write up because I find it difficult to understand this identity server thing as a whole. I am tasked to build a custom identity server that can be used to serve multiple applications ( it will identify users and grant them access to applications to have access to).
My idea is to use your implementation with the Claims Authorization bit of it – don’t know if that is a good strategy. Also been looking forward to the part 6 of your tutorial. As I would like to create clients (mvc applications) that will be served by my idneity server implementation (SOMETHING like what your tutorial has taught me)
Thanks and looking forward to your reply.
Thanks very much. Waiting for Part 6!
I am new in Asp.Net Web Api. Please help me to add to this project:
– API for POST the orders: save it into SQL database with some info such as: Order ID, User Id (who login and add order) , Order Name, Amount of the Order , Date Time of the Order,Notes, …
– API for GET: return details of the order of current user (who login)
– API for PUT: edit an order
– API for DELETE: delete an order
Thanks!
HI, wao thank you for an amazing guide into leveraging Identity. Tried a couple before finding your awesome tutorial. I just have one question. Hos I could add angular 2 support to it. I know how to manage the frontend part I just need help setting up the api to host the angular 2 app inside an specific folder Ej: Resources/*Angular2AppFolders*
THANKS IN ADVANCED
Btw: Also looking forward to part 6.
Taiseer, whatever happened to the promised Part 6 in this series? I was looking forward to seeing it all tied together, especially since I’m being tasked with the exact same requirements. Biggest thing for me is setting up a claim manager using Angular as we have a decoupled UI.
This tutorial was so unbelievably clear, with no error whatsoever. I have searched the web time and time again and this is by far the best tutorial I have encountered. Smooth implementation and if anything went wrong the answer was either in the comments or I could just have a look at the source code on GitHub for clarification. I just want to thank you very much for the time you took and I appreciate the time you have put into this to get this done so clear and easy to follow.
Thanks Taiseer for such enlightening articles. How can we apply claims in our Resource Server (separate API from Authorization server) ? I am not able to use ClaimsAuthorizationAttribute in my Resource Server’s. Please suggest how to do it.
Also, how can we communicate from one resource server to another without involving client ?
Thanks!
Hello and thanks. Your posts is the most complete that I found on internet, with asp.net identity, jwt and all explanations around roles, claims and etc. Very helpful.
You will make the part 6?
I want to make a mvc project to consumes this api, do you have any example for this?
Thanks again
your posts are*, im sorry, english is not my native language.
when I said that I want to make a mvc project, I means that I want to create view for the api, don’t need to be a whole mvc project, just the views inside the api its fits.
Your all tutorials are great to me. Please write something on ASP.NET Core with JWT.
Taiseer, what a wonderful & detailed explanation. I thoroughly enjoyed reading all articles of this series. Eagerly waiting for the last one to see how have you used token in Angular client.
Hi @tjoudeh,
Greaat posts! Any chance you can let us know when part 6 is coming?
very insightful and educational, please keep up the good work.
Hello,
Any news regarding the part 6???
Great job!
Taiseer, what a wonderful & detailed explanation. I thoroughly enjoyed reading all articles of this series. Eagerly waiting for the last one to see how have you used token in Angular client.
This is a great article! Thank you!
Glad yo hear 🙏