Share via


Azure Active Directory B2C 中的 OAuth 2.0 授權碼流程

在安裝於裝置上的應用程式中,您可以使用 OAuth 2.0 授權碼授與來存取受保護的資源,例如 Web API。 您可以使用 Azure Active Directory B2C (Azure AD B2C) 的 OAuth 2.0 實作,將註冊、登入及其他身分識別管理工作新增至您的單一頁面、行動及桌面應用程式。 這篇文章是與語言無關。 在本文中,我們將說明如何傳送及接收 HTTP 訊息,但不使用任何開放原始碼程式庫。 可能的話,建議您使用支援的 Microsoft 驗證程式庫 (MSAL)。請參閱使用 MSAL 的範例應用程式

如需 OAuth 2.0 授權碼流程的說明,請參閱 OAuth 2.0 規格的 4.1 節。 在大多數應用程式類型 (包括 Web 應用程式、單一頁面應用程式,以及原生安裝的應用程式) 中,您都能用其執行驗證及授權作業。 您可以使用 OAuth 2.0 授權碼流程,安全地為您的應用程式取得存取權杖和重新整理權杖,而這些存取權杖可用來存取授權伺服器所保護的資源。 一旦存取權杖到期 (通常在一小時後),重新整理權杖即可讓用戶端取得新的存取 (和重新整理) 權杖。

本文著重在公開用戶端 OAuth 2.0 授權碼流程。 公開用戶端是指不可信任會安全地維護密碼完整性的任何用戶端應用程式。 這包括單一頁面應用程式、行動應用程式、桌面應用程式,以及基本上任何未在伺服器上執行的應用程式。

注意

若要使用 Azure AD B2C 將身分識別管理新增至 Web 應用程式,請使用 OpenID Connect,而不是 OAuth 2.0。

Azure AD B2C 擴充標準的 OAuth 2.0 流程,功能更強大,而不僅止於簡單的驗證和授權。 並引進使用者流程參數。 透過使用者流程,您可以利用 OAuth 2.0 來將使用者體驗新增至應用程式,例如註冊、登入和設定檔管理。 使用 OAuth 2.0 通訊協定的識別提供者包括AmazonMicrosoft Entra識別碼FacebookGitHubGoogleLinkedIn

若要嘗試本文中的 HTTP 要求:

  1. {tenant} 取代為您的 Azure AD B2C 租用戶名稱。
  2. 90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6 取代為您先前在 Azure AD B2C 租用戶中註冊應用程式的應用程式識別碼。
  3. {policy} 取代為您在租用戶中建立的原則名稱,例如 b2c_1_sign_in

單頁應用程式所需的重新導向 URI 設定

單頁應用程式的授權碼流程需要一些額外的設定。 請依照指示來建立單一頁面應用程式,以正確地將您的重新導向 URI 標示為針對 CORS 啟用。 若要更新現有的重新導向 URI 以啟用 CORS,您可以在 [應用程式註冊] 的 [驗證] 索引標籤的 [Web] 區段中,按一下 [移轉] 提示。或者,您也可以開啟應用程式註冊資訊清單編輯器,並將重新導向 URI 的 type 欄位設定為 replyUrlsWithType 區段中的 spa

spa 重新導向類型可與隱含流程回溯相容。 目前使用隱含流程來取得權杖的應用程式可移至 spa 重新導向 URI 類型,而不會發生問題,並可繼續使用隱含流程。

1. 取得授權碼

授權碼流程始於用戶端將使用者導向 /authorize 端點。 這是使用者在流程中會採取動作的互動部分。 在此要求中,用戶端會在 scope 參數中指出必須向使用者索取的權限。 下列範例 (為方便閱讀,使用了分行符號) 示範如何取得授權碼。 如果您要測試此 GET HTTP 要求,請使用您的瀏覽器。

