上面使用授权码模式生成的Access Token是存在过期时间的(实际上无论什么方式生成的Access Token都存在过期时间),Token过期后又不可能让用户再授权一次,所以需要使用Refresh Token来定期刷新Access Token,.Net中实现Refresh Token的方式与授权码类似,在生成Refresh Token的同时会关联用户的身份信息,后续可以使用这个Refresh Token来生成新的Access Token。
1. 创建Refresh Token提供器(实现方式与授权码提供器基本一致):
2. 为授权服务器配置Refresh Token提供器:
3. 再次获取到授权码后,根据该授权码获取Access Token,返回信息中将携带Refresh Token:
4. 根据Refresh Token刷新Access Token:
实现通过用户密码模式获取Access Token
上面介绍了授权码模式的实现方式,但这种方式的核心实际上是建立了一个授权码和用户信息的映射(包括刷新令牌方式也是建立了刷新令牌与用户信息的映射),后续的Access Token实际上是使用这个了用户信息生成的。换句话用户信息才是核心,.Net中用户信息的体现从底到高分别是:IIdentity->ClaimsIdentity-> AuthenticationTicket,关于用户的身份信息可参考:《ASP.NET没有魔法——ASP.NET Identity与授权》,在基于授权码的模式时通过在授权服务器的登录功能获得了用户信息,而基于用户名密码模式时没有这个跳转登录环节,所以需要直接通过用户名密码来获取用户信息,其实现如下重载了OAuthAuthorizationServerProvider类型的GrantResourceOwnerCredentials方法:
该方法从Owin环境中获取Identity中的UserManager对象,通过UserManager来验证用户是否存在,如果存在则将使用用户信息来创建一个ClaimsIdentity对象(注:此处是省略的实现,正常实现可根据需求参考Cookie验证方式将Scope或者Role等信息也添加到Identity对象中)。另UserManager是通过以下代码添加到Owin上下文中的,它的Key值是"AspNet.Identity.Owin:" + typeof(ApplicationUserManager).AssemblyQualifiedName。
使用用户名密码获取Access Token:
实现客户端模式获取Access Token
客户端模式和用户名密码模式是类似的,它是通过Client的Id以及密码来进行授权,使用的是Client相关的信息,它的实现方式如下,重载GrantClientCredentials方法,通过客户端验证后的id和密码信息来验证改Client是否合法,对于合法的Client为其创建Identity对象(注:此处可以根据实际需求在Identity中添加相应的属性):
使用Client信息获取Access Token:
以上就是.Net中对于OAuth的实现,另外.Net中没有提供简化模式的接口,但是提供了一个GrantCustomExtension,也就是说授权模式是可拓展的。
关于.Net中OAuth相关令牌的加密说明本例中除了授权码以及刷新令牌是2个Guid连接外,访问令牌(包括所有授权模式生成的令牌)以及授权码对应的用户信息、刷新令牌对应的用户信息都是经过加密的,其加解密对象创建过程如下,具体内容可参考《ASP.NET没有魔法——ASP.NET Identity的加密与解密》