ASP.NET OAuth:解决refresh token无法刷新access token的问题
最近同事用iOS App调用Open API时遇到一个问题:在access token过期后,用refresh token刷新access token时,服务器响应"invalid_grant"错误;而在access token没有过期的情况下,能正常刷新access token。
先查看了一下OAuth规范中的“Refreshing an Expired Access Token”流程图,以确认客户端的操作流程有没有问题。

问题发生在上图中的(G)操作步骤。iOS App就是按上图的流程进行操作的——在调用Open API时,如果服务器响应access token无效,就用refresh token刷新access token,客户端的操作流程一点问题没有。
于是将问题锁定在服务端。打点写日志,发现refresh token刷新access token时服务端先调用了IAuthenticationTokenProvider.ReceiveAsync(),然后调用了IOAuthAuthorizationServerProvider.GrantRefreshToken()方法。对应于我们的实现就是CNBlogsRefreshTokenProvider.ReceiveAsync()与CNBlogsAuthorizationServerProvider.GrantRefreshToken()。
查看ReceiveAsync()方法的实现代码:
public override async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
{
var refreshToken = await _refreshTokenService.Get(context.Token);
if (refreshToken != null)
{
context.DeserializeTicket(refreshToken.ProtectedTicket);
await _refreshTokenService.Remove(context.Token);
}
}
从上面的代码可以得知,用refresh token刷新access token,实际就是将存储在数据库中的ProtectedTicket反序列为包含access token的ticket,然后根据这个ticket生成access token返回给客户端。而refreshToken.ProtectedTicket是在生成refresh token时由包含access token的ticket序列化生成的,refresh token无法刷新access token,问题很可能就出在它身上。
于是查看生成refresh token部分的代码——CNBlogsRefreshTokenProvider(继承自AuthenticationTokenProvider)的CreateAsync()方法:
var refreshToken = new RefreshToken()
{
Id = refreshTokenId,
ClientId = new Guid(clientId),
UserName = context.Ticket.Identity.Name
IssuedUtc = DateTime.UtcNow,
ExpiresUtc = DateTime.UtcNow.AddSeconds(Convert.ToDouble(refreshTokenLifeTime)),
ProtectedTicket = context.SerializeTicket()
}; context.Ticket.Properties.IssuedUtc = refreshToken.IssuedUtc;
context.Ticket.Properties.ExpiresUtc = refreshToken.ExpiresUtc;
当时一看代码,立马恍然大悟。应该是先设置IssuedUtc与ExpiresUtc,然后再SerializeTicket();实际被写成了先SerializeTicket(),后设置IssuedUtc与ExpiresUtc。结果造成refreshToken.ProtectedTicket的过期时间不正确,从而无法刷新access token。
解决方法很简单,只需将context.SerializeTicket()移至设置Ticket的IssuedUtc与ExpiresUtc的代码之后:
var refreshToken = new RefreshToken()
{
Id = refreshTokenId,
ClientId = new Guid(clientId),
UserName = context.Ticket.Identity.Name
IssuedUtc = DateTime.UtcNow,
ExpiresUtc = DateTime.UtcNow.AddSeconds(Convert.ToDouble(refreshTokenLifeTime)), };
context.Ticket.Properties.IssuedUtc = refreshToken.IssuedUtc;
context.Ticket.Properties.ExpiresUtc = refreshToken.ExpiresUtc;
refreshToken.ProtectedTicket = context.SerializeTicket();
ASP.NET OAuth:解决refresh token无法刷新access token的问题的更多相关文章
- OAuth 白话简明教程 4.刷新 Access Token
转自:http://www.cftea.com/c/2016/11/6705.asp OAuth 白话简明教程 1.简述 OAuth 白话简明教程 2.授权码模式(Authorization Code ...
- iOS实现OAuth2.0中刷新access token并重新请求数据操作
一.简要概述 OAuth2.0是OAuth协议的下一版本,时常用于移动客户端的开发,是一种比较安全的机制.在OAuth 2.0中,server将发行一个短有效期的access token和长生命期的r ...
- ASP.NET OWIN OAuth:refresh token的持久化
在前一篇博文中,我们初步地了解了refresh token的用途——它是用于刷新access token的一种token,并且用简单的示例代码体验了一下获取refresh token并且用它刷新acc ...
- Access Token 机制详解
我们在访问很多大公司的开放 api 的时候,都会发现这些 api 要求传递一个 access token 参数.这个参数是什么呢?需要去哪里获取这个 access token 呢? access to ...
- Web API与OAuth:既生access token,何生refresh token
在前一篇博文中,我们基于 ASP.NET Web API 与 OWIN OAuth 以 Resource Owner Password Credentials Grant 的授权方式( grant_t ...
- ASP.NET没有魔法——ASP.NET OAuth、jwt、OpenID Connect
上一篇文章介绍了OAuth2.0以及如何使用.Net来实现基于OAuth的身份验证,本文是对上一篇文章的补充,主要是介绍OAuth与Jwt以及OpenID Connect之间的关系与区别. 本文主要内 ...
- ASP.NET OAuth、jwt、OpenID Connect
ASP.NET OAuth.jwt.OpenID Connect 上一篇文章介绍了OAuth2.0以及如何使用.Net来实现基于OAuth的身份验证,本文是对上一篇文章的补充,主要是介绍OAuth与J ...
- Access Token 与 Refresh Token【转载哒科普啊】
Access Token 与 Refresh Token access token 是客户端访问资源服务器的令牌.拥有这个令牌代表着得到用户的授权.然而,这个授权应该是临时的,有一定有效期.这是因 ...
- Oauth2.0(三):Access Token 与 Refresh Token
access token 是客户端访问资源服务器的令牌.拥有这个令牌代表着得到用户的授权.然而,这个授权应该是临时的,有一定有效期.这是因为,access token 在使用的过程中可能会泄露.给 a ...
随机推荐
- 【大型网站技术实践】初级篇:借助LVS+Keepalived实现负载均衡
一.负载均衡:必不可少的基础手段 1.1 找更多的牛来拉车吧 当前大多数的互联网系统都使用了服务器集群技术,集群即将相同服务部署在多台服务器上构成一个集群整体对外提供服务,这些集群可以是Web应用服务 ...
- 工欲善其事,必先利其器 之 VS2013全攻略(安装,技巧,快捷键,插件)!
如有需要WPF工具的朋友可以移步 工欲善其事,必先利其器 之 WPF篇: 随着开发轨迹来看高效WPF开发的工具和技巧 之前一篇<c++的性能, c#的产能?!鱼和熊掌可以兼得,.NET NATI ...
- 【原】AFNetworking源码阅读(六)
[原]AFNetworking源码阅读(六) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这一篇的想讲的,一个就是分析一下AFSecurityPolicy文件,看看AF ...
- 引人瞩目的 CSS 变量(CSS Variable)
这是一个令人激动的革新. CSS 变量,顾名思义,也就是由网页的作者或用户定义的实体,用来指定文档中的特定变量. 更准确的说法,应该称之为 CSS 自定义属性 ,不过下文为了好理解都称之为 CSS 变 ...
- 在jekyll模板博客中添加网易云模块
最近使用GitHub Pages + Jekyll 搭建了个人博客,作为一名重度音乐患者,博客里面可以不配图,但是不能不配音乐啊. 遂在博客里面引入了网易云模块,这里要感谢网易云的分享机制,对开发者非 ...
- android studio 使用 jni 编译 opencv 完整实例 之 图像边缘检测!从此在andrid中自由使用 图像匹配、识别、检测
目录: 1,过程感慨: 2,运行环境: 3,准备工作: 4,编译 .so 5,遇到的关键问题及其解决方法 6,实现效果截图. (原创:转载声明出处:http://www.cnblogs.com/lin ...
- const extern static 终极指南
const extern static 终极指南 不管是从事哪种语言的开发工作,const extern static 这三个关键字的用法和原理都是我们必须明白的.本文将对此做出非常详细的讲解. co ...
- 漫谈C#编程语言在游戏领域的应用
0x00 前言 随着微软越来越开放,C#也变得越来越吸引人们的眼球.而在游戏行业中,C#也开始慢慢地获得了关注.这不, 网易绝代双娇手游团队已经全面使用.Net Core支持前后端统一C#开发,跨平台 ...
- Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
- SAP自定义权限对象
SAP系统自带了很多的权限对象,每一个运行画面都有非常多的权限用到.不过标准的权限对象并不一定适合于用在客户自己开发的程序里面,所以每个ABAPer都应该会自己开发一套权限对象,并引用在程序代码里面. ...