GET https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/authorize?
client_id=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6
&response_type=code
&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob
&response_mode=query
&scope=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6%20offline_access%20https://{tenant-name}/{app-id-uri}/{scope}
&state=arbitrary_data_you_can_receive_in_the_response
&code_challenge=YTFjNjI1OWYzMzA3MTI4ZDY2Njg5M2RkNmVjNDE5YmEyZGRhOGYyM2IzNjdmZWFhMTQ1ODg3NDcxY2Nl
&code_challenge_method=S256
參數 必要? 描述
{tenant} 必要 Azure AD B2C 租用戶的名稱
{policy} 必要 要執行的使用者流程。 指定您在 Azure AD B2C 租用戶中建立的使用者流程名稱。 例如:b2c_1_sign_inb2c_1_sign_upb2c_1_edit_profile
client_id 必要 Azure 入口網站中指派給應用程式的應用程式識別碼。
response_type 必要 回應類型,必須針對授權碼流程來加入 code。 如果您在回應類型中包括識別碼權杖 (例如 code+id_token),則會收到識別碼權杖,而在此情況下,範圍需要包括 openid
redirect_uri 必要 應用程式的重新導向 URI,您的應用程式會在此處傳送及接收驗證回應。 它必須與您在入口網站中註冊的其中一個重新導向 URI 完全相符,不過必須是 URL 編碼格式。
scope 必要 範圍的空格分隔清單。 openid 範圍指示使用識別碼權杖形式的權限,以登入使用者及取得使用者相關資料。 對於 Web 應用程式,offline_access 範圍是選擇性的。 這表示您的應用程式需要重新整理權杖,才能延長資源的存取權。用戶端識別碼表示簽發的權杖僅供 Azure AD B2C 註冊的用戶端使用。 https://{tenant-name}/{app-id-uri}/{scope} 指出受保護資源的權限 (例如 WEB API)。 如需詳細資訊,請參閱要求存取權杖
response_mode 建議 用來將產生的授權碼傳回至應用程式的方法。 可以是 queryform_postfragment
狀態 建議 包含在要求中的值,可以是您想要使用的任何內容字串。 通常會使用隨機產生的唯一值,以防止跨網站偽造要求攻擊。 在驗證要求出現之前,也會使用此狀態將應用程式中使用者狀態的相關資訊編碼。 例如,使用者所在的頁面,或正在執行的使用者流程。
Prompt 選擇性 需要的使用者互動類型。 目前,唯一有效的值是 login,可強制使用者針對該要求輸入其認證。 單一登入將沒有作用。
code_challenge 建議 / 必要 用來透過「代碼交換的證明金鑰」(PKCE) 保護授權碼授與。 如果包含 code_challenge_method,則為必要參數。 您必須在應用程式中新增邏輯,才能產生 code_verifiercode_challengecode_challengecode_verifier 的 Base64 URL 編碼 SHA256 雜湊。 您會將 code_verifier 儲存在應用程式中以供稍後使用,並將 code_challenge 連同授權要求一起傳送。 如需詳細資訊,請參閱 PKCE RFC。 現在建議所有的應用程式類型,包括原生應用程式、SPA 和機密用戶端 (例如 Web 應用程式)。
code_challenge_method 建議 / 必要 用來為 code_challenge 參數編碼 code_verifier 的方法。 這應該S256,但如果基於某些原因而導致用戶端無法支援 SHA256,則規格允許使用 plain

如果您排除 code_challenge_method,但仍包含 code_challenge,那麼會假設 code_challenge 為純文字。 Microsoft 身分識別平台同時支援 plainS256。 如需詳細資訊,請參閱 PKCE RFC。 這是使用授權碼流程單頁應用程式所需的必要條件。
login_hint No 可以用來預先填入登入頁面的 [登入名稱] 欄位。 如需詳細資訊,請參閱預先填入登入名稱
domain_hint No 向 Azure AD B2C 提供應該用於登入的社交識別提供者相關提示。 如果包含有效的值,使用者會直接前往識別提供者登入頁面。 如需詳細資訊,請參閱將登入重新導向至社交提供者
自訂參數 No 可與自訂原則搭配使用的自訂參數。 例如,動態自訂頁面內容 URI機碼值宣告解析程式

此時會要求使用者完成使用者流程的工作流程。 這可能會牽涉到讓使用者輸入自己的使用者名稱及密碼、以社交身分識別登入、註冊目錄,或是其他任何數目的步驟。 使用者動作取決於使用者流程的定義方式。

使用者完成使用者流程之後,Microsoft Entra識別碼會在您用於 redirect_uri 的值傳回應用程式的回應。 它會使用 response_mode 參數中指定的方法。 對於每個使用者動作情節來說,回應完全相同,與已執行的使用者流程無關。

使用 response_mode=query 的成功回應如下所示:

