Refresh Token的使用场景以及如何与JWT交互 - 我是钟钟的个人空间 - OSCHINA

标签: | 发表时间:2019-08-02 16:29 | 作者:
出处:https://my.oschina.net


在这篇文章中,我们将探索由 OAuth2定义的Refresh Token的概念。我们将会明白为什么他们会这样做,以及他们如何与其他类型的Token进行比较。我们也将通过一个简单的例子来学习如何使用它们。

更新:目前这篇文章写的Auth0还没有通过 OpenID Connect认证。本文中使用的某些术语(如 access token)不符合此规范,但符合 OAuth2规范。OpenID Connect在 access token(用于访问授权服务器的API)和 id token(用于针对资源服务器的客户端验证)之间建立明确的区别。

介绍

现代的认证或者授权的解决方案已经将 token引入到了协议当中。 token是一种特殊的数据片段,用来授权用户执行特定的操作,或允许客户获得关于授权过程的额外信息(然后完成)。换句话说,令牌是允许授权过程执行的信息。该信息是否可由客户端(或授权服务器以外的任何方)读取或解析,由该实现定义。重要的是:客户端获取这些信息,然后用来获取特定的资源。JSON Web Token(JWT) 规范定义了一种代表通用的 token信息的方式。

JWT简短回顾

JWT定义了可以表示与认证/授权过程有关的某些共同信息的方式。顾名思义,数据格式是JSON。JWT拥有subject,issuer,过期时间等通用属性。JWT与其他规范(如 JSON Web签名(JWS)和 JSON Web加密(JWE))结合使用时会变得非常有用。 这些规范不仅提供了授权 token通常需要的所有信息,还提供了一种验证 token内容的方法,以便它不会被篡改(JWS)和一种加密信息的方法,以使其对于客户端(JWE)。数据格式(及其他优点)的简单性已经帮助JWT成为最常见的 token类型之一。如果您有兴趣学习如何在您的Web应用程序中实现JWT,请查看Ryan Chenkie撰写的优秀 文章

Token类型

为了这篇文章的目的,我们将重点讨论两种最常见的 token类型: access tokenrefresh token

  • Access Token携带了直接访问资源的必要信息。换句话说,当客户端将 access token传给管理资源的服务器时,该服务器可以使用 token中包含的信息来决定是否授权给客户端。 access token通常有一个过期时间,而且通常时间非常短暂。

  • Refresh Token携带了用来获取新的access token的必要信息。换句话说,当客户端需要使用access token来访问特定资源的时候,客户端可以使用refresh token来向认证服务器请求下发新的access token。通常情况下,当旧的access token失效之后,才需要获得新的access token,或者是在第一次访问资源的时候。refresh token也有过期时间但是时间相对较长。refresh token对存储的要求通常会非常严格,以确保它不会被泄漏。它们也可以被授权服务器列入黑名单。

通常由具体的实现来定义token是透明的还是不透明的。通用实现允许对access token进行直接授权检查。也就是说,当access token传递给管理资源的服务器时,服务器可以读取token中包含的信息,并决定用户是否被授权(不需要对授权服务器进行检查)。这就是token必须签名的原因之一(例如使用JWS)。另一方面,refresh token通常需要对授权服务器进行检查。处理授权检查的这种分离方式有以下3个优点:

  1. 改进了对授权服务器的访问模式(更低的负载,更快的检查)
  2. 泄露access token的访问窗口更短(这些access token会很快过期,从而减少泄露的token访问受保护资源的机会)
  3. 滑动session(见下文)

滑动session

滑动session是只一段时间不活动后过期的session。正如你想到的,使用access token和refresh token可以很容易实现这个功能。当用户执行操作时,会发出一个新的access token。如果用户使用过期的access token,则session被认为是不活动的,并且需要新的access token。这个token是否可以通过access token获得,或者是否需要新的认证轮回,由开发团队的要求来定义。

安全考虑

refresh token的存活时间较长。这意味着当客户端获取refresh token时,必须安全的存储此token以防止潜在攻击者使用此token。如果refresh token泄露,它可能会被用来获取新的access token(并访问受保护的资源),直到它被列入黑名单或到期(可能需要很长时间)。refrsh token必须发给单个经过身份验证的客户端,以防止其他方使用泄漏的token。访问令牌必须保密,但是正如你所想象的那样,安全考虑因其寿命较短而不那么严格。

实例:Refresh Token发放服务器

为了这个例子的目的,我们使用一个基于 node-oauth2-server的简单的服务器来发布access token和refresh token。访问受保护的资源需要access token。客户端使用简单的curl命令。此示例中的代码基于 node-oauth2-server中的示例。我们已经修改了基本示例,access token使用JWT格式。Node-oauth2-server为模型使用预定义的API。你可以点 这里查看文档。以下代码展示了如何实现JWT格式的access token模型。

免责声明:请注意以下示例中的代码不是为生产环境准备的。

      model.generateToken = function(type, req, callback) {
  //Use the default implementation for refresh tokens
  console.log('generateToken: ' + type);
  if(type === 'refreshToken') {
    callback(null, null);
    return;
  }

  //Use JWT for access tokens
  var token = jwt.sign({
    user: req.user.id
  }, secretKey, {
    expiresIn: model.accessTokenLifetime,
    subject: req.client.clientId
  });

  callback(null, token);
}

model.getAccessToken = function (bearerToken, callback) {
  console.log('in getAccessToken (bearerToken: ' + bearerToken + ')');

  try {
    var decoded = jwt.verify(bearerToken, secretKey, {
        ignoreExpiration: true //handled by OAuth2 server implementation
    });
    callback(null, {
      accessToken: bearerToken,
      clientId: decoded.sub,
      userId: decoded.user,
      expires: new Date(decoded.exp * 1000)
    });
  } catch(e) {    
    callback(e);
  }
};

model.saveAccessToken = function (token, clientId, expires, userId, callback) {
  console.log('in saveAccessToken (token: ' + token +
              ', clientId: ' + clientId + ', userId: ' + userId.id +
              ', expires: ' + expires + ')');

  //No need to store JWT tokens.
  console.log(jwt.decode(token, secretKey));

  callback(null);
};

OAuth2 token端点(/oauth/token)处理所有类型的授权(密码和refresh token)的发放。其它所有端点都是受保护的,需要检查access token。

      // Handle token grant requests
app.all('/oauth/token', app.oauth.grant());

app.get('/secret', app.oauth.authorise(), function (req, res) {
  // Will require a valid access_token
  res.send('Secret area');
});

因此,例如,假设有一个用户'test',密码'test'和一个客户端'testclient',客户端密码'secret',可以请求一个新的access token/refresh token对,如下所示:

      $ curl -X POST -H 'Authorization: Basic dGVzdGNsaWVudDpzZWNyZXQ=' -d 'grant_type=password&username=test&password=test' localhost:3000/oauth/token

{
    "token_type":"bearer",
    "access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiVlx1MDAxNcKbwoNUwoonbFPCu8KhwrYiLCJpYXQiOjE0NDQyNjI1NDMsImV4cCI6MTQ0NDI2MjU2M30.MldruS1PvZaRZIJR4legQaauQ3_DYKxxP2rFnD37Ip4",
    "expires_in":20,
    "refresh_token":"fdb8fdbecf1d03ce5e6125c067733c0d51de209c"
}

授权头包含以BASE64(testclient:secret)编码的客户端ID和密钥。

使用该access token访问受保护的资源:

      $ curl 'localhost:3000/secret?access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiVlx1MDAxNcKbwoNUwoonbFPCu8KhwrYiLCJpYXQiOjE0NDQyNjI1NDMsImV4cCI6MTQ0NDI2MjU2M30.MldruS1PvZaRZIJR4legQaauQ3_DYKxxP2rFnD37Ip4'

Secret area

由于JWT,访问”安全区域“(就是受保护资源)不需要通过查询数据库来校验access token。

一旦token过期:

      $ curl 'localhost:3000/secret?access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiVlx1MDAxNcKbwoNUwoonbFPCu8KhwrYiLCJpYXQiOjE0NDQyNjI2MTEsImV4cCI6MTQ0NDI2MjYzMX0.KkHI8KkF4nmi9z6rAQu9uffJjiJuNnsMg1DC3CnmEV0'

{
    "code":401,
    "error":"invalid_token",
    "error_description":"The access token provided has expired."
}

现在我们可以通过refresh token来获取新的access token,如下所示:

      $ curl -X POST -H 'Authorization: Basic dGVzdGNsaWVudDpzZWNyZXQ=' -d 'refresh_token=fdb8fdbecf1d03ce5e6125c067733c0d51de209c&grant_type=refresh_token' localhost:3000/oauth/token

{
    "token_type":"bearer",
    "access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiVlx1MDAxNcKbwoNUwoonbFPCu8KhwrYiLCJpYXQiOjE0NDQyNjI4NjYsImV4cCI6MTQ0NDI2Mjg4Nn0.Dww7TC-d0teDAgsmKHw7bhF2THNichsE6rVJq9xu_2s",
    "expires_in":20,
    "refresh_token":"7fd15938c823cf58e78019bea2af142f9449696a"
}

这里查看完整代码。

另外:在你的auth0应用中使用refresh token

在auth0应用中我们为你解决了认证的难点。一旦你 配置了我们的应用程序,你就可以根据这里的 文档来获取refresh token。

结论

