Oauth和oidc的关系和讲解
Oauth2.0是一套授权框架,目标是解决第三方应用如何在不获取用户密码的前提下,代表用户去访问受保护的资源。oidc是在oauth2之上的身份认证层,核心目标是让客户端能验证用户,它在 OAuth 2.0 的授权流程上,额外返回一个 ID Token
OAuth
Oauth2.0是一套授权框架,目标是解决第三方应用如何在不获取用户密码的前提下,代表用户去访问受保护的资源。oauth体系里面,有四个角色,分别是资源所有者、客户端、授权服务器、资源服务器。
资源所有者一般就是用户,是数据拥有者,有权决定是否授权,客户端是想要访问用户数据的第三方应用,比如有个工具想要读取你gayhub仓库列表的项目管理。授权服务器用于验证身份、征得同意、颁发令牌,gayhub也有oauth登录服务。资源服务用于存储受保护的api服务,如github有restapi,需要令牌,不认密码。
然后是授权模式,首先是授权码模式,这个是最安全、最常用的模式。用户需要发请请求,比如阿紫客户端点击使用github登录,重定向到授权服务器中,客户端把用户的浏览器重定向到github的授权服务器,请求用户授权。用户需要登录并授权,同意授权给客户端相应的权限。完成之后授权服务器把浏览器重定向会客户端,并在URL上带上一个授权码,客户端在后台用授权码+客户端秘钥向授权服务器换取访问令牌,客户端就可以通过访问令牌去资源服务器上请求用户的数据了。
隐式模式不推荐,它是令牌慧姐通过URL返回,容易泄漏,无法刷新。密码模式已禁止,用户需要把密码直接给客户端,从根本上违背了OAuth的设计。
客户端机密模式是服务间调用,用户无参与,客户端会以自己的身份获取令牌,用于访问自己的资源,不涉及用户。
OAuth本身留下了很多安全细节,最新实践RFC 9700明确表示强制使用PKCE,所有的客户端类型,尤其是公开客户端SPA 移动APP都需要使用PKCE来防止授权码被拦截。授权服务器必须对重定向uri进行精确的字符串匹配,不能使用通配符或者模式匹配,防止授权码被重定向到恶意地址。
注意: OAuth只负责授权,不负责认证,使用Google登录这种选项实际上是OAuth2.0 + OIDC的组合。OIDC 是 OAuth 2.0 之上的一个身份层,它额外提供了一个 ID 令牌 (ID Token) ,这是一个包含用户身份信息(如姓名、邮箱)的 JWT,用来证明用户身份,之后会讲。
为什么访问资源需要客户端秘钥,这个是为了证明客户端身份,因为授权服务器需要确认客户端是否真的是我们自己规定的客户端,如果说授权码被拦截也无所谓,有了客户端秘钥才能换令牌。
OIDC
然后我们来谈谈oidc部分,它是在oauth2之上的身份认证层,核心目标是让客户端能验证用户,它在 OAuth 2.0 的授权流程上,额外返回一个 ID Token(JWT)。
因为oauth2只会给access_token,也就是用于访问资源的访问令牌,oidc额外返回了id_token,id_token是jwt,能够包含用户信息,客户端解 id_token。然后客户端是可以验证id token里面的签名的,需要使用JWKS,我们可以通过一个get请求,去访问公钥集合:
GET https://auth.example.com/.well-known/jwks.json
{
"keys": [
{
"kty": "RSA",
"kid": "key-1",
"use": "sig",
"n": "...",
"e": "AQAB"
}
]
}
并且scope里面必须包含openid,不然就不是oidc。OIDC 定义了标准 scope:
| scope | 含义 | 返回的 claim |
|---|---|---|
openid | 必须,表示 OIDC | sub |
profile | 基本资料 | name、family_name、picture 等 |
email | 邮箱 | email、email_verified |
address | 地址 | address |
phone | 电话 | phone_number、phone_number_verified |
oidc的使用场景:
SSO 单点登录,用户登录一次,可以多个应用共享身份,每个应用用oidc来验证用户。比如企业sso,一个idp,多个应用。
社交登录:使用google登录,是使用oauth2.0+oidc,拿id_token->验证用户。
移动App:调用系统浏览器访问授权服务器返回id_token。然后客户端是可以验证id