OpenID Connect 協(xié)議入門指南

如果要談單點(diǎn)登錄和身份認(rèn)證售睹,就不得不談OpenID Connect (OIDC)。最典型的使用實(shí)例就是使用Google賬戶登錄其他應(yīng)用,這一經(jīng)典的協(xié)議模式龙誊,為其他廠商的第三方登錄起到了標(biāo)桿的作用韭寸,被廣泛參考和使用春哨。

相關(guān)閱讀:
OAuth2.0 協(xié)議入門指南
SAML2.0入門指南

1. OpenID Connect簡介

OpenID Connect是基于OAuth 2.0規(guī)范族的可互操作的身份驗(yàn)證協(xié)議。它使用簡單的REST / JSON消息流來實(shí)現(xiàn)恩伺,和之前任何一種身份認(rèn)證協(xié)議相比赴背,開發(fā)者可以輕松集成。

OpenID Connect允許開發(fā)者驗(yàn)證跨網(wǎng)站和應(yīng)用的用戶,而無需擁有和管理密碼文件凰荚。OpenID Connect允許所有類型的客戶,包括基于瀏覽器的JavaScript和本機(jī)移動應(yīng)用程序,啟動登錄流動和接收可驗(yàn)證斷言對登錄用戶的身份燃观。

2. OpenID的歷史是什么?

OpenID Connect是OpenID的第三代技術(shù)便瑟。首先是原始的OpenID缆毁,它不是商業(yè)應(yīng)用,但讓行業(yè)領(lǐng)導(dǎo)者思考什么是可能的胳徽。OpenID 2.0設(shè)計(jì)更為完善积锅,提供良好的安全性保證。然而养盗,其自身存在一些設(shè)計(jì)上的局限性缚陷,最致命的是其中依賴方必須是網(wǎng)頁,但不能是本機(jī)應(yīng)用程序往核;此外它還要依賴XML箫爷,這些都會導(dǎo)致一些應(yīng)用問題。

OpenID Connect的目標(biāo)是讓更多的開發(fā)者使用聂儒,并擴(kuò)大其使用范圍虎锚。幸運(yùn)的是,這個目標(biāo)并不遙遠(yuǎn)衩婚,現(xiàn)在有很好的商業(yè)和開源庫來幫助實(shí)現(xiàn)身份驗(yàn)證機(jī)制窜护。

3. OIDC基礎(chǔ)

簡要而言,OIDC是一種安全機(jī)制非春,用于應(yīng)用連接到身份認(rèn)證服務(wù)器(Identity Service)獲取用戶信息柱徙,并將這些信息以安全可靠的方法返回給應(yīng)用。

在最初奇昙,因?yàn)镺penID1/2經(jīng)常和OAuth協(xié)議(一種授權(quán)協(xié)議)一起提及护侮,所以二者經(jīng)常被搞混。

  • OpenIDAuthentication储耐,即認(rèn)證羊初,對用戶的身份進(jìn)行認(rèn)證,判斷其身份是否有效什湘,也就是讓網(wǎng)站知道“你是你所聲稱的那個用戶”长赞;
  • OAuthAuthorization,即授權(quán)闽撤,在已知用戶身份合法的情況下涧卵,經(jīng)用戶授權(quán)來允許某些操作,也就是讓網(wǎng)站知道“你能被允許做那些事情”腹尖。
    由此可知柳恐,授權(quán)要在認(rèn)證之后進(jìn)行伐脖,只有確定用戶身份只有才能授權(quán)。

(身份驗(yàn)證)+ OAuth 2.0 = OpenID Connect

OpenID Connect是“認(rèn)證”和“授權(quán)”的結(jié)合乐设,因?yàn)槠浠?em>OAuth協(xié)議讼庇,所以OpenID-Connect協(xié)議中也包含了client_idclient_secret還有redirect_uri等字段標(biāo)識近尚。這些信息被保存在“身份認(rèn)證服務(wù)器”蠕啄,以確保特定的客戶端收到的信息只來自于合法的應(yīng)用平臺。這樣做是目的是為了防止client_id泄露而造成的惡意網(wǎng)站發(fā)起的OIDC流程戈锻。

