实现Client Credentials Grant
[OAuth]基于DotNetOpenAuth实现Client Credentials Grant
Client Credentials Grant是指直接由Client向Authorization Server请求access token,无需用户(Resource Owner)的授权。比如我们提供OpenAPI让大家可以获取园子首页最新随笔,只需验证一下Client是否有权限调用该API,不需要用户的授权。而如果Client需要进行发布博客的操作,就需要用户的授权,这时就要采用Authorization Code Grant。
DotNetOpenAuth是当前做得做好的基于.NET的OAuth开源实现,项目网址:https://github.com/DotNetOpenAuth。
Client Credentials Grant的流程图如下(图片1来源,图片2来源):


一、Client向Authorization Server请求access token
主要操作如下:
1. 由client_id和client_secret构建出credentials。
2. 将credentials以http basic authentication的方式发送给Authorization Server。
3. 从Authorization Server的响应中提取access token
Client的实现代码如下:

public async Task<ActionResult> SiteHome()
{
var client_id = "m.cnblogs.com";
var client_secret = "20140213";
var credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(client_id + ":" + client_secret)); var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
var httpContent = new FormUrlEncodedContent(new
Dictionary<string, string>
{
{"grant_type", "client_credentials"}
}); var response = await httpClient.PostAsync("https://authserver.open.cnblogs.com/oauth/token", httpContent); var responseContent = await response.Content.ReadAsStringAsync();
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
var accessToken = JObject.Parse(responseContent)["access_token"].ToString();
return Content("AccessToken: " + accessToken);
}
else
{
return Content(responseContent);
}
}

二、Authorization Server验证Client,发放access token
主要操作如下:
1. Authorization Server通过IAuthorizationServerHost.GetClient()获取当前Client。
2. Authorization Server通过IClientDescription.IsValidClientSecret()验证当前Client。
3. 验证通过后,将access token包含在响应中发送给Client。
主要实现代码如下(基于ASP.NET MVC):
1. Authorization Server中Client实体类的实现代码(关键代码是IsValidClientSecret()的实现):

public class Client : IClientDescription
{
public string Id { get; set; } public string Secret { get; set; } public Uri DefaultCallback
{
get { throw new NotImplementedException(); }
} private ClientType _clientType;
public ClientType ClientType
{
get { return _clientType; }
set { _clientType = value; }
} public bool HasNonEmptySecret
{
get { throw new NotImplementedException(); }
} public bool IsCallbackAllowed(Uri callback)
{
throw new NotImplementedException();
} public bool IsValidClientSecret(string secret)
{
return this.Secret == secret;
}
}

AuthorizationServerHost的代码(关键代码是GetClient()与CreateAccessToken()的实现):

public class AuthorizationServerHost : IAuthorizationServerHost
{
public static readonly ICryptoKeyStore HardCodedCryptoKeyStore = new HardCodedKeyCryptoKeyStore("..."); public IClientDescription GetClient(string clientIdentifier)
{
return ServiceLocator.GetService<IClientService>().GetClient(clientIdentifier);
} public AccessTokenResult CreateAccessToken(IAccessTokenRequest accessTokenRequestMessage)
{
var accessToken = new AuthorizationServerAccessToken
{
Lifetime = TimeSpan.FromHours(10),
SymmetricKeyStore = this.CryptoKeyStore,
};
var result = new AccessTokenResult(accessToken);
return result;
} public AutomatedAuthorizationCheckResponse CheckAuthorizeClientCredentialsGrant(IAccessTokenRequest accessRequest)
{
//...
} public AutomatedUserAuthorizationCheckResponse CheckAuthorizeResourceOwnerCredentialGrant
(string userName, string password, IAccessTokenRequest accessRequest)
{
//...
} public DotNetOpenAuth.Messaging.Bindings.ICryptoKeyStore CryptoKeyStore
{
get { return HardCodedCryptoKeyStore; }
} public bool IsAuthorizationValid(IAuthorizationDescription authorization)
{
return true;
} public INonceStore NonceStore
{
get { return null; }
}
}

三、Client通过access token调用Resource Server上的API
主要实现代码如下:

public async Task<ActionResult> HomePosts(string blogApp)
{
//获取access token的代码见第1部分
//...
var accessToken = JObject.Parse(responseContent)["access_token"].ToString();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
response = await httpClient.GetAsync("https://api.open.cnblogs.com/blog/posts/sitehome");
return Content(await response.Content.ReadAsStringAsync());
}

四、Resource Server验证Client的access token,响应Client的API调用请求
主要实现代码如下(基于ASP.NET Web API):
1. 通过MessageHandler统一验证access token

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MessageHandlers.Add(new BearerTokenHandler());
}
}

2. BearerTokenHandler的实现代码(来自DotNetOpenAuth的示例代码):

public class BearerTokenHandler : DelegatingHandler
{
protected override async System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
if (request.Headers.Authorization != null && request.Headers.Authorization.Scheme == "Bearer")
{
var resourceServer = new DotNetOpenAuth.OAuth2.ResourceServer
(new StandardAccessTokenAnalyzer
(AuthorizationServerHost.HardCodedCryptoKeyStore)); var principal = await resourceServer.GetPrincipalAsync(request, cancellationToken);
HttpContext.Current.User = principal;
Thread.CurrentPrincipal = principal;
} return await base.SendAsync(request, cancellationToken);
}
}

3. Web API的示例实现代码:

public class PostsController : ApiController
{
[Route("blog/posts/sitehome")]
public async Task<IEnumerable<string>> GetSiteHome()
{
return new string[] { User.Identity.Name };
}
}

