Microsoft 身分識別平台 和 OAuth 2.0 隱含授與流程

Microsoft 身分識別平台 支援 OAuth 2.0 隱含授與流程,如 OAuth 2.0 規格中所述。 隱含授與的定義特性是,令牌(標識符令牌或存取令牌)會直接從 /authorize 端點傳回,而不是 /token 端點。 這通常用於授權碼流程的 一部分,也就是所謂的「混合式流程」-擷取 /authorization 要求上的標識符令牌以及授權碼。

本文說明如何直接針對應用程式中的通訊協議進行程序設計,以向 Microsoft Entra ID 要求令牌。 建議您盡可能改為使用支援的 Microsoft 驗證程式庫 (MSAL),以取得權杖並呼叫受保護的 Web API。 另請參閱使用 MSAL範例應用程式。

偏好驗證碼流程

透過從 瀏覽器移除第三方 Cookie 的計畫, 隱含授與流程不再是適當的驗證方法隱含流程的無訊息單一登錄 (SSO) 功能無法在沒有第三方 Cookie 的情況下運作,導致應用程式嘗試取得新的令牌時中斷。 強烈建議所有新的應用程式都使用 授權碼流程 ,現在支援單頁應用程式取代隱含流程。 現有的單頁應用程式也應該 移轉至授權碼流程

適用於 OAuth2 隱含授與的適用案例

隱含授與僅適用於登入流程的初始互動式部分,其中缺少 第三方 Cookie 不會影響您的應用程式。 此限制表示您應該在混合式流程中獨佔使用,其中您的應用程式會要求程序代碼,以及授權端點的令牌。 在混合式流程中,您的應用程式會收到可兌換重新整理令牌的程序代碼,因此可確保應用程式登入會話在一段時間內保持有效。

通訊協定圖表

下圖顯示整個隱含登入流程的外觀,以及後續各節會詳細說明每個步驟。

Diagram showing the implicit sign-in flow

傳送登入要求

若要一開始將使用者登入您的應用程式,您可以傳送 OpenID 連線 驗證要求,並從 Microsoft 身分識別平台 取得 id_token

重要

若要成功要求標識碼令牌和/或存取令牌,Microsoft Entra 系統管理中心 - 應用程式註冊 頁面中的應用程式註冊必須啟用對應的隱含授與流程,方法是在 [隱含授與和混合式流程] 區段中選取 [標識符令牌和存取令牌]。 如果未啟用, unsupported_response 則會傳回錯誤:

The provided value for the input parameter 'response_type' is not allowed for this client. Expected value is 'code'

// Line breaks for legibility only

https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id=00001111-aaaa-2222-bbbb-3333cccc4444
&response_type=id_token
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&scope=openid
&response_mode=fragment
&state=12345
&nonce=678910
參數 類型 描述
tenant 必要 {tenant}要求路徑中的值可用來控制誰可以登入應用程式。 允許的值為 commonorganizationsconsumers和租用戶標識碼。 如需詳細資訊,請參閱通訊協定基本概念。關鍵是,對於將使用者從某個租使用者登入另一個租使用者的來賓案例,您必須提供租使用者標識碼,才能正確地將使用者登入資源租使用者。
client_id 必要 Microsoft Entra 系統管理中心 - 應用程式註冊 指派給應用程式的應用程式 (用戶端) 識別碼
response_type 必要 必須包含用於 OpenID Connect 登入的 id_token。 它也 response_type可能包含、 token。 在這裡使用 token 可讓您的應用程式立即從授權端點接收存取令牌,而不需要對授權端點提出第二個要求。 如果您使用 token response_type,參數必須包含一個範圍, scope 指出要發行令牌的資源(例如, user.read 在 Microsoft Graph 上)。 它也可以包含 code 來取代 token 來提供授權碼,以在授權碼流程中使用。 此 id_token+code 回應有時稱為混合式流程。
redirect_uri 建議使用 應用程式的重新導向 URI,應用程式可以傳送和接收驗證回應。 它必須完全符合您在入口網站中註冊的其中一個重新導向 URI,但必須經過 URL 編碼。
scope 必要 以空格分隔的範圍清單。 若為 OpenID 連線 (id_tokens),它必須包含範圍openid,這會轉譯為同意 UI 中的「登入」許可權。 您也可以選擇性地包含 emailprofile 範圍,以取得其他用戶數據的存取權。 如果要求存取令牌,您也可以在此要求中包含其他範圍,以要求同意各種資源。
response_mode 選用 指定應該用來將所產生權杖傳回給應用程式的方法。 默認只會查詢存取令牌,但如果要求包含id_token,則為片段。
state 建議使用 要求中包含,也會在權杖回應中傳回的值。 其可以是任何內容的字串。 隨機產生的唯一值通常用於 防止跨網站要求偽造攻擊。 此狀態也可用來在驗證要求發生之前,將使用者狀態的相關資訊編碼,例如他們所在的頁面或檢視。
nonce 必要 應用程式所產生的要求中包含的值,將包含在產生的標識元令牌中做為宣告。 然後,應用程式可以驗證此值,以減輕權杖重新執行所造成的攻擊。 此值通常是隨機的唯一字串,可以用來識別要求的來源。 只有在要求 id_token 時才需要。
prompt 選用 表示必要的使用者互動類型。 目前login唯一有效的值為、 noneselect_account、 和 consentprompt=login 會強制使用者在該要求上輸入其認證,並否定單一登錄。 prompt=none 相反 ─ 它會確保使用者不會顯示任何互動式提示。 如果無法透過 SSO 以無訊息方式完成要求,則 Microsoft 身分識別平台 會傳回錯誤。 prompt=select_account 會將使用者傳送至帳戶選擇器,其中所有帳戶都會出現在會話中。 prompt=consent 會在使用者登入之後觸發 OAuth 同意對話方塊,要求使用者將許可權授與應用程式。
login_hint 選用 如果您事先知道使用者名稱,您可以使用此參數預先填入使用者登入頁面的使用者名稱和電子郵件位址字段。 應用程式通常會在重新驗證期間使用此參數,在已從先前的登入擷取 login_hint選擇性宣告 之後。
domain_hint 選用 如果包含,則會略過使用者在登入頁面上經歷的電子郵件式探索程式,進而獲得稍微簡化的用戶體驗。 此參數通常用於在單一租用戶中運作的企業營運應用程式,其中他們會提供指定租使用者內的域名,將使用者轉送給該租使用者的同盟提供者。 此提示可防止來賓登入此應用程式,並限制使用 FIDO 之類的雲端認證。

此時,系統會要求使用者輸入其認證並完成驗證。 Microsoft 身分識別平台 也會確保使用者已同意查詢參數中所scope指出的許可權。 如果使用者已同意 這些許可權, 則會要求使用者同意所需的許可權。 如需詳細資訊,請參閱 許可權、同意和多租用戶應用程式

一旦使用者驗證並授與同意之後,Microsoft 身分識別平台 會使用 參數中指定的response_mode方法,將回應傳回至您的應用程式redirect_uri

成功的回覆

使用 response_mode=fragment 的成功回應,如下所示 response_type=id_token+code (具有可讀性的換行符):

GET https://localhost/myapp/#
code=0.AgAAktYV-sfpYESnQynylW_UKZmH-C9y_G1A
&id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...
&state=12345
參數 描述
code 如果 response_type 包含 ,則包含 code。 這是適合用於授權碼流程授權碼。
access_token 如果 response_type 包含 ,則包含 token。 應用程式所要求的存取令牌。 存取令牌不應譯碼或檢查,應該視為不透明的字串。
token_type 如果 response_type 包含 ,則包含 token。 這一律為 Bearer
expires_in 如果 response_type 包含 ,則包含 token。 指出權杖有效的秒數,以供快取之用。
scope 如果 response_type 包含 ,則包含 token。 表示 access_token 適用的範圍。 如果所有要求的範圍不適用於使用者,則可能不會包含這些範圍。 例如,使用個人帳戶登入時所要求的僅限 Microsoft Entra 範圍。
id_token 已簽署的 JSON Web 權杖 (JWT)。 應用程式可以將此權杖的區段解碼,以索取已登入使用者的相關資訊。 應用程式可以快取並顯示值,但不應依賴這些值來取得任何授權或安全性界限。 如需識別元令牌的詳細資訊,請參閱 id_token reference
注意:只有在要求範圍並response_type包含 id_tokens時才openid提供。
state 如果要求中包含 state 參數,則回應中應該會出現相同的值。 應用程式必須確認要求與回覆中的狀態值完全相同。

警告

請勿在程式代碼中嘗試驗證或讀取您未擁有之任何 API 的令牌,包括此範例中的令牌。 Microsoft 服務 的令牌可以使用不會驗證為 JWT 的特殊格式,也可以為取用者 (Microsoft 帳戶) 使用者加密。 雖然讀取令牌是實用的偵錯和學習工具,但請勿在程式代碼中對此採取相依性,或假設您控制之 API 的令牌相關細節。

回覆錯誤

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

GET https://localhost/myapp/#
error=access_denied
&error_description=the+user+canceled+the+authentication
參數 描述
error 錯誤碼字串,可用來分類發生的錯誤類型,並可用來回應錯誤。
error_description 特定錯誤訊息,可協助開發人員識別驗證錯誤的根本原因。

以無訊息方式取得存取令牌

重要

隱含流程的這個部分不太可能適用於您的應用程式,因為預設會移除第三方 Cookie,因此會跨不同的瀏覽器使用。 雖然這目前仍在以 Chromium 為基礎的瀏覽器中運作,但不在 Incognito 中,但開發人員應該重新考慮使用流程的這個部分。 在不支援第三方 Cookie 的瀏覽器中,您會收到錯誤,指出沒有使用者登入,因為瀏覽器已移除登入頁面的會話 Cookie。

既然您已將使用者登入單頁應用程式,您可以以無訊息方式取得存取令牌,以呼叫受 Microsoft 身分識別平台 保護的Web API,例如 Microsoft Graph。 即使您已經使用 token response_type 收到令牌,您也可以使用此方法取得令牌給其他資源,而不重新導向使用者再次登入。

在一般的 OpenID 連線/OAuth 流程中,您會對 Microsoft 身分識別平台 /token 端點提出要求來執行此動作。 您可以在隱藏的 iframe 中提出要求,以取得其他 Web API 的新權杖:

// Line breaks for legibility only

https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id=00001111-aaaa-2222-bbbb-3333cccc4444&response_type=token
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&scope=https%3A%2F%2Fgraph.microsoft.com%2Fuser.read
&response_mode=fragment
&state=12345
&nonce=678910
&prompt=none
&login_hint=myuser@mycompany.com

如需 URL 中查詢參數的詳細資訊,請參閱 傳送登入要求

提示

請嘗試將下列要求複製並貼到瀏覽器索引標籤中! (別忘了以使用者的正確值取代 login_hint 值)

https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=535fb089-9ff3-47b6-9bfb-4f1264799865&response_type=token&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F&scope=https%3A%2F%2Fgraph.microsoft.com%2Fuser.read&response_mode=fragment&state=12345&nonce=678910&prompt=none&login_hint={your-username}

請注意,即使在沒有第三方 Cookie 支援的瀏覽器中也是如此,因為您直接將它輸入瀏覽器列,而不是在 iframe 中開啟它。

prompt=none由於 參數,此要求會立即成功或失敗,並返回您的應用程式。 回應會使用 參數中指定的 response_mode 方法,在指定的 redirect_uri處傳送至您的應用程式。

成功的回覆

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

GET https://localhost/myapp/#
access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...
&state=12345
&token_type=Bearer
&expires_in=3599
&scope=https%3A%2F%2Fgraph.microsoft.com%2Fdirectory.read
參數 描述
access_token 如果 response_type 包含 ,則包含 token。 應用程式要求的存取令牌,在此案例中為 Microsoft Graph。 存取令牌不應譯碼或檢查,應該視為不透明的字串。
token_type 這一律為 Bearer
expires_in 指出權杖有效的秒數,以供快取之用。
scope 指出存取令牌的有效範圍。 如果這些範圍不適用於使用者,則不一定包含所要求的所有範圍(在個人帳戶用來登入時所要求的僅限 Microsoft Entra 範圍中)。
id_token 已簽署的 JSON Web 權杖 (JWT)。 如果 response_type 包含 ,則包含 id_token。 應用程式可以將此權杖的區段解碼,以索取已登入使用者的相關資訊。 應用程式可以快取並顯示值,但不應依賴這些值來取得任何授權或安全性界限。 如需id_tokens的詳細資訊,請參閱 id_token 參考
注意: 只有在要求範圍時才 openid 提供。
state 如果要求中包含 state 參數,則回應中應該會出現相同的值。 應用程式必須確認要求與回覆中的狀態值完全相同。

回覆錯誤

錯誤回應也可能傳送至 , redirect_uri 讓應用程式可以適當地處理它們。 在 的案例中 prompt=none,預期的錯誤會是:

GET https://localhost/myapp/#
error=user_authentication_required
&error_description=the+request+could+not+be+completed+silently
參數 描述
error 錯誤碼字串,可用來分類發生的錯誤類型,並可用來回應錯誤。
error_description 特定錯誤訊息,可協助開發人員識別驗證錯誤的根本原因。

如果您在 iframe 要求中收到此錯誤,用戶必須再次以互動方式登入,才能擷取新的令牌。 您可以選擇以任何對應用程式有意義的方式來處理此案例。

重新整理令牌

隱含授與不提供重新整理權杖。 標識元令牌和存取令牌都會在短時間內到期,因此您的應用程式必須準備好定期重新整理這些令牌。 若要重新整理任一類型的令牌,您可以使用 參數來執行上述相同的隱藏 iframe 要求 prompt=none ,以控制身分識別平台的行為。 如果您想要接收新的識別碼令牌,請務必在 id_tokenscope=openid中使用 response_type ,以及 nonce 參數。

在不支援第三方 Cookie 的瀏覽器中,這會導致錯誤,指出沒有使用者登入。

傳送註銷要求

OpenID 連線 end_session_endpoint 可讓您的應用程式將要求傳送至 Microsoft 身分識別平台,以結束使用者的會話,並清除 Microsoft 身分識別平台 所設定的 Cookie。 若要將使用者完全註銷 Web 應用程式,您的應用程式應該結束與使用者本身的會話(通常是清除令牌快取或卸除 Cookie),然後將瀏覽器重新導向至:

https://login.microsoftonline.com/{tenant}/oauth2/v2.0/logout?post_logout_redirect_uri=https://localhost/myapp/
參數 類型 描述
tenant 必要 {tenant}要求路徑中的值可用來控制誰可以登入應用程式。 允許的值為 commonorganizationsconsumers和租用戶標識碼。 如需詳細資訊,請參閱 通訊協定基本概念
post_logout_redirect_uri 建議使用 註銷完成後,用戶應該傳回的URL。 此值必須符合為應用程式註冊的其中一個重新導向 URI。 如果未包含,使用者將會由 Microsoft 身分識別平台 顯示一般訊息。

下一步