OpenID Connect 是什麼?
July 7, 2020
大家好,今天我們來淺談什麼是 OpenID Connect。雖然對這名詞本身可能不太熟悉,但我想大家在使用一些服務的時候,都有體驗過像下面這樣的一個登入方式。
在大家網購時常用的 PChome 登入頁面,除了輸入 PChome 自家帳號跟密碼的選項以外,也有一個快速登入的選項。快速登入的選項中會有使用 Google 帳號登入、Apple 帳號登入等等的選擇。其實,像這樣可以讓使用者在其他平台上的帳號(以上面的例子來說是 Google、Apple),登入到另外的服務上(以上面的例子來說是 PChome),這件事情我們稱它為單一登入,英文會叫它 Single sign-on。單一登入的實現方式有很多種,而 OpenID Connect 就是能夠實作單一登入的技術之一。
在討論 OpenID Connect 之前,不能避開的 OAuth 2.0
OpenID Connect 是 OpenID Foundation 在 2014 年發布的 OpenID Connect Core 1.0 中定義的一個身分認證協議。而它的設計理念是以當時就已被廣為使用的 OAuth 2.0 的協議為基礎,再加上可以認證使用者的層次而成。為什麼會採取這樣的方式呢?我們先來看看 OAuth 2.0 的背景。
OAuth 2.0 (RFC 6749) 是 IETF 在 2012 年發布的一個為授權而設計的協議。為什麼會需要「授權」呢?這跟近年來網際網路和雲端服務的起飛,並促使各項服務間連結需求的增加有很大的關係。
先讓我來舉一個簡單的例子。
現在有一個使用者,就假定是我自己本身。我的行事曆資訊都放在我的 Google Calendar 上。我現在想要使用一個可以做到比 Google Calendar 還要多功能的第三方行事曆服務。這時候我就會想要讓這第三方行事曆服務得到我在 Google Calendar 上的行事曆資訊。
而如果是在一個只有帳號跟密碼的世界上,我就必須要把我的 Google 帳號和密碼告訴給這第三方服務行事曆服務,它才有辦法取得這些資訊。但如果我把帳號密碼告訴了第三方,它可能就可以在暗地裡竊取行事曆以外的資訊,像是在 Gmail 裡的機密資訊。這時候就出現了使用 Access Token 來解決這個問題的協議,OAuth 2.0。
Access Token 就像是一張兌換卷,每一張 Access Token 上都有寫「誰」「對誰」「給予什麼樣的權限」,如此一來就可以在不告訴對方帳號密碼的情況下,給予對方最低限度需要的權限。這就是為什麼 OAuth 2.0 被稱為是一個授權的協議。
在 OAuth 2.0 的世界中,我這個使用者被稱為 Resource Owner;第三方行事曆服務被稱之為 Client;有放我行事曆資訊的 Google Calendar 稱為 Resource Server;幫忙發 Access Token 的伺服器稱之為 Authorization Server,在這例子中就會是 Google。
從 OAuth 2.0 到 OpenID Connect
但是解決了一個問題,新的問題就又跑出來了。
因為 OAuth 2.0 的便利性,就出現了很多將 OAuth 2.0 用為使用者登入驗證方式的服務。 但大家千萬不能忘記 OAuth 2.0 只是一個定義如何使用 Access Token 來授權的協議,內容是沒有提到如何去認證一個使用者的登入。因此如果使用 OAuth 2.0 做為使用者登入的認證機制,就會有很多意想不到的資安問題發生。而再次的有人想出了一個在現有 OAuth 2.0 的協議基礎下發放 ID Token 的方法來解決這個問題,這就是我們今天的主題所討論的 OpenID Connect。
重新介紹今天的主角 -- OpenID Connect
因為 OpenID Connect 是以 OAuth 2.0 為基礎設計,因此使用方法上有很多的相似處。角色也是其中一個,只是在 OpenID Connect 中的 Client 有了一個新稱呼叫 Relying Party。Authorization Server 的新稱呼為 OpenID Provider,它除了可以發放 Access Token 外,同時也可以發放 ID Token。
OpenID Connect 的精華 -- ID Token
OpenID Connect 中定義的 ID Token 採取了 JWS(JSON Web Signature, RFC 7515)的規格。也因為採用了 JWS ,收到這 ID Token 的服務即可以透過它的數位簽章確保此使用者的身分的正確性。我個人是將 ID Token 比喻為可以被驗證的一張名片。
比如說當 Client 順利得到 ID Token 時,它的外觀會長的像是
eyJraWQiOiIxZTlnZGs3IiwiYWxnIjoiUlMyNTYifQ.ewogImlz
cyI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4
Mjg5NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAi
bi0wUzZfV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEz
MTEyODA5NzAsCiAibmFtZSI6ICJKYW5lIERvZSIsCiAiZ2l2ZW5fbmFtZSI6
ICJKYW5lIiwKICJmYW1pbHlfbmFtZSI6ICJEb2UiLAogImdlbmRlciI6ICJm
ZW1hbGUiLAogImJpcnRoZGF0ZSI6ICIwMDAwLTEwLTMxIiwKICJlbWFpbCI6
ICJqYW5lZG9lQGV4YW1wbGUuY29tIiwKICJwaWN0dXJlIjogImh0dHA6Ly9l
eGFtcGxlLmNvbS9qYW5lZG9lL21lLmpwZyIKfQ.rHQjEmBqn9Jre0OLykYNn
spA10Qql2rvx4FsD00jwlB0Sym4NzpgvPKsDjn_wMkHxcp6CilPcoKrWHcip
R2iAjzLvDNAReF97zoJqq880ZD1bwY82JDauCXELVR9O6_B0w3K-E7yM2mac
AAgNCUwtik6SjoSUZRcf-O5lygIyLENx882p6MtmwaL1hd6qn5RZOQ0TLrOY
u0532g9Exxcm-ChymrB4xLykpDj3lUivJt63eEGGN6DH5K6o33TcxkIjNrCD
4XB1CKKumZvCedgHHF3IAK4dVEDSUoGlH9z4pP_eWYNXvqQOjGs-rDaQzUHl
6cQQWNiDpWOl_lxXjQEvQ
(此例參考了 OpenID Connect Core 1.0 中的例子。)
乍看之下完全看不懂它在寫什麼,但是仔細一看會發現中間會有兩個 「.」 ,它們可以將這整個 ID Token 分為三大部分。
去閱讀 RFC 7515,文件裡有說明 JWS 的構成是
BASE64URL(UTF8(JWS Protected Header)) || '.' ||
BASE64URL(JWS Payload) || '.' ||
BASE64URL(JWS Signature)
我們就照他的意思將它們拆解後,用 base64url decode 就可以得到像以下的內容。
Header
Payload
Signature
(是一個二進位的數據,用來驗證 Header 和 Payload 內容的完整性。)
透過這樣的結構,Client 就可以從 Header 裡得到的公鑰資訊和演算法資訊,驗證內容的 ID Token 內容的正確性,並將其驗證結果使用在使用者註冊及登入認證之上。這就是 OpenID Connect 的精華所在。
以上是 OpenID Connect 的簡介。
結語
不管是哪一種單一登入的理念其實非常簡單。對於使用者,使用單一登入的技術,就可以只要記住一組帳號密碼即登入所有已經串接好的服務;對於服務提供者,可以讓使用者不需要每次都重新輸入相同的註冊資訊,進而降低開始使用他們服務的門檻。如此單一登入的技術帶給我了們強大的便利性,但同時也讓那一組帳號密碼的安全性更加受到注重。如果是一家企業被要求的安全性等級就會比起個人使用時更加嚴謹、更加的嚴格。大家不妨可以藉由這個機會,重新評估看看自己使用的帳號環境的安全性喔。
如果有任何問題,都歡迎在下方留言,或透過官網表單與我們聯繫。
喜歡這篇文章嗎?歡迎分享出去!