起源
今天逛阮一峰老师的周报,发现了一篇有意思的博客,分享给大家。
概念
我们需要熟悉几个概念:
- client ID:申请
- client secret:申请
- authorization code:二次交换
- access token:三次交换
- refresh token:三次交换
开始流程
- 下发密钥
需要前往下发密钥的服务端,申请client ID,client secret,还需要配置回调地址(有些平台是让你传,有些平台还需要确认你对服务器的控制权,需要你认证一下服务器),这里的回调地址是用来下发 token 或者返回相关使用信息的。 - 获取认证地址
像是(xxx/oauth/xxxx),这个地址是用户来确认可以将你的数据授权给第三方应用的。 - 开始认证流程
这时候,用户点击授权,会跳转到对应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,非常重要,请勿泄露。
- 换access token与refresh token
这时候,我们再拿client ID、client secret、authorization code 去换取访问的access token和 refresh token - 使用access token为所欲为
这时候你就可以使用access token,注意这里需要带上一个标识Bearer ,服务端会根据授权返回你的数据,比如访问:getUserInfo - 过期刷新
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的身份证: