Microsoft 身分識別平台上的 OpenID Connect

OpenID Connect (OIDC) 可擴充 OAuth 2.0 授權通訊協定,使其也能作為驗證通訊協定。 您可以使用 OIDC,透過稱為識別碼權杖的安全性權杖,在啟用 OAuth 的應用程式之間啟用單一登入 (SSO)。

如需 OIDC 的完整規格,請參閱 OpenID Foundation 網站上的 OpenID Connect Core 1.0 規格 (英文)。

通訊協定流程:登入

下圖顯示基本 OpenID Connect 登入流程。 流程中的步驟會在本文稍後的章節中更詳細說明。

顯示 OpenID Connect 通訊協定登入流程的泳道圖。

提示

嘗試在 Postman 中執行此要求
嘗試在 Postman 中執行此要求及其他操作 -- 別忘了取代權杖與識別碼!

啟用識別碼權杖

OpenID Connect 引進的「識別碼權杖」是在用戶端應用程式於使用者驗證期間要求時,由授權伺服器 (Microsoft 身分識別平台) 所發行。 識別碼權杖可讓用戶端應用程式驗證使用者的身分,並取得其他相關資訊 (宣告)。

預設不會對向 Microsoft 身分識別平台註冊的應用程式發行識別碼權杖。 請使用下列其中一種方法來啟用應用程式的識別碼權杖。

若要啟用應用程式的識別碼權杖,請瀏覽至 Azure 入口網站,然後:

  1. 選取 [Azure Active Directory]>[應用程式註冊]><您的應用程式>>[驗證]。
  2. 在 [Implicit grant and hybrid flows] \(隱含授與和混合式流程\) 下,選取 [ID tokens (used for implicit and hybrid flows)] \(識別碼權杖 (用於隱含和混合式流程)\) 核取方塊。

或:

  1. 選取 [Azure Active Directory]>[應用程式註冊]><您的應用程式>>[資訊清單]。
  2. 在應用程式註冊的應用程式資訊清單中將 oauth2AllowIdTokenImplicitFlow 設定為 true

如果您忘記啟用應用程式的識別碼權杖並要求識別碼權杖,Microsoft 身分識別平台會傳回類似如下的 unsupported_response 錯誤:

不允許此用戶端使用為輸入參數 'response_type' 提供的值。 預期的值為 'code'。

本文稍後的傳送登入要求將說明如何指定 id_tokenresponse_type 來要求識別碼權杖。

擷取 OpenID 設定文件

OpenID 提供者 (例如 Microsoft 身分識別平台) 會在可公開存取的端點提供 OpenID 提供者設定文件 (英文),其中包含提供者的 OIDC 端點、支援的宣告,以及其他中繼資料。 用戶端應用程式可以使用中繼資料來探索要用於驗證的 URL,以及驗證服務的公開簽署金鑰等。

驗證程式庫是 OpenID 設定文件的最常見取用者,用於探索驗證 URL、提供者的公開簽署金鑰,以及其他服務中繼資料。 如果您在應用程式中使用驗證程式庫 (建議使用),您可能不需要手動撰寫 OpenID 設定文件端點的要求和回應程式碼。

尋找應用程式的 OpenID 設定文件 URI

Azure AD 中的每個應用程式註冊都會有可公開存取的端點,以提供其 OpenID 設定文件。 若要判斷應用程式設定文件端點的 URI,請將「已知的 OpenID 設定」路徑附加至應用程式註冊的「授權單位 URL」。

  • 已知的設定文件路徑:/.well-known/openid-configuration
  • 授權單位 URL:https://login.microsoftonline.com/{tenant}/v2.0

{tenant} 的值會因應用程式的登入對象而異,如下表所示。 授權單位 URL 也會因雲端執行個體而異。

描述
common 使用者如果同時具有個人 Microsoft 帳戶和來自 Azure AD 的公司或學校帳戶,便可登入應用程式。
organizations 只有具有來自 Azure AD 之工作或學校帳戶的使用者可以登入應用程式。
consumers 只有具有個人 Microsoft 帳戶的使用者可以登入應用程式。
8eaef023-2b34-4da1-9baa-8bc8c9d6a490contoso.onmicrosoft.com 只有來自特定 Azure AD 租用戶的使用者 (具有公司或學校帳戶的目錄成員,或是具有個人 Microsoft 帳戶的目錄來賓) 才可以登入應用程式。