舉個例子歼跟。某個用戶使用Facebook應(yīng)用“What online quiz best describes you?” ,該應(yīng)用可以通過Facebook賬號登錄格遭,則你可以在應(yīng)用中發(fā)起請求到“身份認(rèn)證服務(wù)器”(也就是Facebook的服務(wù)器)請求登錄哈街。這時你會看到如下界面,詢問是否授權(quán)拒迅。

image.png

OAuth中骚秦,這些授權(quán)被稱為scopeOpenID-Connect也有自己特殊的scope--openid ,它必須在第一次請求“身份鑒別服務(wù)器”(Identity Provider,簡稱IDP)時發(fā)送過去璧微。

4. OIDC流程

OAuth2提供了Access Token來解決授權(quán)第三方客戶端訪問受保護(hù)資源的問題作箍;相似的,OIDC在這個基礎(chǔ)上提供了ID Token來解決第三方客戶端標(biāo)識用戶身份認(rèn)證的問題前硫。OIDC的核心在于在OAuth2的授權(quán)流程中胞得,一并提供用戶的身份認(rèn)證信息(ID-Token)給到第三方客戶端,ID-Token使用JWT格式來包裝屹电,得益于JWTJSON Web Token)的自包含性阶剑,緊湊性以及防篡改機(jī)制,使得ID-Token可以安全的傳遞給第三方客戶端程序并且容易被驗(yàn)證嗤详。應(yīng)有服務(wù)器,在驗(yàn)證ID-Token正確只有瓷炮,使用Access-TokenUserInfo的接口換取用戶的更多的信息葱色。

有上述可知,OIDC是遵循OAuth協(xié)議流程娘香,在申請Access-Token的同時苍狰,也返回了ID-Token來驗(yàn)證用戶身份。

4.1 相關(guān)定義

  • EU:End User烘绽,用戶淋昭。
  • RP:Relying Party ,用來代指OAuth2中的受信任的客戶端安接,身份認(rèn)證和授權(quán)信息的消費(fèi)方翔忽;
  • OP:OpenID Provider,有能力提供EU身份認(rèn)證的服務(wù)方(比如OAuth2中的授權(quán)服務(wù)),用來為RP提供EU的身份認(rèn)證信息歇式;
  • ID-Token:JWT格式的數(shù)據(jù)驶悟,包含EU身份認(rèn)證的信息。
  • UserInfo Endpoint:用戶信息接口(受OAuth2保護(hù))材失,當(dāng)RP使用ID-Token訪問時痕鳍,返回授權(quán)用戶的信息,此接口必須使用HTTPS龙巨。

下面我們來看看OIDC的具體協(xié)議流程笼呆。
根據(jù)應(yīng)用客戶端的不同,OIDC的工作模式也應(yīng)該是不同的旨别。和OAuth類似诗赌,主要看是否客戶端能保證client_secret的安全性。

如果是JS應(yīng)用昼榛,其所有的代碼都會被加載到瀏覽器而暴露出來境肾,沒有后端可以保證client_secret的安全性,則需要是使用默認(rèn)模式流程(Implicit Flow)胆屿。

如果是傳統(tǒng)的客戶端應(yīng)用奥喻,后端代碼和用戶是隔離的,能保證client_secret的不被泄露非迹,就可以使用授權(quán)碼模式流程(Authentication Flow)环鲤。

此外還有混合模式流程(Hybrid Flow),簡而言之就是以上二者的融合憎兽。

