怎樣相信JWT是真實(shí)的?

在這篇文章中,我將分享一些關(guān)于JWT令牌的知識。具體來說,我將討論JWT的結(jié)構(gòu),以及如何通過驗(yàn)證簽名來信任令牌中的信息是真實(shí)的。

JWT令牌的結(jié)構(gòu)。

Json Web Token(JWT)包含某些聲明或事實(shí),例如頒發(fā)者,用戶,訪問類型和其他特定于應(yīng)用程序的屬性。假設(shè)令牌有效,應(yīng)用程序根據(jù)令牌中的事實(shí)或聲明授予或拒絕訪問權(quán)限。

簽名的JWT令牌由三部分組成:頭部,有效負(fù)載和簽名。各個(gè)部分用點(diǎn)分開。下面是我從jwt.io獲取的令牌的示例

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

JWT令牌的每個(gè)部分都是base64編碼的。例如,如果您獲取標(biāo)頭:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9,并將其提供給base64解碼器功能,則會得到以下內(nèi)容:{"alg":"HS256","typ":"JWT"}表示令牌是JWT令牌,并使用HMAC-SHA256算法對其進(jìn)行簽名。

JWT標(biāo)題

標(biāo)題基本上告訴您JWT是否已簽名。如果令牌未簽名,則“alg”的值將為“none”。如果它已簽名,則該值將指示用于對令牌進(jìn)行簽名的算法類型,如上例所示。驗(yàn)證令牌時(shí),應(yīng)確保令牌具有有效簽名,否則請勿接受。

JWT有效載荷

根據(jù)令牌的類型,有效負(fù)載可能包含不同類型的信息,我們稱之為聲明。例如,如果JWT是id令牌,則聲明可能包含有關(guān)用戶的信息,包括用戶名,id,電子郵件,姓名等...如果JWT是訪問令牌,則聲明還可以包括范圍,角色,受眾,等等...... JWT還可能包含特定于發(fā)行者或應(yīng)用程序的自定義聲明。例如,Azure AD允許您通過修改應(yīng)用程序清單來定義自定義聲明。所有索賠都是可選的。但其中一定數(shù)量已成為標(biāo)準(zhǔn)。有關(guān)標(biāo)準(zhǔn)聲明的列表,請查看此Wiki文檔JWT手冊的 3.2.1注冊聲明部分。

下面我展示了Microsoft Azure Active Directory發(fā)布的示例訪問令牌。

{
  "aud": "api://bafd76b5-ccb0-4e81-****-************",
  "iss": "https://sts.windows.net/91db64d0-e9d0-43a4-a34b-************/",
  "iat": 1560128459,
  "nbf": 1560128459,
  "exp": 1560132359,
  "acr": "1",
  "aio": "ATQAy/8LAAAAna3Zp9so64X3zDBfw1omazGdFgA+7aU/pqZ4C1K6Dg282U8h0rrv7AQ2NpW11QGu",
  "amr": [
    "pwd"
  ],
  "appid": "546e1552-cd97-48d1-****-************",
  "appidacr": "0",
  "family_name": "John",
  "given_name": "Doe",
  "hasgroups": "true",
  "ipaddr": "216.65.***.***",
  "name": "John Doe",
  "oid": "29c94cd3-f78c-4470-****-************",
  "onprem_sid": "S-1-5-21-1543824733-581343488-**********-*****",
  "roles": [
    "Admin"
  ],
  "scp": "",
  "sub": "FV-j2XdynjmjHq3VU5OwlmcqzXgGw**********_***",
  "tid": "91db64d0-e9d0-43a4-a34b-************",
  "unique_name": "johndoe@email.com",
  "upn": "johndoe@email.com",
  "uti": "zmDgejHyj0apCH********",
  "ver": "1.0"
}