此值可以是 Azure AD 租用戶的網域名稱或 GUID 格式的租用戶識別碼。 您也可以使用取用者租用戶 GUID 9188040d-6c67-4c5b-b112-36a304b66dad 來取代 consumers

提示

請注意,針對個人 Microsoft 帳戶使用 commonconsumers 授權單位時,取用的資源應用程式必須根據 signInAudience 設定為支援這類帳戶類型。

您也可以在 Azure 入口網站的應用程式註冊中,找到應用程式的 OpenID 設定文件 URI。

若要尋找應用程式的 OIDC 設定文件,請瀏覽至 Azure 入口網站,然後:

  1. 選取 [Azure Active Directory]>[應用程式註冊]><您的應用程式>>[端點]。
  2. 在 [OpenID Connect 中繼資料文件] 下找到 URI。

範例要求

此要求會從 Azure 公用雲端上 common 授權單位的 OpenID 設定文件端點取得 OpenID 設定中繼資料:

GET /common/v2.0/.well-known/openid-configuration
Host: login.microsoftonline.com

提示

試試看! 若要查看應用程式 common 授權單位的 OpenID 設定文件,請瀏覽至 https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration

範例回應

設定中繼資料會以 JSON 格式傳回,如下列範例所示 (為了簡潔表示已刪減)。 JSON 回應中傳回的中繼資料會在 OpenID Connect 1.0 探索規格 (英文) 中詳細說明。

{
  "authorization_endpoint": "https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize",
  "token_endpoint": "https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token",
  "token_endpoint_auth_methods_supported": [
    "client_secret_post",
    "private_key_jwt"
  ],
  "jwks_uri": "https://login.microsoftonline.com/{tenant}/discovery/v2.0/keys",
  "userinfo_endpoint": "https://graph.microsoft.com/oidc/userinfo",
  "subject_types_supported": [
      "pairwise"
  ],
  ...
}

傳送登入要求

若要驗證使用者並要求識別碼權杖以用於您的應用程式,請將其使用者代理程式導向至 Microsoft 身分識別平台的 /authorize 端點。 這個要求類似於 OAuth 2.0 授權碼流程的第一個階段,但有下列區別:

  • scope 參數中包含 openid 範圍。
  • response_type 參數中指定 id_tokencode+id_token
  • 包含 nonce 參數。

範例登入要求 (包含分行符號僅為方便閱讀):

GET https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&response_type=id_token
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&response_mode=form_post
&scope=openid
&state=12345
&nonce=678910
參數 條件 描述
tenant 必要 您可以要求路徑中使用 {tenant} 值來控制可登入應用程式的人員。 允許的值為 commonorganizationsconsumers 及租用戶識別碼。 如需詳細資訊,請參閱通訊協定基本概念。 嚴格來說,針對您會將使用者從一個租用戶登入另一個租用戶的來賓案例,您必須提供租用戶識別碼,才能正確地將其登入資源租用戶。
client_id 必要 Azure 入口網站 - 應用程式註冊體驗指派給您應用程式的應用程式 (用戶端) 識別碼
response_type 必要 必須包含 OpenID Connect 登入的 id_token 。 它也可能包含其他 response_type 值,例如 code
redirect_uri 建議 應用程式的重新導向 URI,您的應用程式可在此傳送及接收驗證回應。 它必須與您在入口網站中註冊的其中一個重新導向 URI 完全相符,不過必須是 URL 編碼格式。 如果不存在,端點將會隨機挑選一個已註冊的 redirect_uri 來將使用者傳送回去。
scope 必要 範圍的空格分隔清單。 針對 OpenID Connect,即必須包含範圍 openid,其會在同意 UI 中轉譯成「讓您登入」權限。 您也可以在此要求中包含其他範圍來要求同意。
nonce 必要 應用程式在針對識別碼權杖的要求中產生並傳送的值。 Microsoft 身分識別平台傳回給應用程式的識別碼權杖中會包含相同的 nonce 值。 若要減輕權杖重新執行攻擊,您的應用程式應該驗證識別碼權杖中的 nonce 值與要求權杖時所傳送的值相同。 此值通常是唯一的隨機字串。
response_mode 建議 指定將產生的授權碼傳回到應用程式所應該使用的方法。 可以是 form_postfragment。 針對 Web 應用程式,建議使用 response_mode=form_post,以確保會以最安全的方式將權杖傳輸至您的應用程式。
state 建議 一個包含在要求中而將一併在權杖回應中傳回的值。 它可以是您想要的任何內容的字串。 通常會使用一個隨機產生的唯一值來防止跨站台偽造要求攻擊。 此狀態也用來在驗證要求出現之前,於應用程式中將使用者狀態的相關資訊 (例如使用者所在的網頁或檢視) 編碼。
prompt 選用 表示需要的使用者互動類型。 此時唯有 loginnoneconsentselect_account 是有效值。 prompt=login 宣告會強制使用者在該要求上輸入其認證,亦即取消單一登入。 prompt=none參數是相反的,且應與搭配使用 login_hint,以指出必須登入的使用者。 這些參數會確保無論如何都不會對使用者顯示任何互動式提示。 如果無法透過單一登入以無訊息方式完成要求,Microsoft 身分識別平台就會傳回錯誤。 原因包含沒有已登入的使用者、提示的使用者未登入,或已登入多個使用者但未提供提示。 prompt=consent 宣告會在使用者登入之後觸發 OAuth 同意對話方塊。 該對話方塊會請使用者將權限授與應用程式。 最後,select_account 會向使用者顯示帳戶選取器,否定無訊息 SSO,但允許使用者選擇他們想要登入的帳戶,而不需要認證輸入。 您無法同時使用 login_hintselect_account
login_hint 選用 如果您事先知道使用者名稱,便可使用此參數為使用者預先填入登入頁面的使用者名稱和電子郵件地址欄位。 通常應用程式會在重新驗證期間,在已從稍早的登入擷取login_hint選擇性宣告之後使用此參數。
domain_hint 選用 使用者於同盟目錄中的領域。 這會略過使用者在登入頁面上經歷的電子郵件型探索程序,以提供稍微更流暢的使用者體驗。 針對透過如 AD FS 的內部部署目錄進行同盟的租用戶,這通常會因現有的登入工作階段而導致流暢的登入。

此時,系統會要求使用者輸入其認證並完成驗證。 Microsoft 身分識別平台會驗證使用者已經同意 scope 查詢參數所指出的權限。 如果使用者尚未同意那些權限中的任何一項,Microsoft 身分識別平台就會提示使用者同意必要的權限。 您可以深入了解權限、同意及多租用戶應用程式

在使用者驗證並授與同意之後,Microsoft 身分識別平台會使用 response_mode 參數中指定的方法,於指定的重新導向 URI 將回應傳回給您的應用程式。

成功回應

使用 response_mode=form_post 時的成功回應類似如下:

POST /myapp/ HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded

id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNB...&state=12345
參數 描述
id_token 應用程式所要求的識別碼權杖。 您可以使用 id_token 參數來驗證使用者的身分識別,並開始與使用者的工作階段。 如需識別碼權杖及其內容的詳細資訊,請參閱識別碼權杖參考
state 如果要求中包含 state 參數,則回應中應該會出現相同的值。 應用程式應該確認要求和回應中的狀態值完全相同。

錯誤回應

錯誤回應也可能傳送到重新導向 URI,以便應用程式能夠進行處理,例如:

POST /myapp/ HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded

error=access_denied&error_description=the+user+canceled+the+authentication
參數 描述
error 您可用來分類發生的錯誤類型並對錯誤做出反應的錯誤碼字串。
error_description 可協助您識別驗證錯誤根本原因的特定錯誤訊息。

授權端點錯誤的錯誤碼

下表說明可能在錯誤回應的 error 參數中傳回的錯誤碼:

錯誤碼 描述 用戶端動作
invalid_request 通訊協定錯誤,例如遺漏必要的參數。 修正並重新提交要求。 在應用程式測試期間,應該會攔截到此開發錯誤。
unauthorized_client 用戶端應用程式無法要求授權碼。 當用戶端應用程式未在 Azure AD 中註冊,或未新增至使用者的 Azure AD 租用戶時,就可能會發生此錯誤。 應用程式可以對使用者提示一些指示,來安裝應用程式並將它新增到 Azure AD。
access_denied 資源擁有者拒絕同意。 用戶端應用程式可以通知使用者除非使用者同意,否則其無法繼續進行。
unsupported_response_type 授權伺服器不支援要求中的回應類型。 修正並重新提交要求。 在應用程式測試期間,應該會攔截到此開發錯誤。
server_error 伺服器發生非預期的錯誤。 重試要求。 這些錯誤可能是由暫時性狀況所引起。 用戶端應用程式可能會向使用者解釋其回應因暫時性錯誤而延遲。
temporarily_unavailable 伺服器暫時過於忙碌而無法處理要求。 重試要求。 用戶端應用程式可能會向使用者解釋其回應因暫時性狀況而延遲。
invalid_resource 目標資源無效,因為不存在、Azure AD 找不到,或是未正確設定。 此錯誤表示尚未在租用戶中設定資源 (如果存在)。 應用程式可以對使用者提示一些指示,來安裝應用程式並將它新增到 Azure AD。