GET urn:ietf:wg:oauth:2.0:oob?
code=AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrq...        // the authorization_code, truncated
&state=arbitrary_data_you_can_receive_in_the_response                // the value provided in the request
參數 描述
code 應用程式所要求的授權碼。 應用程式可以使用授權碼來要求目標資源的存取權杖。 授權碼的存留期很短。 通常會在大約 10 分鐘後過期。
狀態 如需完整說明,請參閱上一節的表格。 如果要求中包含 state 參數,則回應中應該會出現相同的值。 應用程式應該驗證要求和回應中的 state 值完全相同。

錯誤回應也能傳送到重新導向 URI,以便讓應用程式能夠適當地處理它們:

GET urn:ietf:wg:oauth:2.0:oob?
error=access_denied
&error_description=The+user+has+cancelled+entering+self-asserted+information
&state=arbitrary_data_you_can_receive_in_the_response
參數 描述
error 可用於將發生的錯誤類型分類的錯誤碼字串。 您也可以使用此字串對錯誤做出反應。
error_description 可協助您識別驗證錯誤根本原因的特定錯誤訊息。
狀態 如需完整說明,請參閱前一個表格。 如果要求中包含 state 參數,則回應中應該會出現相同的值。 應用程式應該驗證要求和回應中的 state 值完全相同。

2. 取得存取權杖

既然已取得授權碼,您可以將 POST 要求傳送至 /token 端點,針對所需的資源來兌換權杖的 code。 在 Azure AD B2C 中,您可以在要求中指定範圍,以要求其他 API 的存取權杖

您也可以使用應用程式的用戶端識別碼作為要求範圍,以要求應用程式本身的後端 Web API 的存取權杖 (這會產生具有該用戶端識別碼的存取權杖做為「受眾」):

POST https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/token HTTP/1.1

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
&code_verifier=ThisIsntRandomButItNeedsToBe43CharactersLong 
參數 必要? 描述
{tenant} 必要 Azure AD B2C 租用戶的名稱
{policy} 必要 用來取得授權碼的使用者流程。 您無法在此要求中使用不同的使用者流程。
client_id 必要 Azure 入口網站中指派給應用程式的應用程式識別碼。
client_secret 是,在 Web Apps 中 Azure 入口網站中產生的應用程式祕密。 用戶端密碼是用於 Web 應用程式情節的流程中,用戶端可以在其中安全地儲存用戶端密碼。 針對原生應用程式 (公用用戶端) 情節,無法安全地儲存用戶端密碼,因此不會在此呼叫上使用用戶端密碼。 如果您使用用戶端密碼,請定期變更。
grant_type 必要 授與類型。 在授權碼流程中,授與類型必須的 authorization_code
scope 建議 以空格分隔的範圍清單。 單一範圍值表示Microsoft Entra要求的許可權兩者識別碼。 使用用戶端識別碼作為範圍時,表示您的應用程式需要可針對您自己的服務或 Web API 使用的存取權杖 (以相同的用戶端識別碼表示)。 offline_access 範圍表示您的應用程式需要重新整理權杖,才能長久存取資源。 您也可以使用 openid 範圍從 Azure AD B2C 要求識別碼權杖。
code 必要 您從 /authorize 端點取得的授權碼。
redirect_uri 必要 應用程式的重新導向 URI,您已在此處收到授權碼。
code_verifier 建議使用 用來取得授權碼的相同 code_verifier。 如果在授權碼授與要求中使用 PKCE,則此為必要參數。 如需詳細資訊,請參閱 PKCE RFC

如果您要測試此 POST HTTP 要求,可以使用任何 HTTP 用戶端,例如 Microsoft PowerShellPostman

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

{
    "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...",
}
參數 Description
not_before 權杖生效的時間 (以新紀元 (Epoch) 時間表示)。
token_type 權杖類型值。 Microsoft Entra識別碼支援的唯一類型是持有人。
access_token 您所要求的已簽署 JSON Web 權杖 (JWT)。
scope 權杖有效的範圍。 您也可以使用範圍來快取權杖,以供稍後使用。
expires_in 權杖的有效時間長度 (以秒為單位)。
refresh_token OAuth 2.0 重新整理權杖。 應用程式在目前的權杖過期之後,可以使用這個權杖來取得其他權杖。 重新整理權杖是長期權杖。 您可以使用它們來長時間持續存取資源。 如需詳細資訊,請參閱 Azure AD B2C 權杖參考