讓我們看看上面例子中的一些聲明。

  • aud - audience:這表示目標(biāo)web api可以驗(yàn)證此訪問令牌并授予用戶 - John Doe訪問api。
  • iss - issuer:這表示發(fā)布訪問令牌的頒發(fā)者。在這種情況下,Azure Active Directory是頒發(fā)令牌的服務(wù)。
  • iat - issue at:這表示AAD發(fā)出令牌的時(shí)間。在這種情況下,令牌發(fā)布于:格林威治標(biāo)準(zhǔn)時(shí)間2019年6月9日星期日8:03:50。
  • nbf - 不在之前:這表示令牌有效的最早時(shí)間。如果時(shí)間早于nbf中的值,則令牌無效。在示例中,nbf = iat,這意味著令牌在發(fā)布時(shí)立即生效。但是,nbf可能大于iat。例如,您可以提前發(fā)出訪問令牌,但直到稍后才激活它。有關(guān)詳細(xì)信息,請參閱此帖子
  • exp - expire:表示令牌過期的時(shí)間。上述令牌將于2019年6月9日星期日格林尼治標(biāo)準(zhǔn)時(shí)間9:08:50到期。因此,令牌在發(fā)布時(shí)間后的一小時(shí)五分鐘內(nèi)有效。過期后,不應(yīng)再接受令牌。
  • amr - 身份驗(yàn)證方法參考:客戶端如何進(jìn)行身份驗(yàn)證?在這種情況下,客戶端使用用戶名和密碼進(jìn)行身份驗(yàn)證。根據(jù)openid連接規(guī)范,“使用此聲明的各方需要就所使用的值的含義達(dá)成一致,這可能是特定于上下文的。amr值是一個(gè)區(qū)分大小寫的字符串?dāng)?shù)組“。
  • sub - Subject:令牌斷言信息的主體。根據(jù)Microsoft的文檔,此值特定于特定的應(yīng)用程序ID。例如,“如果單個(gè)用戶使用兩個(gè)不同的客戶端ID登錄兩個(gè)不同的應(yīng)用程序,那么這些應(yīng)用程序?qū)⑹盏絻蓚€(gè)不同的主題聲明值”。
  • scp - 作用域:這是一組值,用于定義具有訪問令牌的應(yīng)用程序可以代表用戶訪問的資源和權(quán)限的種類。在OAuth2協(xié)議之后,當(dāng)客戶端代表用戶請求訪問令牌時(shí),授權(quán)服務(wù)器應(yīng)向用戶顯示一個(gè)同意屏幕,其中列出了應(yīng)用程序請求的范圍。用戶需要給出同意,表明可以授予應(yīng)用程序?qū)Ψ秶甘镜馁Y源的訪問權(quán)限。

示例中的某些其他聲明特定于Azure Active Directory。有關(guān)它們的詳細(xì)信息,請查看文檔

id令牌的有效負(fù)載類似于訪問令牌的有效負(fù)載。id令牌具有更多關(guān)于用戶的聲明,而不是授權(quán)。下面顯示了Microsoft Azure Active Directory發(fā)出的id令牌的示例。

{
  "aud": "546e1552-cd97-48d1-a9f4-************",
  "iss": "https://login.microsoftonline.com/91db64d0-e9d0-****-****-************/v2.0",
  "iat": 1560128457,
  "nbf": 1560128457,
  "exp": 1560132357,
  "aio": "ATQAy/8LAAAA7U6jE1sIGgx/SMN5yYGYEJJvEx+u4GoMMLP5OTDfs4j1wcCPa/*************",
  "name": "John Doe",
  "nonce": "19e9904a-46b4-4dfe-a7a7-f068a637d1a2",
  "oid": "29c94cd3-f78c-4470-89df-************",
  "preferred_username": "johndoe@email.com",
  "sub": "8V2XFRo4ea8GYl7are8FanR7vFNn6HnhO_*********",
  "tid": "91db64d0-e9d0-43a4-a34b-************",
  "uti": "39Un3zlE-*************",
  "ver": "2.0"
}

請注意'oid'的值,它與訪問令牌中的值相同。根據(jù)Microsoft的文檔,“此ID可以跨應(yīng)用程序唯一標(biāo)識用戶 - 在同一用戶中簽名的兩個(gè)不同應(yīng)用程序?qū)⒃?code>oid聲明中獲得相同的值”。

JWT簽名

JWT的最后一部分是簽名。安全的JWT必須始終包含簽名。針對JWT的一些攻擊包括剝離簽名并使JWT成為未簽名的JWT。所以你應(yīng)該總是確保JWT有一個(gè)有效的簽名。

存在用于簽署包括HS256,RS256和ES256的JWT的若干算法。根據(jù)JSON Web算法(JWA)規(guī)范,實(shí)現(xiàn)必須支持HS256。該規(guī)范還推薦了另外兩種算法:RS256和ES256。其他算法是可選的。