OAuth2中還有口令模式和“應(yīng)有訪問模式”的方式來獲取Access Token(關(guān)于OAuth2的內(nèi)容冷离,可以參見OAuth2.0 協(xié)議入門指南),為什么OIDC沒有擴(kuò)展這些方式呢?
"口令模式"是需要用戶提供賬號和口令給RP的纯命,既然都已經(jīng)有用戶名和口令了西剥,就不需要在獲取什么用戶身份了。至于“應(yīng)有訪問模式”亿汞,這種方式不需要用戶參與瞭空,也就無需要認(rèn)證和獲取用戶身份了。這也能反映授權(quán)和認(rèn)證的差異疗我,以及只使用OAuth2來做身份認(rèn)證的事情是遠(yuǎn)遠(yuǎn)不夠的咆畏,也是不合適的。

4.2 授權(quán)碼模式流程

授權(quán)碼模式流程

OAuth認(rèn)證流程類似

  1. RP發(fā)送一個認(rèn)證請求給OP吴裤,其中附帶client_id旧找;
  2. OP對EU進(jìn)行身份認(rèn)證;
  3. OP返回響應(yīng)麦牺,發(fā)送授權(quán)碼給RP钮蛛;
  4. RP使用授權(quán)碼向OP索要ID-Token和Access-Token鞭缭,RP驗(yàn)證無誤后返回給RP;
  5. RP使用Access-Token發(fā)送一個請求到UserInfo EndPoint愿卒; UserInfo EndPoint返回EU的Claims缚去。

4.2.1 基于Authorization Code的認(rèn)證請求

RP使用OAuth2的Authorization-Code的方式來完成用戶身份認(rèn)證,所有的Token都是通過OP的Token EndPoint(OAuth2中定義)來發(fā)放的琼开。構(gòu)建一個OIDC的Authentication Request需要提供如下的參數(shù):

  • scope:必須易结。OIDC的請求必須包含值為“openid”的scope的參數(shù)。
  • response_type:必選柜候。同OAuth2搞动。
  • client_id:必選。同OAuth2渣刷。
  • redirect_uri:必選鹦肿。同OAuth2。
  • state:推薦辅柴。同OAuth2箩溃。防止CSRF, XSRF。

示例如下:

GET /authorize?
    response_type=code
    &scope=openid%20profile%20email
    &client_id=s6BhdRkqt3
    &state=af0ifjsldkj
    &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb HTTP/1.1
  Host: server.example.com

4.2.2 基于Authorization Code的認(rèn)證請求的響應(yīng)

在OP接收到認(rèn)證請求之后碌嘀,需要對請求參數(shù)做嚴(yán)格的驗(yàn)證涣旨,具體的規(guī)則參見http://openid.net/specs/openid-connect-core-1_0.html#AuthRequestValidation,驗(yàn)證通過后引導(dǎo)EU進(jìn)行身份認(rèn)證并且同意授權(quán)股冗。在這一切都完成后霹陡,會重定向到RP指定的回調(diào)地址(redirect_uri),并且把codestate參數(shù)傳遞過去止状。比如:

  HTTP/1.1 302 Found
  Location: https://client.example.org/cb?
    code=SplxlOBeZQQYbYS6WxSbIA
    &state=af0ifjsldkj

4.2.3 獲取ID Token

RP使用上一步獲得的code來請求Token EndPoint烹棉,這一步桶OAuth2,就不再展開細(xì)說了怯疤。然后Token EndPoint會返回響應(yīng)的Token浆洗,其中除了OAuth2規(guī)定的部分?jǐn)?shù)據(jù)外,還會附加一個id_token的字段集峦。id_token字段就是上面提到的ID Token伏社。例如:

  HTTP/1.1 200 OK
  Content-Type: application/json
  Cache-Control: no-store
  Pragma: no-cache

  {
   "access_token": "SlAV32hkKG",
   "token_type": "Bearer",
   "refresh_token": "8xLOxBtZp8",
   "expires_in": 3600,
   "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzc
     yI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5
     NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZ
     fV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5Nz
     AKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6q
     Jp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJ
     NqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7Tpd
     QyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoS
     K5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4
     XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg"
  }