錯誤回應如下所示:

{
    "error": "access_denied",
    "error_description": "The user revoked access to the app.",
}
參數 描述
error 可用於將發生的錯誤類型分類的錯誤碼字串。 您也可以使用此字串對錯誤做出反應。
error_description 可協助您識別驗證錯誤根本原因的特定錯誤訊息。

3. 使用權杖

既然已成功取得存取權杖,在對後端 Web API 發出的要求中,您可以將權杖加入 Authorization 標頭中,即可使用權杖:

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

4. 重新整理權杖

存取權杖和識別碼權杖的存留期短暫。 權杖過期之後,您必須重新整理權杖,才能繼續存取資源。 當您重新整理存取權杖時,Azure AD B2C 會傳回新的權杖。 存取權杖重新整理後,nbf (宣告時間)、iat (簽發時間) 和 exp (到期時間) 宣告值也都已更新過了。 所有其他宣告值都會與原先簽發的存取權杖相同。

若要重新整理權杖,請向 /token 端點提交另一個 POST 要求。 但這次要提供 refresh_token,而不是 code

POST https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/token HTTP/1.1

Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&client_id=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6
&scope=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6 offline_access
&refresh_token=AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrq...
&redirect_uri=urn:ietf:wg:oauth:2.0:oob
參數 必要? 描述
{tenant} 必要 Azure AD B2C 租用戶的名稱
{policy} 必要 用來取得原始重新整理權杖的使用者流程。 您無法在此要求中使用不同的使用者流程。
client_id 必要 Azure 入口網站中指派給應用程式的應用程式識別碼。
client_secret 是,在 Web Apps 中 Azure 入口網站中產生的應用程式祕密。 用戶端密碼是用於 Web 應用程式情節的流程中,用戶端可以在其中安全地儲存用戶端密碼。 針對原生應用程式 (公用用戶端) 情節,無法安全地儲存用戶端密碼,因此不會在此呼叫上使用用戶端密碼。 如果您使用用戶端密碼,請定期變更。
grant_type 必要 授與類型。 在授權碼流程的這個階段中,授與類型必須是 refresh_token
scope 建議 以空格分隔的範圍清單。 單一範圍值表示Microsoft Entra要求的許可權兩者識別碼。 使用用戶端識別碼作為範圍時,表示您的應用程式需要可針對您自己的服務或 Web API 使用的存取權杖 (以相同的用戶端識別碼表示)。 offline_access 範圍表示您的應用程式需要重新整理權杖,才能長久存取資源。 您也可以使用 openid 範圍從 Azure AD B2C 要求識別碼權杖。
redirect_uri 選擇性 應用程式的重新導向 URI,您已在此處收到授權碼。
refresh_token 必要 您在流程的第二個階段中取得的原始重新整理權杖。

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

{
    "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...",
}
參數 Description
not_before 權杖生效的時間 (以新紀元 (Epoch) 時間表示)。
token_type 權杖類型值。 Microsoft Entra識別碼支援的唯一類型是 Bearer。
access_token 您所要求的已簽署 JWT。
scope 權杖有效的範圍。 您也可以使用範圍來快取權杖,以供稍後使用。
expires_in 權杖的有效時間長度 (以秒為單位)。
refresh_token OAuth 2.0 重新整理權杖。 應用程式在目前的權杖過期之後,可以使用這個權杖來取得其他權杖。 重新整理權杖的有效期很長,而且可以用來長期保留資源存取權。 如需詳細資訊,請參閱 Azure AD B2C 權杖參考

錯誤回應如下所示:

{
    "error": "access_denied",
    "error_description": "The user revoked access to the app.",
}
參數 描述
error 可用於將發生的錯誤類型分類的錯誤碼字串。 您也可以使用此字串對錯誤做出反應。
error_description 可協助您識別驗證錯誤根本原因的特定錯誤訊息。

使用您自己的 Azure AD B2C 目錄

若要自行嘗試這些要求,請完成下列步驟。 使用您自己的值取代我們在本文中使用的範例值。

  1. 建立 Azure AD B2C 目錄。 在要求中使用您的目錄名稱。
  2. 建立應用程式來取得應用程式識別碼和重新導向 URI。 在您的應用程式中包含原生用戶端。
  3. 建立您的使用者流程以取得您的使用者流程名稱。