refresh token提升了安全性,并缩短了授权时间,提供了访问授权服务器的更好的一种新模式。使用JWT + JWS等工具可以简化实现。如果您有兴趣了解更多关于token(和cookies)的信息,请查看我们的 文章

原文地址: https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/

相关 [refresh token jwt] 推荐:

Refresh Token的使用场景以及如何与JWT交互 - 我是钟钟的个人空间 - OSCHINA

- -
OAuth2定义的Refresh Token的概念. 我们将会明白为什么他们会这样做,以及他们如何与其他类型的Token进行比较. 我们也将通过一个简单的例子来学习如何使用它们. 更新:目前这篇文章写的Auth0还没有通过. OpenID Connect认证. access token)不符合此规范,但符合.

什么是 JWT -- JSON WEB TOKEN - 简书

- -
Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准(. (RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景. JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密.

服务器session和jwt之争

- - zzm
session 和cookie的目的相同,都是为了克服http协议无状态的缺陷,但完成的方法不同. session通过cookie,在客户端保存session id,而将用户的其他会话消息保存在服务端的session对象中,与此相对的,cookie需要将所有信息都保存在客户端. 因此cookie存在着一定 的安全隐患,例如本地cookie中保存的用户名密码被破译,或cookie被其他网站收集(例如:1.

RSA的SecureID token数据被偷了?

- ripwu - 张志强的网络日志
博客 » 记事本 » 密码学 ». WSJ报道:RSA承认其数据被偷,4000万SecureID token需要被更新. 中国银行银行密钥用的就是RSA生产,就是下图这玩意儿,手里有这玩意儿的同学们要小心了(当然,如果你的账户里的钱没有6位数以上,也不用太担心,毕竟网银的安全性不全依赖于这个设备):.

[Web 安全] 如何通过JWT防御CSRF

- - SegmentFault 最新的文章
先解释两个名词,CSRF 和 JWT. CSRF (Cross Site Request Forgery),它讲的是你在一个浏览器中打开了两个标签页,其中一个页面通过窃取另一个页面的 cookie 来发送伪造的请求,因为 cookie 是随着请求自动发送到服务端的. JWT (JSON Web Token),通过某种算法将两个 JSON 对象加密成一个字符串,该字符串能代表唯一用户.

用JWT技术为SpringBoot的API增加授权保护 – springcamp

- -
示例 https://github.com/qihaiyan/jwt-boot-auth. 用spring-boot开发RESTful API非常的方便,在生产环境中,对发布的API增加授权保护是非常必要的. 现在我们来看如何利用JWT技术为API增加授权保护,保证只有获得授权的用户才能够访问API.

JWT Tool:针对 JSON Web Tokens 的测试工具

- - FreeBuf互联网安全新媒体平台
众望所归,大家期待已久的JWT渗透测试工具终于出炉啦. 没错,今天给大家介绍的这款名叫JWT Tool的工具,就可以针对JSON Web Tokens进行渗透测试. JWT是JSON Web Token的缩写,它是一串带有声明信息的字符串,由服务端使用加密算法对信息签名,以保证其完整性和不可伪造性.

使用RSA非对称加密JWT | 燃情岁月

- -
JWT几乎是当前分布式开发中无状态token的最佳选择,被越来越多的开发者接受和使用, JWT是基于加密算法的认证方式,省去了到认证服务器的校验过程,认证效率大大提高. 更详细的关于JWT的介绍可以点击 这里查看. 通常大家在使用JWT的时候都是使用 HmacSHA256加密钥的加密方式,这种方式严格依赖密钥,在分布式开发的过程中,通常是由认证服务器生成 JWT,然后再由资源校验 JWT的有效性,那么这时候资源服务器就也需要密钥了,认证服务和资源服务很可能是不同的团队开发和维护,密钥在这个过程中传递,很有可能泄漏.

微信平台的token安全验证(转)

- - 行业应用 - ITeye博客
本文目标:学习一种比较安全的服务器间互相验证身份的方式. 问题:开发微信公众平台接口,开发者的服务器为了确保请求是否来自微信服务器,应该如何去做. 1)  在微信管理页面上填写URL和TOKEN,开发者服务器上也记录同样的TOKEN. 2)  微信服务器发送HTTP请求,附带上参数(注意TOKEN是不会被传输的).

springmvc下的基于token的防重复提交

- - zzm
现在的网站在注册步骤中,由于后台要处理大量信息,造成响应变慢(测试机器性能差也是造成变慢的一个因素),在前端页面提交信息之前,等待后端响应,此时如果用户. 再点一次提交按钮,后台会保存多份用户信息. 为解决此问题,借鉴了struts2的token思路,在springmvc下实现token. 在springmvc配置文件中加入拦截器的配置,拦截两类请求,一类是到页面的,一类是提交表单的.