ASP.NET Web API Claims Authorization with ASP.NET Identity 2.1 Part 5 (by TAISEER)
https://www.cnblogs.com/KimmyLee/p/6430474.html
https://www.cnblogs.com/rocketRobin/p/9077523.html
http://bitoftech.net/2015/03/31/asp-net-web-api-claims-authorization-with-asp-net-identity-2-1/
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:
[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:
[
{"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
Method 2: Creating custom Claims Authorization attribute
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:
[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:
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.
ASP.NET Web API Claims Authorization with ASP.NET Identity 2.1 Part 5 (by TAISEER)的更多相关文章
- 【ASP.NET Web API教程】1 ASP.NET Web API入门
原文 [ASP.NET Web API教程]1 ASP.NET Web API入门 Getting Started with ASP.NET Web API第1章 ASP.NET Web API入门 ...
- Announcing the Release of ASP.NET MVC 5.1, ASP.NET Web API 2.1 and ASP.NET Web Pages 3.1 for VS2012
The NuGet packages for ASP.NET MVC 5.1, ASP.NET Web API 2.1 and ASP.NET Web Pages 3.1 are now live o ...
- Implement JSON Web Tokens Authentication in ASP.NET Web API and Identity 2.1 Part 3 (by TAISEER)
http://bitoftech.net/2015/02/16/implement-oauth-json-web-tokens-authentication-in-asp-net-web-api-an ...
- 杂项:ASP.NET Web API
ylbtech-杂项:ASP.NET Web API ASP.NET Web API 是一种框架,用于轻松构建可以访问多种客户端(包括浏览器和移动设备)的 HTTP 服务. ASP.NET Web A ...
- ASP.NET Web API 控制器执行过程(一)
ASP.NET Web API 控制器执行过程(一) 前言 前面两篇讲解了控制器的创建过程,只是从框架源码的角度去简单的了解,在控制器创建过后所执行的过程也是尤为重要的,本篇就来简单的说明一下控制器在 ...
- ASP.NET Web API WebHost宿主环境中管道、路由
ASP.NET Web API WebHost宿主环境中管道.路由 前言 上篇中说到ASP.NET Web API框架在SelfHost环境中管道.路由的一个形态,本篇就来说明一下在WebHost环境 ...
- ASP.NET Web API Selfhost宿主环境中管道、路由
ASP.NET Web API Selfhost宿主环境中管道.路由 前言 前面的几个篇幅对Web API中的路由和管道进行了简单的介绍并没有详细的去说明一些什么,然而ASP.NET Web API这 ...
- ASP.NET Web API 管道模型
ASP.NET Web API 管道模型 前言 ASP.NET Web API是一个独立的框架,也有着自己的一套消息处理管道,不管是在WebHost宿主环境还是在SelfHost宿主环境请求和响应都是 ...
- ASP.NET Web API 路由对象介绍
ASP.NET Web API 路由对象介绍 前言 在ASP.NET.ASP.NET MVC和ASP.NET Web API这些框架中都会发现有路由的身影,它们的原理都差不多,只不过在不同的环境下作了 ...
随机推荐
- 常用web对比
Apache与nginx对比 nginx相对于apache的优点: 1.轻量级同样启动WEB服务,比apache占用更少的内存以及资源: 2.抗并发性能高,核心区别在于apache是同步多线程模型.一 ...
- 2017 Multi-University Training Contest - Team 2——HDU6050 Funny Function
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6050 题意:题目很短自己看吧, 就是这个递推式子,说的很清楚了,让你求F(m,1).题解里面分什么奇偶 ...
- 对于应用需要记录某个方法耗时的场景,必须使用clock_gettime传入CLOCK_MONOTONIC参数,该参数获得的是自系统开机起单调递增的纳秒级别精度时钟,相比gettimeofday精度提高不少,并且不受NTP等外部服务影响,能准确更准确来统计耗时(java中对应的是System.nanoTime),也就是说所有使用gettimeofday来统计耗时(java中是System.curre
对于应用需要记录某个方法耗时的场景,必须使用clock_gettime传入CLOCK_MONOTONIC参数,该参数获得的是自系统开机起单调递增的纳秒级别精度时钟,相比gettimeofday精度提高 ...
- Whether to hide the cookie from JavaScript
w禁用js访问特定cookie. https://codeigniter.com/userguide3/helpers/cookie_helper.html $this->load->he ...
- apt-get 报 The following signatures were invalid: KEYEXPIRED 错误
apt-get 原理: 参考:https://blog.csdn.net/a13526758473/article/details/79247478 apt对它所管理的每一个程序包都有一对公钥和私钥, ...
- Linux which命令
which常用与查看并显示指定命令的绝对路径,使用which命令,还可以看到某个系统命令是否存在,以及执行的到底是哪一个位置的命令. 1.用法 which [命令] 2.实例 1)查看 ls 命令的绝 ...
- tools-eclipse-002-常用插件
1.spring 查看eclipse版本 下载对应版本插件包Spring Tool Sute 地址:http://spring.io/tools/sts/all 离线包只列举了最新的,如图, 如果ec ...
- 实时流计算Spark Streaming原理介绍
1.Spark Streaming简介 1.1 概述 Spark Streaming 是Spark核心API的一个扩展,可以实现高吞吐量的.具备容错机制的实时流数据的处理.支持从多种数据源获取数据,包 ...
- 《FLASH PROGRAMMING 那些事》总结
注明来自 http://www.ssdfans.com/?p=5589 以MLC为例: 对FGF(Floating Gate Flash)技术的,MLC programming一般分两步走:先prog ...
- SQL Server 自定义函数(Function)——参数默认值
sql server 自定义函数分为三种类型:标量函数(Scalar Function).内嵌表值函数(Inline Function).多声明表值函数(Multi-Statement Functio ...