其中看起來一堆亂碼的部分就是JWT格式的ID-Token。在RP拿到這些信息之后少梁,需要對id_token以及access_token進(jìn)行驗(yàn)證(具體的規(guī)則參見http://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidationhttp://openid.net/specs/openid-connect-core-1_0.html#ImplicitTokenValidation)洛口。至此矫付,可以說用戶身份認(rèn)證就可以完成了凯沪,后續(xù)可以根據(jù)UserInfo EndPoint獲取更完整的信息。

4.2.4 安全令牌 ID-Token

上面提到過OIDCOAuth2最主要的擴(kuò)展就是提供了ID-Token买优。下面我們就來看看ID-Token的主要構(gòu)成:

  • iss = Issuer Identifier:必須妨马。提供認(rèn)證信息者的唯一標(biāo)識挺举。一般是Url的host+path部分;
  • sub = Subject Identifier:必須烘跺。iss提供的EU的唯一標(biāo)識湘纵;最長為255個ASCII個字符;
  • aud = Audience(s):必須滤淳。標(biāo)識ID-Token的受眾梧喷。必須包含OAuth2的client_id;
  • exp = Expiration time:必須脖咐。ID-Token的過期時間铺敌;
  • iat = Issued At Time:必須。JWT的構(gòu)建的時間屁擅。
  • auth_time = AuthenticationTime:EU完成認(rèn)證的時間偿凭。如果RP發(fā)送認(rèn)證請求的時候攜帶max_age的參數(shù),則此Claim是必須的派歌。
  • nonce:RP發(fā)送請求的時候提供的隨機(jī)字符串弯囊,用來減緩重放攻擊,也可以來關(guān)聯(lián)ID-Token和RP本身的Session信息胶果。
  • acr = Authentication Context Class Reference:可選匾嘱。表示一個認(rèn)證上下文引用值,可以用來標(biāo)識認(rèn)證上下文類稽物。
  • amr = Authentication Methods References:可選奄毡。表示一組認(rèn)證方法。
  • azp = Authorized party:可選贝或。結(jié)合aud使用吼过。只有在被認(rèn)證的一方和受眾(aud)不一致時才使用此值,一般情況下很少使用咪奖。
{
   "iss": "https://server.example.com",
   "sub": "24400320",
   "aud": "s6BhdRkqt3",
   "nonce": "n-0S6_WzA2Mj",
   "exp": 1311281970,
   "iat": 1311280970,
   "auth_time": 1311280969,
   "acr": "urn:mace:incommon:iap:silver"
  }

另外ID Token必須使用JWT(JSON Web Token)進(jìn)行簽名和JWE(JSON Web Encryption)加密盗忱,從而提供認(rèn)證的完整性、不可否認(rèn)性以及可選的保密性羊赵。關(guān)于JWT的更多內(nèi)容趟佃,請參看JSON Web Token - 在Web應(yīng)用間安全地傳遞信息

4.2 默認(rèn)模式流程

默認(rèn)模式流程

默認(rèn)流程和OAuth中的類似,只不過也是添加了ID-Token的相關(guān)內(nèi)容昧捷。

這里需要說明的是:OIDC的說明文檔里很明確的說明了用戶的相關(guān)信息都要使用JWT形式編碼闲昭。在JWT中,不應(yīng)該在載荷里面加入任何敏感的數(shù)據(jù)靡挥。如果傳輸?shù)氖怯脩舻腢ser ID序矩。這個值實(shí)際上不是什么敏感內(nèi)容,一般情況下被知道也是安全的跋破。

但是現(xiàn)在工業(yè)界已經(jīng)不推薦使用OAuth默認(rèn)模式簸淀,而推薦使用不帶client_Secret授權(quán)碼模式瓶蝴。

4.3 混合模式