驗證識別碼權杖

在您的應用程式中接收識別碼權杖可能不一定足以充分驗證使用者。 您可能需要一併驗證識別碼權杖的簽章,並依照您應用程式的需求確認其宣告。 類似所有 OIDC 提供者,Microsoft 身分識別平台的識別碼權杖是使用使用公開金鑰加密簽署的 JSON Web 權杖 (JWT)

使用識別碼權杖進行授權的 Web 應用程式和 Web API 必須加以驗證,因為這類應用程式可以存取資料。 不過,其他類型的應用程式可能無法受益於識別碼權杖驗證。 例如,原生和單頁應用程式 (SPA) 很少受益於識別碼權杖驗證,因為任何具有裝置或瀏覽器實體存取權的實體都可能會略過驗證。

權杖驗證略過的兩個範例包括:

  • 藉由修改裝置的網路流量來提供假權杖或金鑰
  • 在程式執行期間偵錯應用程式並略過驗證邏輯。

如果您在應用程式中驗證識別碼權杖,建議「不要」手動執行此動作。 請改用權杖驗證程式庫來剖析和驗證權杖。 權杖驗證程式庫適用於大部分的開發語言、架構和平台。

在識別碼權杖中驗證的內容

除了驗證識別碼權杖的簽章之外,您也應該驗證其中幾個宣告,如識別碼權杖參考驗證識別碼權杖中所述。 另請參閱簽署金鑰變換的相關重要資訊

還有其他幾個驗證很常見,並會因應用程式案例而異,包括:

  • 確保使用者/組織已註冊應用程式。
  • 確保使用者擁有正確的授權/權限
  • 確保所發生的驗證具有特定強度,例如多重要素驗證

驗證識別碼權杖之後,您就可以開始使用者工作階段,並使用權杖宣告中的資訊進行應用程式個人化、顯示或儲存其資料。

通訊協定圖表:存取權杖取得

許多 Web 應用程式不僅需要將使用者登入,也需要代表使用者存取受保護的資源 (例如 Web API)。 此案例結合了 OpenID Connect 與 OAuth 2.0,前者可取得識別碼權杖以驗證使用者,後者可取得受保護資源的存取權杖。

完整的 OpenID Connect 登入和權杖取得流程看起來類似下圖:

OpenID Connect 通訊協定:權杖取得

取得使用者資訊端點的存取權杖

除了識別碼權杖之外,OIDC 使用者資訊端點也會提供已驗證的使用者資訊。

若要取得 OIDC 使用者資訊端點的存取權杖,請修改登入要求,如下所述:

// Line breaks are for legibility only.

GET https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e        // Your app registration's Application (client) ID
&response_type=id_token%20token                       // Requests both an ID token and access token
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F       // Your application's redirect URI (URL-encoded)
&response_mode=form_post                              // 'form_post' or 'fragment'
&scope=openid+profile+email                           // 'openid' is required; 'profile' and 'email' provide information in the UserInfo endpoint as they do in an ID token. 
&state=12345                                          // Any value - provided by your app
&nonce=678910                                         // Any value - provided by your app

您可以使用 授權碼流程裝置程式碼流程重新整理權杖取代 response_type=token 來取得應用程式的存取權杖。

成功的權杖回應

使用 response_mode=form_post 的成功回應如下:

POST /myapp/ HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
 access_token=eyJ0eXAiOiJKV1QiLCJub25jZSI6I....
 &token_type=Bearer
 &expires_in=3598
 &scope=email+openid+profile
 &id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI....
 &state=12345

無論用來取得的流程為何,回應參數都代表相同的內容。

