OIDC协议介绍

协议背景

在我们之前的文章深入理解Spring Cloud Security OAuth2及JWT已经提到,OAuth2 本身设计是一个资源访问的授权协议而不是一个身份认证协议,虽然也可以通过提供一个用户身份的资源接口来实现SSO,但终归是野路子。同时缺乏标准化的用户身份验证规范,不同服务商返回的用户信息格式不统一,从而导致跨服务商的身份验证复杂化。

那有啥办法可以既用到OAuth2认证的灵活性,又可以在 token 中携带用户信息呢?OIDC就是在这个背景之上设计出来的一个专门用于身份认证的规范(可以类比于SAML2),OIDC全称为OpenID Connect,由OpenID Foundation这个非营利性组织制定(其实背后还是微软、谷歌、salesforce这些大佬)。它是OAuth2的一个超集,基于OAuth2认证规范(RFC 6749 和 6750),同时扩展了与认证相关的信息,可以作为标准的SSO服务器使用。

较OAuth2,OIDC中的概念更加接近于SAML2:

  • EU:End User,用户。
  • RP:Relying Party ,用来代指OAuth2中的受信任的客户端,身份认证和授权信息的消费方;
  • OP:OpenID Provider,有能力提供EU身份认证的服务方(比如OAuth2中的授权服务),用来为RP提供EU的身份认证信息;
  • ID-Token:JWT格式的数据,包含EU身份认证的信息。
  • UserInfo Endpoint:用户信息接口(受OAuth2保护),当RP使用ID-Token访问时,返回授权用户的信息,此接口必须使用HTTPS。

完整术语参见http://openid.net/specs/openid-connect-core-1_0.html#Terminology

OIDC的认证流程:


oidc.png
  1. RP发送认证请求到OP
  2. OP对EU进行认证(AuthN)及授权(AuthZ)
  3. OP在认证请求响应报文中返回access_token及id_token
  4. RP携带Access Token发送请求到UserInfo Endpoint
  5. UserInfo Endpoint返回EU的完整Claims

OIDC协议

OIDC本身是有多个规范构成,其中包含一个核心的规范,多个可选支持的规范来提供扩展支持,简单的来看一下:

  1. Core:必选。定义OIDC的核心功能,在OAuth 2.0之上构建身份认证,以及如何使用Claims来传递用户的信息。
  2. Discovery:可选。发现服务,使客户端可以动态的获取OIDC服务相关的元数据描述信息(比如支持那些规范,接口地址是什么等等)。
  3. Dynamic Registration :可选。动态注册服务,使客户端可以动态的注册到OIDC的OP(这个缩写后面会解释)。
  4. OAuth 2.0 Multiple Response Types :可选。针对OAuth2的扩展,提供几个新的response_type。
  5. OAuth 2.0 Form Post Response Mode:可选。针对OAuth2的扩展,OAuth2回传信息给客户端是通过URL的querystring和fragment这两种方式,这个扩展标准提供了一基于form表单的形式把数据post给客户端的机制。
  6. Session Management :可选。Session管理,用于规范OIDC服务如何管理Session信息。
  7. Front-Channel Logout:可选。基于前端的注销机制,使得RP(这个缩写后面会解释)可以不使用OP的iframe来退出。
  8. Back-Channel Logout:可选。基于后端的注销机制,定义了RP和OP直接如何通信来完成注销。

下图是协议族的全景图,一般我们用core这个核心规范就可以了


Protocal Suite

ID Token

OIDC对OAuth2进行的主要扩展(用户身份验证)就是在access_token这一步的返回中增加了ID Token,为JWT格式。其中包含授权服务器对用户验证的Claims和其它请求的Claims。

