一、认证和授权
认证 (Authentication):告诉服务器“这个人代表谁”。
授权 (Authenrization):告诉服务器“这个人可以做什么”。
OAuth2.0 定义了【授权】框架;OpenID 为其扩展了【认证】的标准。
OAuth2.0 帮用户获得接口的调用权限;OpenID 为用户提供身份标识。
OpenID 和 OAuth2.0 有着相同的流程。
注意:不是 OAuth2.0 无法完成认证,而是 OAuth2.0 本身的认证过程缺乏统一的标准。
二、流程描述
OAuth2.0 如何完成授权?
所谓授权,就是指拿到令牌(Access Token)的方式。
令牌保存在每次调用 API 的请求中。
curl -H "Authorization: Bearer ACCESS_TOKEN" "https://资源服务器.com"
这里面涉及到几个角色:
资源拥有者:通常是正在操作系统的用户。加入这里的资源指“订单”,那资源所有者就是有权限查看订单数据的用户。
资源服务器:通常指业务系统。比如 B/S 架构的订单管理系统的 S 端。
客户端应用:通常指浏览器。比如 B/S 架构的订单管理系统的 B 端。
授权服务器:通常指认证中心。用户登录界面就是在此系统上。
OAuth2.0 有四种授权模式:
授权码:最完整的流程,适用于有服务端,可以安全存储 AccessToken 的场景。
隐式授权:简化的流程,适用于没有服务端的前端应用。
密码凭证:适用于应用可信任,可以代替服务端收集用户名密码的应用,
客户端凭证:适用于纯后台应用。
具体流程:
授权码(response_type=code):
1. 资源服务器 在 授权服务器 完成注册;
(ClientID、Secret、Callback URL等)
2. 资源拥有者 访问 资源服务器;
(业务的开端)
3. 资源服务器 提供链接,请 资源拥有者 去 授权服务器 完成认证;
代码语言:javascript复制https://授权中心.com/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=SCOPE
4. 资源拥有者 完成认证后,在 授权服务器 上继续授权 资源服务器 用自己的身份调用资源;
(XX应用需要使用您的XX信息,是否同意授权?)
5. 授权服务器 将授权码 CODE 转发给第3步中的 REDIRECT_URI;
代码语言:javascript复制https://REDIRECT_URI?code=CODE
6. 资源服务器 用 CODE 向 授权服务器 换取 Access Token,CODE 随即失效;
代码语言:javascript复制https://授权中心.com/oauth/token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=CALLBACK_URL
7. 授权服务器 颁发 Access Token 给 资源服务器,资源服务器 替 资源所有者 保存到 客户端应用 中;
8. 资源所有者 每次通过 客户端应用 访问 资源服务器 都携带此令牌,资源服务器 验证后提供资源服务。
隐式授权(repsonse_type=token):
1. 应用系统 请 资源所有者 访问 授权服务器 的链接;
代码语言:javascript复制https://授权中心.com/oauth/authorize?response_type=token&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&
scope=SCOPE
2. 授权服务器 认证用户,返回 Access Token;
代码语言:javascript复制https://应用系统.com/callback#token=ACCESS_TOKEN
注意,此时的 Token 存放在锚点中,而非查询参数里,这样可以在 http 协议时避免“中间人攻击”,因为锚点不会发送到服务端。
密码凭证(grant_type=password):
1. 应用系统 要求 资源所有者 提供 用户名 和 密码;
2. 应用系统 将 用户名密码 发送给 授权服务器 换取 Access Token;
代码语言:javascript复制https://授权中心.com/token?grant_type=password&username=USERNAME&password=PASSWORD&client_id=CLIENT_ID
注意:这里的 Token 是直接在 JSON 响应中返还,而不需要再跳转。
客户端凭证(grant_type=client_credentials):
1. 应用系统 在后台直接向 授权服务器 索要 Access Token;
代码语言:javascript复制https://oauth.b.com/token?grant_type=client_credentials&client_id=CLIENT_ID&client_secret=CLIENT_SECRET
OIDC 模式
OIDC 为 OAuth2.0 扩展了 scope=openid 的场景,在返回值中会额外增加 ID_TOKEN:
代码语言:javascript复制https://授权服务器.com/authorize?
response_type=code
&scope=openid profile email
&client_id=CLIENT_ID
&state=STATE
&redirect_uri=REDIRECT_URI
响应数据:
代码语言:javascript复制{
"access_token": ACCESS_TOKEN,
"token_type": "Bearer",
"refresh_token": REFRESH_TOKEN,
"expires_in": EXPIRES_IN_SECOND,
"id_token": JWT_ID_TOKEN
}