Skip to content

起源

今天逛阮一峰老师的周报,发现了一篇有意思的博客,分享给大家。

概念

我们需要熟悉几个概念:

  • client ID:申请
  • client secret:申请
  • authorization code:二次交换
  • access token:三次交换
  • refresh token:三次交换

开始流程

  1. 下发密钥
    需要前往下发密钥的服务端,申请client ID,client secret,还需要配置回调地址(有些平台是让你传,有些平台还需要确认你对服务器的控制权,需要你认证一下服务器),这里的回调地址是用来下发 token 或者返回相关使用信息的。
  2. 获取认证地址
    像是(xxx/oauth/xxxx),这个地址是用户来确认可以将你的数据授权给第三方应用的。
  3. 开始认证流程
    这时候,用户点击授权,会跳转到对应xxxx的授权地址,跳转的时候,一半来说需要带上以下几个值:
javascript
  //响应值
  params.set("response_type", "code");
  //客户申请的token(这里是客户的标识)
  params.set("client_id", CLIENT_ID);
  //重定向地址
  params.set("redirect_uri", "http://localhost:3000/oauth/google/callback");
  //你想要获取的权限
  params.set("scope", "email");
  //防止跨站攻击
   res.set("Set-Cookie", `oauth_state=${state}; HttpOnly; Secure; SameSite=Lax`);

用户这时候是在认证的页面,确认给你授权项目,这时候用户点击授权,触发回调接口,返回一些重要值 4. 接收到回调
确认一下state的值,如果匹配,就可以继续流程,这时候你使用client_id换取到了一个至关重要的值:authorization_code

这个code可以换取对应的访问token,非常重要,请勿泄露。

  1. 换access token与refresh token
    这时候,我们再拿client ID、client secret、authorization code 去换取访问的access token和 refresh token
  2. 使用access token为所欲为
    这时候你就可以使用access token,注意这里需要带上一个标识Bearer ,服务端会根据授权返回你的数据,比如访问:getUserInfo
  3. 过期刷新
    access token是有时间限制的,这时候可以使用refresh token进行刷新token,获取新的access token

小思考

其实 OAuth2 只是一个授权协议,真正的认证协议是自定义在如获取用户信息,获取 token 等位置,所以出现了一种变种OIDC的认证框架,所以其实市面上的安全框架(sa-token、spring security)都是授权的框架,但是会有认证的自定义代码写在其中。

为什么需要两次才能换取到access token,而不是一次

主要是为了安全考虑,一般来说authorization_code的时间都会很短,第一步中通过前端传递,但实际的访问令牌交换过程在后台进行,减少了令牌暴露在不安全的网络环境中的风险。

简单聊聊openId这种变种(OIDC)

主要在OIDC这种变种之下,会返回对应的用户身份认证标识,可以拿这个标识换取到对应人的信息,但是oauth中,如果资源服务器不定义对应的接口(getUserInfo),你是无法访问用户信息的。具体描述如下

  • 整个OAuth2协议,只是定义了access_token/refresh_token,但是这俩token只是为了保护Resource Server的,并没有Resource Owner的身份信息;
  • OIDC引入了id_token的概念,用这个特殊的token来表示这是Resource Owner的身份证: