在 Azure Active Directory B2C 中使用 OpenID 連線 進行 Web 登入

OpenID 連線 是以 OAuth 2.0 為基礎的驗證通訊協定,可用來安全地將使用者登入 Web 應用程式。 藉由使用 OpenID 連線 的 Azure Active Directory B2C (Azure AD B2C) 實作,您可以將 Web 應用程式中的註冊、登入和其他身分識別管理體驗外包給 Microsoft Entra ID。 本指南說明如何以與語言無關的方式執行這項操作。 它描述如何在不使用任何開放原始碼連結庫的情況下傳送和接收 HTTP 訊息。

注意

大部分的開放原始碼驗證連結庫都會取得並驗證應用程式的 JWT 令牌。 建議您探索這些選項,而不是實作您自己的程序代碼。 如需詳細資訊,請參閱 Microsoft 驗證連結庫 (MSAL)Microsoft 身分識別 Web 驗證連結庫的概觀。

OpenID 連線 擴充 OAuth 2.0 授權通訊協定,以作為驗證通訊協定。 此驗證通訊協定可讓您執行單一登入。 其引進「識別碼權杖」的概念,而這可讓用戶端確認使用者的身分識別,以及取得使用者的基本設定檔資訊。

OpenID 連線 也可讓應用程式安全地取得存取令牌。 您可以使用存取權杖來存取授權伺服器所保護的資源。 如果您要建置裝載於伺服器上並透過瀏覽器存取的 Web 應用程式,建議您 連線 OpenID。 如需令牌的詳細資訊,請參閱 Azure Active Directory B2C 中的令牌概觀

Azure AD B2C 擴充標準 OpenID 連線 通訊協定,以執行比簡單的驗證和授權還要多。 它引進了使用者流程參數,可讓您使用 OpenID 連線 將用戶體驗新增至您的應用程式,例如註冊、登入和配置檔管理。

傳送驗證要求

當您的 Web 應用程式需要驗證使用者並執行使用者流程時,它可以將使用者 /authorize 導向端點。 用戶會根據使用者流程採取動作。

在此要求中,用戶端會指出它需要從 參數中的 scope 使用者取得的許可權,並指定要執行的使用者流程。 若要瞭解要求的運作方式,請將要求貼到瀏覽器並加以執行。 將:

  • {tenant} 使用租用戶的名稱。
  • 90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6具有您在租用戶中註冊之應用程式的應用程式識別碼。
  • {application-id-uri}/{scope-name} 具有您在租用戶中註冊之應用程式的 [應用程式識別碼 URI] 和範圍。
  • {policy} 使用您在租使用者中擁有的原則名稱,例如 b2c_1_sign_in
