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 = "";
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(),
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

Implementing an API Key with DotNetOpenAuth

[OAuth]基于DotNetOpenAuth实现Client Credentials Grant的更多相关文章

  1. 基于OWIN WebAPI 使用OAuth授权服务【客户端模式(Client Credentials Grant)】

    适应范围 采用Client Credentials方式,即应用公钥.密钥方式获取Access Token,适用于任何类型应用,但通过它所获取的Access Token只能用于访问与用户无关的Open ...

  2. 实现Client Credentials Grant

    [OAuth]基于DotNetOpenAuth实现Client Credentials Grant   Client Credentials Grant是指直接由Client向Authorizatio ...

  3. 在ASP.NET中基于Owin OAuth使用Client Credentials Grant授权发放Token

    OAuth真是一个复杂的东东,即使你把OAuth规范倒背如流,在具体实现时也会无从下手.因此,Microsoft.Owin.Security.OAuth应运而生(它的实现代码在Katana项目中),帮 ...

  4. (转)基于OWIN WebAPI 使用OAuth授权服务【客户端模式(Client Credentials Grant)】

    适应范围 采用Client Credentials方式,即应用公钥.密钥方式获取Access Token,适用于任何类型应用,但通过它所获取的Access Token只能用于访问与用户无关的Open ...

  5. 基于 IdentityServer3 实现 OAuth 2.0 授权服务【客户端模式(Client Credentials Grant)】

    github:https://github.com/IdentityServer/IdentityServer3/ documentation:https://identityserver.githu ...

  6. Oauth Client Credentials Grant

    http://www.cnblogs.com/dudu/p/4569857.html OAuth真是一个复杂的东东,即使你把OAuth规范倒背如流,在具体实现时也会无从下手.因此,Microsoft. ...

  7. OAuth2.0学习(1-7)授权方式4-客户端模式(Client Credentials Grant)

    授权方式4-客户端模式(Client Credentials Grant) 客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提 ...

  8. 基于OWIN WebAPI 使用OAuth授权服务【客户端验证授权(Resource Owner Password Credentials Grant)】

    适用范围 前面介绍了Client Credentials Grant ,只适合客户端的模式来使用,不涉及用户相关.而Resource Owner Password Credentials Grant模 ...

  9. OAuth 白话简明教程 3.客户端模式(Client Credentials)

    转自:http://www.cftea.com/c/2016/11/6704.asp OAuth 白话简明教程 1.简述 OAuth 白话简明教程 2.授权码模式(Authorization Code ...

随机推荐

  1. JavaScript进阶之路(一)初学者的开始

    一:写在前面的问题和话 一个javascript初学者的进阶之路! 背景:3年后端(ASP.NET)工作经验,javascript水平一般般,前端水平一般般.学习资料:犀牛书. 如有误导,或者错误的地 ...

  2. C#中如何给Excel添加水印

    我们知道Microsoft Excel并没有内置的功能直接给Excel表添加水印,但是其实我们可以用其他变通的方式来解决此问题,如通过添加页眉图片或艺术字的方法来模仿水印的外观.所以在这篇文章中,我将 ...

  3. 关于.NET参数传递方式的思考

    年关将近,整个人已经没有了工作和写作的激情,估计这个时候很多人跟我差不多,该相亲的相亲,该聚会喝酒的聚会喝酒,总之就是没有了干活的心思(我有很多想法,但就是叫不动我的手脚,所以我只能看着别人在做我想做 ...

  4. 调用微信退款接口或发红包接口时出现System.Security.Cryptography.CryptographicException: 出现了内部错误 解决办法

    我总结了一下出现证书无法加载的原因有以下三个 1.证书密码不正确,微信证书密码就是商户号 解决办法:请检查证书密码是不是和商户号一致 2.IIS设置错误,未加载用户配置文件 解决办法:找到网站使用的应 ...

  5. MATLAB中绘制质点轨迹动图并保存成GIF

    工作需要在MATLAB中绘制质点轨迹并保存成GIF以便展示. 绘制质点轨迹动图可用comet和comet3命令,使用例子如下: t = 0:.01:2*pi;x = cos(2*t).*(cos(t) ...

  6. Git 学习看这篇就够了!

    Git是一个开源的分布式版本控制系统,可以有效.高速的处理从很小到非常大的项目版本管理. 可能新手会问"git和github有什么关系啊?" git是一个版本控制工具: githu ...

  7. Mysql - 增删改

    因为项目原因, mysql用了两年了, 但是一直都未曾去总结过. 最近也是领导让总结项目, 才想起把mysql的使用小结一下. 一. Create 1. 单条插入, sql格式: insert int ...

  8. 鱼眼模式(Fisheye projection)的软件实现

    简单实现 鱼眼模式(Fisheye)和普通的透视投影(Perspective projection),一个很大的区别就是鱼眼的投影算法是非线性的(non-linear),实际照相机的情况是在镜头外面包 ...

  9. 第12章 Linux系统管理

    1. 进程管理 1.1 进程查看 (1)进程简介 进程是正在执行的一个程序或命令(如ls命令也是一个进程),每个进程都是一个运行的实体,都有自己的地址空间,并占用一定的系统资源. (2)进程管理的作用 ...

  10. 在CentOS上构建.net自动化编译环境

             我们知道在Windows上我们很容易构建于MSBuild的自动化编译环境,那么在CentOS也是可以的,主要是需要Mono. 在这儿我们选择Jenkins+Gitlab+Mono在C ...