參數 Description
access_token 將用來呼叫使用者資訊端點的權杖。
token_type 一律是「持有人」
expires_in 存取權杖到期之前的時間長度 (以秒為單位)。
scope 授與存取權杖的權限。 由於使用者資訊端點裝載於 Microsoft Graph,scope 可能會包含先前授與應用程式的其他端點 (例如 User.Read)。
id_token 應用程式所要求的識別碼權杖。 您可以使用識別碼權杖來確認使用者的身分識別,然後開始與使用者的工作階段。 您將在識別碼權杖參考中找到有關識別碼權杖及其內容的更多詳細資料。
state 如果要求中包含 state 參數,則回應中應該會出現相同的值。 應用程式必須驗證要求與回應中的狀態值是否相同。

警告

請勿在程式碼中,嘗試驗證或讀取任何您未擁有的 API 的權杖 (包括此範例中的權杖)。 Microsoft 服務的權杖可以使用不會驗證為 JWT 的特殊格式,且可能為取用者 (Microsoft 帳戶) 使用者進行加密。 雖然讀取權杖是很實用的偵錯與學習工具,但請勿在程式碼中依賴此功能的相依性,或是假設並非用於您所控制 API 的權杖相關內容。

錯誤回應

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

POST /myapp/ HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded

error=access_denied&error_description=the+user+canceled+the+authentication
參數 描述
error 您可用來分類發生的錯誤類型並對錯誤做出反應的錯誤碼字串。
error_description 可協助您識別驗證錯誤根本原因的特定錯誤訊息。

如需可能的錯誤碼說明及建議的用戶端回應,請參閱授權端點錯誤的錯誤碼

在您取得授權碼和識別碼權杖之後,您可以將使用者登入並代表他們取得存取權杖。 若要將使用者登入,您必須完全依照所述的方式驗證識別碼權杖。 若要取得存取權杖,請依照 OAuth 程式碼流程文件中所述的步驟操作。

呼叫使用者資訊端點

請檢閱 UserInfo 文件,了解如何使用此權杖來呼叫使用者資訊端點。

傳送登出要求

若要將使用者登出,請執行下列兩項作業:

  • 將使用者的使用者代理程式重新導向至 Microsoft 身分識別平台的登出 URI
  • 清除您應用程式的 Cookie,或結束您應用程式中的使用者工作階段。

如果您無法執行上述任一作業,使用者可能會保持已驗證狀態,而且在下次使用應用程式時將不會收到登入提示。

將使用者代理程式重新導向至 end_session_endpoint,如 OpenID Connect 設定文件中所示。 end_session_endpoint 同時支援 HTTP GET 和 POST 要求。

GET https://login.microsoftonline.com/common/oauth2/v2.0/logout?
post_logout_redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
參數 條件 描述
post_logout_redirect_uri 建議 使用者在成功登出之後,重新導向的 URL。如果未包含此參數,則會顯示 Microsoft 身分識別平台所產生的一般訊息。 此 URL 必須與您在應用程式註冊入口網站中為應用程式註冊的其中一個重新導向 URI 相符。
logout_hint 選用 讓登出進行,而不提示使用者選取帳戶。 若要使用 logout_hint,請在用戶端應用程式中啟用login_hint選擇性宣告,並使用 login_hint 選擇性宣告的值做為 logout_hint 參數。 請勿使用 UPN 或電話號碼作為 logout_hint 參數的值。

注意

成功登出之後,作用中的會話將會設定為非使用中。 如果已登出的使用者有有效的主要重新整理權杖 (PRT) ,而且會執行新的登入,SSO 將會中斷,而且使用者會看到帳戶選擇器的提示。 如果選取的選項是參照 PRT 的已線上帳戶,登入將會自動繼續,而不需要插入全新的認證。

單一登出

當您將使用者重新導向至 end_session_endpoint 時,Microsoft 身分識別平台會從瀏覽器中清除使用者的工作階段。 不過,使用者可能仍然登入其他使用 Microsoft 帳戶進行驗證的應用程式。 為了讓那些應用程式能同時將使用者登出,Microsoft 身分識別平台會將 HTTP GET 要求傳送至使用者目前登入之所有應用程式的已註冊 LogoutUrl。 應用程式必須藉由清除任何可識別使用者的工作階段並傳回 200 回應,以回應此要求。 如果您想要在應用程式中支援單一登出,您必須在應用程式的程式碼中實作這類 LogoutUrl。 您可以從應用程式註冊入口網站設定 LogoutUrl

後續步驟