GET /{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/authorize?
Host: {tenant}.b2clogin.com

client_id=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6
&response_type=code+id_token
&redirect_uri=https%3A%2F%2Fjwt.ms%2F
&response_mode=fragment
&scope=openid%20offline_access%20{application-id-uri}/{scope-name}
&state=arbitrary_data_you_can_receive_in_the_response
&nonce=12345
參數 必要 描述
{tenant} Yes Azure AD B2C 租用戶的名稱。 如果您使用 自訂網域,請將 取代 tenant.b2clogin.com 為您的網域,例如 fabrikam.com
{policy} Yes 應用程式執行的使用者流程或原則。 指定您在 Azure AD B2C 租使用者中建立的使用者流程名稱。 例如: b2c_1_sign_inb2c_1_sign_upb2c_1_edit_profile
client_id Yes Azure 入口網站指派給應用程式的應用程式標識碼。
nonce Yes 要求中所包含的值(由應用程式產生),這個值包含在產生的標識碼令牌中做為宣告。 然後,應用程式可以驗證此值以減輕令牌重新執行攻擊。 值通常是隨機化的唯一字串,可用來識別要求的來源。
response_type Yes 必須包含 OpenID 連線 的識別元令牌。 如果您的 Web 應用程式也需要權杖來呼叫 Web API,您可以使用 code+id_token
範圍 (scope) Yes 以空格分隔的範圍清單。 範圍 openid 指出登入用戶的許可權,並以標識元令牌的形式取得使用者的相關數據。 這個 offline_access 範圍是 Web 應用程式的選擇性範圍。 它表示您的應用程式需要重新 整理令牌 ,才能擴充資源的存取權。 https://{tenant-name}/{app-id-uri}/{scope}表示受保護資源的許可權,例如 Web API。 如需詳細資訊,請參閱 要求存取令牌
Prompt No 您需要的使用者互動類型。 目前 login唯一有效的值為 ,這會強制使用者在該要求上輸入其認證。
redirect_uri Yes redirect_uri應用程式的 參數,其中伺服器會將驗證回應傳送至您的應用程式。 它必須與您在 Azure 入口網站 中註冊的redirect_uri其中一個參數完全相符,不同之處在於它必須經過 URL 編碼。
response_mode No 方法,用來將產生的授權碼傳回您的應用程式。 它可以是 queryform_postfragment。 建議您使用 form_post 回應模式來獲得最佳安全性。
state No 值,您可以包含在授權伺服器在令牌回應中傳回的要求中。 它可以是您想要之任何內容的字串。 隨機產生的唯一值通常用於防止跨網站偽造要求攻擊。 狀態也可用來在驗證要求發生之前,將應用程式中用戶狀態的相關信息編碼,例如他們開啟的頁面。 如果您不想在 Azure 入口網站 中註冊多個重新導向 URL,您可以使用 state 參數來區分應用程式中的回應與 Azure AD B2C 服務,因為要求不同。
login_hint No 可用來預先填入登入頁面的登入名稱欄位。 如需詳細資訊,請參閱 預先填入登入名稱
domain_hint No 提供 Azure AD B2C 的提示,說明應該用於登入的社交識別提供者。 如果包含有效的值,使用者就會直接前往識別提供者登入頁面。 如需詳細資訊,請參閱 將登入重新導向至社交提供者
自訂參數 No 可搭配 自定義原則使用的自定義參數。 例如, 動態自定義頁面內容 URI索引鍵/值宣告解析程式

此時,系統會要求使用者完成工作流程。 使用者可能必須輸入其使用者名稱和密碼、使用社交身分識別登入,或註冊目錄。 視使用者流程的定義方式而定,可能會有任何其他步驟數目。

使用者完成使用者流程之後,會使用您在 參數中指定的 response_mode 方法,以指示redirect_uri的參數將回應傳回至您的應用程式。 上述每個案例的回應都相同,與使用者流程無關。

使用 response_mode=fragment 的成功回應看起來會像這樣:

GET https://jwt.ms/#
id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...
&code=AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrq...
&state=arbitrary_data_you_can_receive_in_the_response
參數 描述
id_token 應用程式所要求的標識碼令牌。 您可以使用識別碼令牌來驗證使用者的身分識別,並與用戶開始會話。
code 如果您使用 response_type=code+id_token,則應用程式要求的授權碼。 應用程式可以使用授權碼來要求目標資源的存取令牌。 授權碼通常會在大約 10 分鐘後到期。
state 如果要求中包含 state 參數,則回應中應該會出現相同的值。 應用程式應該確認 state 要求和回應中的值完全相同。

錯誤回應也可以傳送至 redirect_uri 參數,讓應用程式可以適當地處理它們:

GET https://jwt.ms/#
error=access_denied
&error_description=AADB2C90091%3a+The+user+has+cancelled+entering+self-asserted+information.%0d%0aCorrelation+ID%3a+xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx%0d%0aTimestamp%3a+xxxx-xx-xx+xx%3a23%3a27Z%0d%0a
&state=arbitrary_data_you_can_receive_in_the_response
參數 描述
error 程序代碼,可用來分類所發生的錯誤類型。
error_description 特定錯誤訊息,可協助識別驗證錯誤的根本原因。
state 如果要求中包含 state 參數,則回應中應該會出現相同的值。 應用程式應該確認 state 要求和回應中的值完全相同。

驗證標識碼令牌

只接收標識碼令牌並不足以驗證使用者。 驗證標識元令牌的簽章,並根據您的應用程式需求驗證令牌中的宣告。 Azure AD B2C 使用 JSON Web 令牌 (JWT) 和公鑰密碼編譯來簽署令牌,並確認其有效。

注意

大部分的開放原始碼驗證連結庫都會驗證應用程式的 JWT 令牌。 建議您探索這些選項,而不是實作您自己的驗證邏輯。 如需詳細資訊,請參閱 Microsoft 驗證連結庫 (MSAL)Microsoft 身分識別 Web 驗證連結庫的概觀。

Azure AD B2C 具有 OpenID 連線 元數據端點,可讓應用程式在運行時間取得 Azure AD B2C 的相關信息。 此資訊包括端點、令牌內容和令牌簽署金鑰。 B2C 租使用者中的每個使用者流程都有 JSON 元數據檔。 例如,中fabrikamb2c.onmicrosoft.com使用者流程的b2c_1_sign_in元數據檔位於:

https://fabrikamb2c.b2clogin.com/fabrikamb2c.onmicrosoft.com/b2c_1_sign_in/v2.0/.well-known/openid-configuration

此組態檔的其中一個屬性是 jwks_uri,其相同使用者流程的值會是:

https://fabrikamb2c.b2clogin.com/fabrikamb2c.onmicrosoft.com/b2c_1_sign_in/discovery/v2.0/keys

若要判斷用來簽署識別碼令牌的使用者流程,您有兩個選項。 首先,使用者流程名稱會包含在標識碼令牌中的宣告中 acr ,請參閱 代表使用者流程的宣告。 您的另一個選項是在發出要求時,將使用者流程編碼為 參數的值 state ,然後譯碼以判斷所使用的使用者流程。 任一種方法都有效。

從 OpenID 連線 元資料端點取得元數據檔之後,您可以使用 RSA 256 公鑰來驗證識別元令牌的簽章。 此端點可能會列出多個金鑰,每個金鑰都是 kid 由宣告所識別。 標識元令牌的標頭也包含 kid 宣告,指出哪些密鑰是用來簽署標識碼令牌。

若要驗證來自 Azure AD B2C 的權杖,您必須使用指數(e) 和模數(n) 來產生公鑰。 若要這樣做,您必須瞭解如何以您選擇的程式設計語言產生公鑰。 如需使用 RSA 通訊協定產生公鑰的官方檔,請參閱: https://tools.ietf.org/html/rfc3447#section-3.1

驗證標識元令牌的簽章之後,您需要驗證的各種宣告。 例如:

  • nonce驗證宣告以防止令牌重新執行攻擊。 其值應該是您在登入要求中指定的值。
  • aud驗證宣告,以確保已為您的應用程式發出標識元令牌。 其值應該是應用程式的應用程式識別碼。
  • iat驗證 和 exp 宣告,以確定標識元令牌尚未過期。

另外還有數個您應該執行的驗證。 驗證會在 OpenID 連線 Core 規格詳細說明。根據您的案例,您可能也想要驗證更多宣告。 一些常見的驗證包括:

  • 確定使用者/組織已註冊應用程式。
  • 請確定使用者具有適當的授權/許可權。
  • 請確定已發生特定的驗證強度,例如 Microsoft Entra 多重要素驗證。

驗證標識元令牌之後,您就可以開始與用戶進行會話。 您可以使用識別碼令牌中的宣告來取得應用程式中使用者的相關信息。 這項資訊的用途包括顯示、記錄和授權。

取得令牌

如果您需要 Web 應用程式只執行使用者流程,您可以略過接下來的幾節。 這些區段僅適用於需要對 Web API 進行驗證呼叫的 Web 應用程式,而 Web API 本身受到 Azure AD B2C 保護。

您可以藉由將要求/token傳送POST至端點,來兌換您取得的授權碼,response_type=code+id_token以取得令牌給所需的資源。 在 Azure AD B2C 中,您可以 藉由在要求中指定其範圍來要求其他 API 的存取令牌。

您也可以要求應用程式本身後端 Web API 的存取權杖。 在此情況下,您會使用應用程式的用戶端識別碼作為要求的範圍,這會導致該用戶端識別碼作為「物件」的存取令牌:

POST https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/token HTTP/1.1
Host: {tenant}.b2clogin.com
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&client_id=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6
&scope=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6 offline_access
&code=AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrq...
&redirect_uri=urn:ietf:wg:oauth:2.0:oob
參數 必要 描述
{tenant} Yes Azure AD B2C 租用戶的名稱
{policy} Yes 用來取得授權碼的使用者流程。 您無法在此要求中使用不同的使用者流程。 將此參數新增至查詢字串,而非 POST 主體。
client_id Yes Azure 入口網站指派給應用程式的應用程式標識碼。
client_secret 是,在 Web Apps 中 Azure 入口網站 中產生的應用程式密碼。 此流程會針對 Web 應用程式案例使用用戶端密碼,讓用戶端可以安全地儲存客戶端密碼。 針對原生應用程式(公用用戶端)案例,用戶端密碼無法安全地儲存,因此無法在此流程上使用。 如果使用客戶端密碼,請定期變更它。
code Yes 您在使用者流程開頭取得的授權碼。
grant_type Yes 授與的類型,必須為 authorization_code 授權碼流程。
redirect_uri No redirect_uri您收到授權碼之應用程式的 參數。
範圍 (scope) No 以空格分隔的範圍清單。 範圍 openid 指出登入用戶的許可權,並以id_token參數的形式取得使用者的相關數據。 它可用來取得應用程式本身後端 Web API 的令牌,其以與用戶端相同的應用程式識別元表示。 範圍 offline_access 指出您的應用程式需要重新整理令牌,才能擴充資源的存取權。

成功的權杖回應如下所示:

{
    "not_before": "1442340812",
    "token_type": "Bearer",
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...",
    "scope": "90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6 offline_access",
    "expires_in": "3600",
    "expires_on": "1644254945",
    "refresh_token": "AAQfQmvuDy8WtUv-sd0TBwWVQs1rC-Lfxa_NDkLqpg50Cxp5Dxj0VPF1mx2Z...",
}
參數 描述
not_before 令牌生效的 Epoch 時間。
token_type Token 類型值。 Bearer 是唯一支援的型別。
access_token 您要求的已簽署 JWT 令牌。
範圍 (scope) 令牌的有效範圍。
expires_in 存取令牌有效的時間長度(以秒為單位)。
expires_on 存取令牌無效的 Epoch 時間。
refresh_token OAuth 2.0 重新整理權杖。 應用程式可以使用此令牌,在目前令牌到期后取得更多令牌。 重新整理令牌可用來保留資源存取權一段時間。 範圍 offline_access 必須同時用於授權和令牌要求,才能接收重新整理令牌。

錯誤回應看起來如下:

{
    "error": "invalid_grant",
    "error_description": "AADB2C90080: The provided grant has expired. Please re-authenticate and try again. Current time: xxxxxxxxxx, Grant issued time: xxxxxxxxxx, Grant expiration time: xxxxxxxxxx\r\nCorrelation ID: xxxxxxxx-xxxx-xxxX-xxxx-xxxxxxxxxxxx\r\nTimestamp: xxxx-xx-16 xx:10:52Z\r\n"
}
參數 描述
error 可用來分類所發生錯誤類型的程序代碼。
error_description 訊息,可協助識別驗證錯誤的根本原因。

使用令牌

成功取得存取令牌之後,您可以在後端 Web API 的要求中使用令牌,方法是將令牌包含在標頭中 Authorization

GET /tasks
Host: mytaskwebapi.com
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...

重新整理令牌

存取令牌和標識碼令牌是短期的。 到期之後,您必須重新整理它們,才能繼續存取資源。 當您重新整理存取令牌時,Azure AD B2C 會傳回新的令牌。 重新整理的存取令牌將會更新 nbf (不是之前)、 iat (於 發行的) 和 exp (到期) 宣告值。 所有其他宣告值都類似於先前存取令牌中的宣告值。

將另一個 POST 要求提交至端點, /token 以重新整理令牌。 這次,請提供 refresh_token 參數, code 而不是 參數:

POST https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/token HTTP/1.1
Host: {tenant}.b2clogin.com
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&client_id=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6
&scope=openid offline_access
&refresh_token=AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrq...
&redirect_uri=urn:ietf:wg:oauth:2.0:oob
參數 必要 描述
{tenant} Yes Azure AD B2C 租用戶的名稱
{policy} Yes 用來取得原始重新整理令牌的使用者流程。 您無法在此要求中使用不同的使用者流程。 將此參數新增至查詢字串,而非 POST 主體。
client_id Yes Azure 入口網站指派給應用程式的應用程式標識碼。
client_secret 是,在 Web Apps 中 Azure 入口網站 中產生的應用程式密碼。 此流程會針對 Web 應用程式案例使用用戶端密碼,讓用戶端可以安全地儲存客戶端密碼。 針對原生應用程式(公用用戶端)案例,用戶端密碼無法安全地儲存,因此無法在此呼叫上使用。 如果使用客戶端密碼,請定期變更。
grant_type Yes 授與的類型,必須為 refresh_token 授權碼流程的這個部分。
refresh_token Yes 在流程第二部分中取得的原始重新整理令牌。 offline_access範圍必須同時用於授權和令牌要求,才能接收重新整理令牌。
redirect_uri No redirect_uri您收到授權碼之應用程式的 參數。
範圍 (scope) No 以空格分隔的範圍清單。 範圍 openid 指出登入用戶的許可權,並以標識元令牌的形式取得使用者的相關數據。 它可用來將令牌傳送至應用程式自己的後端 Web API,其以與用戶端相同的應用程式識別符表示。 範圍 offline_access 指出您的應用程式需要重新整理令牌,才能擴充資源的存取權。

成功的權杖回應如下所示:

{
    "not_before": "1442340812",
    "token_type": "Bearer",
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...",
    "scope": "90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6 offline_access",
    "expires_in": "3600",
    "refresh_token": "AAQfQmvuDy8WtUv-sd0TBwWVQs1rC-Lfxa_NDkLqpg50Cxp5Dxj0VPF1mx2Z...",
    "refresh_token_expires_in": "1209600"
}
參數 描述
not_before 令牌生效的 Epoch 時間。
token_type Token 類型值。 Bearer 是唯一支援的型別。
access_token 要求的已簽署 JWT 令牌。
範圍 (scope) 令牌的有效範圍。
expires_in 存取令牌有效的時間長度(以秒為單位)。
refresh_token OAuth 2.0 重新整理權杖。 應用程式可以使用此令牌,在目前令牌到期之後取得其他令牌。 重新整理令牌可用來保留資源存取權一段時間。
refresh_token_expires_in 重新整理令牌有效的時間長度(以秒為單位)。

錯誤回應看起來如下:

{
    "error": "invalid_grant",
    "error_description": "AADB2C90129: The provided grant has been revoked. Please reauthenticate and try again.\r\nCorrelation ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\r\nTimestamp: xxxx-xx-xx xx:xx:xxZ\r\n",
}
參數 描述
error 可用來分類所發生錯誤類型的程序代碼。
error_description 訊息,可協助識別驗證錯誤的根本原因。

傳送註銷要求

當您想要將使用者註銷應用程式時,還不足以清除應用程式的 Cookie,或結束與使用者的會話。 將使用者重新導向至 Azure AD B2C 以登出。如果您無法這麼做,使用者可能無法重新驗證您的應用程式,而不需要再次輸入其認證。 如需詳細資訊,請參閱 Azure AD B2C 會話行為

若要登出使用者,請將使用者重新導向至end_session_endpoint稍早所述的 OpenID 連線 元資料檔中所列的 :

GET https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/logout?post_logout_redirect_uri=https%3A%2F%2Fjwt.ms%2F
參數 必要 描述
{tenant} Yes Azure AD B2C 租用戶的名稱。 如果您使用 自訂網域,請將 取代 tenant.b2clogin.com 為您的網域,例如 fabrikam.com
{policy} Yes 您在授權要求中指定的使用者流程。 例如,如果使用者使用 b2c_1_sign_in 使用者流程登入,請在登入要求中指定 b2c_1_sign_in
id_token_hint No 先前發出的標識元令牌,用來傳遞至註銷端點,以提示使用者目前與客戶端驗證的會話。 可確保 id_token_hintpost_logout_redirect_uri 是 Azure AD B2C 應用程式設定中已註冊的回復 URL。 如需詳細資訊,請參閱 保護註銷重新導向
client_id 不* Azure 入口網站指派給應用程式的應用程式標識碼。

*當在註銷要求中使用 Application 隔離 SSO 組態和 [需要標識符令牌 ] 設定 No為 時,這是必要專案。
post_logout_redirect_uri No 成功註銷之後,用戶應該重新導向至的URL。如果未包含,Azure AD B2C 會向用戶顯示一般訊息。 除非您提供 id_token_hint,否則您不應該在 Azure AD B2C 應用程式設定中將此 URL 註冊為回復 URL。
state No 如果您在 state 授權要求中包含 參數,則授權伺服器會在回應 post_logout_redirect_uri中傳回相同的值。 應用程式應該確認 state 要求和回應中的值完全相同。

註銷要求后,Azure AD B2C 會使 Azure AD B2C Cookie 型會話失效,並嘗試從同盟識別提供者註銷。 如需詳細資訊,請參閱 單一註銷

保護您的註銷重新導向

註銷之後,不論您為應用程式指定的回復 URL 為何,用戶都會重新導向至您在 參數中指定的 post_logout_redirect_uri URI。 不過,如果傳遞有效 id_token_hint ,且 已開啟註銷要求 中的 [需要標識符令牌],Azure AD B2C 會在執行重新導向之前,先確認的值 post_logout_redirect_uri 符合其中一個應用程式設定的重新導向 URI。 如果未為應用程式設定相符的回復 URL,則會顯示錯誤訊息,且不會重新導向使用者。

若要在註銷要求中設定必要的標識符令牌,請參閱 在 Azure Active Directory B2C 中設定會話行為。

下一步