四、Client得到Resouce Server的响应结果
根据上面的Resouce Server中Web API的示例实现代码,得到的结果是:
["client:m.cnblogs.com"]
小结
看起来比较简单,但实际摸索的过程是曲折的。分享出来,也许可以让初次使用DotNetOpenAuth的朋友少走一些弯路。
【参考资料】
The OAuth 2.0 Authorization Framework
Claim-based-security for ASP.NET Web APIs using DotNetOpenAuth
实现Client Credentials Grant的更多相关文章
- 在ASP.NET中基于Owin OAuth使用Client Credentials Grant授权发放Token
OAuth真是一个复杂的东东,即使你把OAuth规范倒背如流,在具体实现时也会无从下手.因此,Microsoft.Owin.Security.OAuth应运而生(它的实现代码在Katana项目中),帮 ...
- [OAuth]基于DotNetOpenAuth实现Client Credentials Grant
Client Credentials Grant是指直接由Client向Authorization Server请求access token,无需用户(Resource Owner)的授权.比如我们提 ...
- (转)基于OWIN WebAPI 使用OAuth授权服务【客户端模式(Client Credentials Grant)】
适应范围 采用Client Credentials方式,即应用公钥.密钥方式获取Access Token,适用于任何类型应用,但通过它所获取的Access Token只能用于访问与用户无关的Open ...
- 基于 IdentityServer3 实现 OAuth 2.0 授权服务【客户端模式(Client Credentials Grant)】
github:https://github.com/IdentityServer/IdentityServer3/ documentation:https://identityserver.githu ...
- 基于OWIN WebAPI 使用OAuth授权服务【客户端模式(Client Credentials Grant)】
适应范围 采用Client Credentials方式,即应用公钥.密钥方式获取Access Token,适用于任何类型应用,但通过它所获取的Access Token只能用于访问与用户无关的Open ...
- OAuth2.0学习(1-7)授权方式4-客户端模式(Client Credentials Grant)
授权方式4-客户端模式(Client Credentials Grant) 客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提 ...
- Oauth Client Credentials Grant
http://www.cnblogs.com/dudu/p/4569857.html OAuth真是一个复杂的东东,即使你把OAuth规范倒背如流,在具体实现时也会无从下手.因此,Microsoft. ...
- 基于OWIN WebAPI 使用OAuth授权服务【客户端验证授权(Resource Owner Password Credentials Grant)】
适用范围 前面介绍了Client Credentials Grant ,只适合客户端的模式来使用,不涉及用户相关.而Resource Owner Password Credentials Grant模 ...
- 使用Resource Owner Password Credentials Grant授权发放Token
对应的应用场景是:为自家的网站开发手机 App(非第三方 App),只需用户在 App 上登录,无需用户对 App 所能访问的数据进行授权. 客户端获取Token: public string Get ...
随机推荐
- CSM认证培训知识汇总
后两天的CSM训练.我们非常颠覆旧观念,有关的一些观点的简要培训记录: 约定大于监管:监督是管理水平.或旧有格局,该公约是一个团队与自己的法规. 工具:传统的管理工具和服务经理,还有许多人是PM正在使 ...
- Xcode HeaderDoc 过程(1)
原版的: http://www.raywenderlich.com/66395/documenting-in-xcode-with-headerdoc-tutorial 了解如何从代码中生成文档! X ...
- 网络资源(6) - EJB视频
2014_08_24 http://v.youku.com/v_show/id_XMjE0NjE3MDA0.html?f=5227828 01_EJB3.0_下载安装与运行jboss -------- ...
- [WF4.0 实战] WPF + WCF + WF 打造Hello World(基础篇)
本篇博客是一个基础的演示样例,也就是一个新手教程吧!让大家熟悉一下WPF + WCF + WF三者的关系!这仅仅是一个基础篇,下篇会继续深入,作为这段时间研究工作流的一个小小总结! 三者关系: WPF ...
- 于Eclipse在建筑cocos2d-x的Android开发环境(避免cygwin)
于Eclipse在建筑cocos2d-x的Android开发环境(避免cygwin) 在袭击几天学习Android开发之后,我開始转向cocos2d-x的Android开发了.因为自己曾经有了解过co ...
- php+flash头像上传组件
有会员系统的站点一般都会有一个头像上传组件,一般做的最简单的是 这样的方式长处是代码写的简单,仅仅要推断图片大小和类型,然后更新数据库.可是用户体验不高.并且站点其它页面假设要使用较小的20X20或1 ...
- 【百度地图API】建立全国银行位置查询系统(二)——怎样为地图添加控件
原文:[百度地图API]建立全国银行位置查询系统(二)--怎样为地图添加控件 <摘要>你将在第二章中学会以下知识: 使用手写代码的利器——notepad++: 如何为地图添加控件——鱼骨. ...
- 【百度地图API】如何制作孪生姐妹地图?
原文:[百度地图API]如何制作孪生姐妹地图? 任务描述: 我想要两张一模一样的地图!我想要双子地图!我想要孪生姐妹地图! 好好好,统统满足大家! 在这里我不需要使用百度地图API提供的地图缩略图控件 ...
- ArcEngine下纵断面图的绘制
我是採用Dev控件中的画图控件来绘制的纵断面图,以下主要来介绍下输电线路选址以及纵断面图的实时绘制的实现流程. 一.关于输电线路的选址,首先要准备好基础地理数据,包含选线区的DOM,DEM,DLG以及 ...
- 初创互联网公司简明创业指南 - YC新掌门Sam Altman
本文只是一个创业指南的简明版 - 更详细的版本请查看:http://startupclass.samaltman.com 创业之前,你更应该去拥有一个好的创意,而不是一个公司.如果开始前你拥有一个好的 ...