簽署JWT主要有兩種不同的方式。第一種方法是使用密鑰散列消息認(rèn)證碼(HMAC)。HMAC實(shí)質(zhì)上意味著使用共享密鑰來簽名和驗(yàn)證簽名。基本上,一旦使用密鑰對JWT進(jìn)行簽名/加密,您需要知道能夠解密令牌的密鑰。這意味著,如果您的應(yīng)用程序擁有密鑰,并且您能夠使用密鑰解密令牌,則您知道該令牌已由預(yù)期的頒發(fā)者簽名,并且未被篡改。但是,對于HMAC,泄露秘密的機(jī)會隨著您需要支持的客戶數(shù)量而增加。HS256(HMAC + SHA-256)是一種使用HMAC的算法。

簽署JWT的第二種方式是使用公鑰/私鑰對。RS256(RSASSA + SHA256)是一種使用公鑰/私鑰對的算法。例如,在RSA算法的變體中,發(fā)行者擁有私鑰,并且每個(gè)消費(fèi)者獲得公鑰。使用公鑰,消費(fèi)者可以驗(yàn)證簽名,從而驗(yàn)證JWT的真實(shí)性。但是,使用者無法使用公鑰創(chuàng)建消息。因此,在共享密鑰上使用公鑰/私鑰對的優(yōu)點(diǎn)在于公鑰/私鑰中泄露秘密密鑰的風(fēng)險(xiǎn)較小,因?yàn)槟恍枰c消費(fèi)者共享密鑰。在RSA算法的另一個(gè)變體中,公鑰可以用于加密令牌,并且只有私鑰可以用于解密它。

您可以在JWT手冊中找到有關(guān)這些算法的詳細(xì)討論。

Azure AD使用公鑰/私鑰對進(jìn)行簽名和驗(yàn)證JWT。

Azure AD使用由公鑰和私鑰對組成的簽名密鑰。當(dāng)用戶登錄使用Azure AD進(jìn)行身份驗(yàn)證的應(yīng)用程序時(shí),Azure AD會創(chuàng)建一個(gè)安全令牌,其中包含有關(guān)該用戶的信息。在將Azure發(fā)送回應(yīng)用程序之前,此標(biāo)記由Azure AD使用其私鑰簽名。要驗(yàn)證令牌是否有效并且源自Azure AD,應(yīng)用程序必須使用Azure AD公開的公鑰來驗(yàn)證令牌的簽名,該公鑰包含在租戶的OpenID Connect發(fā)現(xiàn)文檔或SAML / WS-Fed 聯(lián)合元數(shù)據(jù)文檔中

在Azure Active Directory中簽名密鑰翻轉(zhuǎn)

你怎么能相信JWT是真實(shí)的?

如果您可以驗(yàn)證其簽名,您可以信任JWT是真實(shí)的。例如,Azure AD使用公鑰/私鑰對進(jìn)行簽名和驗(yàn)證訪問令牌。當(dāng)您的API從AAD收到ID或訪問令牌時(shí),令牌的標(biāo)頭包含獲取公鑰的信息。

{"typ":"JWT","alg":"RS256","kid":"CtfQC8Le-8NsC7oC2zQkZpcrfOc"}

在上面的json中,“kid”是公鑰的id,可用于驗(yàn)證令牌。您可以通過訪問此公共端點(diǎn)來驗(yàn)證公鑰是否存在并獲取實(shí)際密鑰:https//login.microsoftonline.com/common/discovery/keys

此外,如果您已有權(quán)訪問公鑰,則無需聯(lián)系授權(quán)服務(wù)器即可驗(yàn)證令牌。也許,您的應(yīng)用程序可以調(diào)用以檢索公鑰并將其緩存以供后續(xù)使用。請記住,AAD等服務(wù)會出于安全目的而轉(zhuǎn)動密鑰。如果您使用AAD,請查看文檔

攜帶簽名的訪問令牌(例如簽名的JWT)可以由資源服務(wù)器自己驗(yàn)證。為此,無需聯(lián)系授權(quán)服務(wù)器。

轉(zhuǎn):https://medium.com/@taithienbo/how-can-you-trust-a-jwt-to-be-authentic-2bd5124b243a

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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