混合模式簡而言之就是以上提到的兩種模式的混合,不過也有一些小的改變租幕,就是允許直接向客戶端返回Access-Token舷手。

業(yè)界普遍認(rèn)為,后端傳遞Token(比如服務(wù)器之間通信)要比前端(比如頁面之間)可靠劲绪,所以如果直接返回令牌的情況下會把令牌的過期時間設(shè)置較短男窟,但是比較

UserInfo Endpoint

可能有的讀者發(fā)現(xiàn)了,ID-Token只有sub是和EU相關(guān)的贾富,這在一般情況下是不夠的蝎宇,必須還需要EU的用戶名,頭像等其他的資料祷安,OIDC提供了一組公共的cliams姥芥,來提供更多用戶的信息,這就是——UserIndo EndPoin汇鞭。

在RP得到Access Token后可以請求此資源凉唐,然后獲得一組EU相關(guān)的Claims,這些信息可以說是ID-Token的擴(kuò)展霍骄,ID-Token中只需包含EU的唯一標(biāo)識sub即可(避免ID Token過于龐大和暴露用戶敏感信息)台囱,然后在通過此接口獲取完整的EU的信息。此資源必須部署在TLS之上读整,例如:

  GET /userinfo HTTP/1.1
  Host: server.example.com
  Authorization: Bearer SlAV32hkKG

成功之后響應(yīng)如下:

  HTTP/1.1 200 OK
  Content-Type: application/json

  {
   "sub": "248289761001",
   "name": "Jane Doe",
   "given_name": "Jane",
   "family_name": "Doe",
   "preferred_username": "j.doe",
   "email": "janedoe@example.com",
   "picture": "http://example.com/janedoe/me.jpg"
  }

其中sub代表EU的唯一標(biāo)識簿训,這個claim是必須的,其他的都是可選的米间。

參考文獻(xiàn)

更多關(guān)于OIDC的內(nèi)容强品,請閱讀以下文章:

  1. https://www.onelogin.com/blog/openid-connect-explained-in-plain-english
  2. http://www.cnblogs.com/linianhui/archive/2017/05/30/openid-connect-core.html
  3. JSON Web Token - 在Web應(yīng)用間安全地傳遞信息
  4. OAuth2.0 協(xié)議入門指南
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市屈糊,隨后出現(xiàn)的幾起案子的榛,更是在濱河造成了極大的恐慌,老刑警劉巖逻锐,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夫晌,死亡現(xiàn)場離奇詭異,居然都是意外死亡昧诱,警方通過查閱死者的電腦和手機(jī)晓淀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盏档,“玉大人凶掰,你說我怎么就攤上這事。” “怎么了锄俄?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長勺拣。 經(jīng)常有香客問我奶赠,道長,這世上最難降的妖魔是什么药有? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任毅戈,我火速辦了婚禮,結(jié)果婚禮上愤惰,老公的妹妹穿的比我還像新娘苇经。我一直安慰自己,他們只是感情好宦言,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布扇单。 她就那樣靜靜地躺著,像睡著了一般奠旺。 火紅的嫁衣襯著肌膚如雪蜘澜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天响疚,我揣著相機(jī)與錄音鄙信,去河邊找鬼。 笑死忿晕,一個胖子當(dāng)著我的面吹牛装诡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播践盼,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼鸦采,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了咕幻?” 一聲冷哼從身側(cè)響起赖淤,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谅河,沒想到半個月后咱旱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡绷耍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年吐限,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片褂始。...
    茶點(diǎn)故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡诸典,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出崎苗,到底是詐尸還是另有隱情狐粱,我是刑警寧澤舀寓,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站肌蜻,受9級特大地震影響互墓,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蒋搜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一篡撵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧豆挽,春花似錦育谬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至娘侍,卻和暖如春宿刮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背私蕾。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工僵缺, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人踩叭。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓磕潮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親容贝。 傳聞我的和親對象是個殘疾皇子自脯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內(nèi)容