在ID Token中,以下Claims适用于使用OIDC的所有OAuth2:

  • iss,必须,发行机构Issuer,大小写敏感的URL,不能包含query参数
  • sub,必须,用户身份Subject,Issuer为End-User分配的唯一标识符,大小写敏感不超过255 ASCII自符
  • aud,必须,特别的身份Audience,必须包含OAuth2的client_id,大小写敏感的字符串/数组
  • exp,必须,iat到期时间Expire,参数要求当前时间在该时间之前,通常可以时钟偏差几分钟,unix时间戳
  • iat,必须,JWT颁发时间Issuer at time,unix时间戳
  • auth_time,End-User验证时间,unix时间戳。当发出max_age或auth_time Claims时,必须。
  • nonce,用于将Client session和ID Token关联,减轻重放攻击,大小写敏感字符串
  • acr,可选,Authentication Context Class Reference
  • amr,可选,Authentication Methods References,JSON字符串数组,身份验证的表示符,如可能使用了密码和OTP身份验证方式
  • azp,可选,Authorized party,被授权方。如果存在必须包含OAuth2的Client ID,仅当ID Token有单个Audience且与授权方不同时,才需要此Claim

ID Token可能包含其它Claims,任何未知的Claims都必须忽略。ID Token必须使用JWS进行签名,并分别使用JWS和JWE进行可选的签名和加密,从而提供身份验证、完整性、不可抵赖性和可选的机密性。如果对ID Token进行了加密,则必须先对其签名,结果是一个嵌套的JWT。ID Token不能使用nonce作为alg值,除非所使用的响应类型没有从Authorization Endpoint返回任何ID Token(如Authorization Code Flow),并且客户端在注册时显示请求使用nonce。

认证流程演示

auth0 提供了一个 OpenID Connect Playground,非常直观的演示了 OIDC认证的全过程,下面使用这个Playground来进行认证步骤的演示(机密信息都已经做了混淆,仅供演示):

  1. 系统未登陆状态,302重定向到 auth0 的 OIDC认证服务器
https://samples.auth0.com/authorize?client_id=kbyuFDidLLm280LIw
&redirect_uri=https://openidconnect.net/callback
&scope=openid profile email phone address
&response_type=code
&state=bb88011dbf3707434d64553a1ab4f2337a5c9fad

这时候在auth0这里进行用户认证(也可以使用谷歌、facebook等用户体系认证,这里以谷歌为例)

  1. 认证通过后,应用拿到了授权码(code)后,从后台发起请求获取access_token 和 id_token
POST https://samples.auth0.com/oauth/token
grant_type=authorization_code
&client_id=kbyuFDidLLm280LIw
&client_secret=60Op4HFM0I8ajz0WdiStA
&redirect_uri=https://openidconnect.net/callback
&code=PbS1Rs5-R9PR21QYiaQg_23792iHAQnf

返回信息:

HTTP/1.1 200
Content-Type: application/json
{
  "access_token": "eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiaXNzIjoiaHR0cHM6Ly9zYW1wbGV...",
  "id_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJRCI6ImtieXVGRGlkTExt...",
  "scope": "openid profile email phone address",
  "expires_in": 86400,
  "token_type": "Bearer"
}

可以看到,第1步和第2步和标准的OAuth2认证是一模一样的,唯一不同的是第2步多返回了一个id_token字段,这个字段的jwt的payload解包后就是携带的用户信息。

  1. 验证id_token的jwt签名
    验证通过后的解包数据:
{
 "clientID": "kbyuFDidLLm280LIw",
 "created_at": "2024-09-11T12:06:05.079Z",
 "email": "foobar@gmail.com",
 "email_verified": true,
 "family_name": "foo",
 "given_name": "bar",
 "identities": [
  {
   "provider": "google-oauth2",
   "user_id": "10202",
   "connection": "google-oauth2",
   "isSocial": true
  }
 ],
 "name": "foo bar",
 "nickname": "foobar",
 "picture": "https://lh3.googleusercontent.com/a/AC",
 "updated_at": "2024-09-11T14:41:09.966Z",
 "user_id": "google-oauth2|10202202",
 "user_metadata": {},
 "app_metadata": {},
 "iss": "https://samples.auth0.com/",
 "sub": "google-oauth2|1020220",
 "aud": "kbyuFDidLLm2",
 "iat": 1726065714,
 "exp": 1726101714
}

如果认证框架用的 spring security,则此时会自动将数据填入构造好的OidcUser对象中,就可以直接使用了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,427评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,551评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,747评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,939评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,955评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,737评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,448评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,352评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,834评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,992评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,133评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,815评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,477评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,022评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,147评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,398评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,077评论 2 355

推荐阅读更多精彩内容