共用方式為


AD FS OpenID Connect/OAuth 流程和應用程式案例

適用於 Active Directory 同盟服務 (AD FS) 2019 和更新版本

Scenario 包含範例的案例逐步解說 OAuth 2.0 流程/授權 用戶端類型
單頁應用程式 使用 MSAL 的範例 Implicit Public
登入使用者的 Web 應用程式 授權碼 公用、機密
原生應用程式呼叫 Web API 使用 MSAL 的範例 授權碼 Public
Web 應用程式呼叫 Web API 使用 MSAL 的範例 授權碼 Confidential
PKCE實施 授權碼 Public
Web API 代表 (OBO) 使用者呼叫另一個 Web API 使用 MSAL 的範例 On-behalf-of Web 應用程式充當機密角色
常駐程式呼叫 Web API 用戶端認證 Confidential
Web 應用程式使用使用者認證呼叫 Web API 資源擁有者密碼認證 公用、機密
無瀏覽器應用程式呼叫 Web API 裝置代碼 公用、機密

隱含授與流程

Note

Microsoft 強烈建議遷移到 Microsoft Entra ID,而不是升級為較新版本的 AD FS。 更多關於 Microsoft Entra ID 的隱式授權流資訊,請參閱 Microsoft 身份平台裡的隱式授權流。

針對單頁應用程式 (AngularJS、Ember.js、React.js等),AD FS 支援 OAuth 2.0 隱含授與流程。 隱含流程在 OAuth 2.0 規格中說明。 其主要優點是可讓應用程式從 AD FS 取得權杖,而不需要執行後端伺服器認證交換。 此流程可讓應用程式在用戶端 JavaScript 程式碼中登入使用者、維持工作階段,並獲得其他 Web API 的權杖。 使用隱含流程時,需要考慮幾項重要的安全性問題,尤其是針對客戶端。

如果您想要使用隱含流程和 AD FS 將驗證新增至 JavaScript 應用程式,請遵循下列區段中的一般步驟。

通訊協議圖表

下圖顯示整個隱含登入流程的外觀。 下列各節會更詳細地說明每個步驟。

顯示隱含登入流程的圖表。

要求 ID 令牌和存取令牌

若要一開始將使用者登入您的應用程式,您可以傳送 OpenID Connect 驗證要求,並從 AD FS 端點取得id_token和存取權杖。

// Line breaks for legibility only

https://adfs.contoso.com/adfs/oauth2/authorize?
client_id=00001111-aaaa-2222-bbbb-3333cccc4444
&response_type=id_token+token
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&scope=openid
&response_mode=fragment
&state=12345
Parameter Required/optional Description
client_id required AD FS 指派給應用程式的應用程式 (用戶端) 識別碼。
response_type required 必須包含 id_token 來進行 OpenID Connect 登入。 它也可以包括response_type token。 使用 token 此功能可讓您的應用程式立即從授權端點接收存取權杖,而無需再向權杖端點發出第二個請求。
redirect_uri required 您的應用程式的 redirect_uri,是用來發送和接收驗證回應的地址。 該 URL 必須完全符合您在 AD FS 中設定的其中一個 redirect_uris。
nonce required 包含在要求中的值 (由應用程式產生),該值將會以宣告的形式包含在產生的 id_token 中。 然後,應用程式可以驗證此值,以減輕令牌重播攻擊。 值通常是隨機化的唯一字串,可用來識別要求的來源。 只有在要求 id_token 時才需要。
範圍 optional 以空格分隔的範圍清單。 若為 OpenID Connect,則必須包含範圍openid
資源 optional Web API 的 URL。
附註 – 如果使用 MSAL 用戶端程式庫,則不會傳送資源參數。 相反地,資源 URL 會作為範圍參數的一部分傳送: scope = [resource url]//[scope values, for example, openid]
如果資源未傳遞到此處或範圍內,AD FS 會使用預設資源 urn:microsoft:userinfo。 userinfo 資源原則 (例如 MFA、發行或授權原則) 無法自訂。
response_mode optional 指定應該用來將所產生權杖傳回給應用程式的方法。 預設為 fragment
狀態 optional 包含在要求中的值將在權杖回應中傳回。 它可以是您想要之任何內容的字串。 隨機產生的唯一值通常用於 防止跨站台要求偽造攻擊。 此狀態也可用來在驗證要求發生之前,將使用者狀態的相關資訊編碼,例如他們所在的頁面或檢視。
提示 optional 指出所需的使用者互動類型。 目前唯一有效的值是 sign-in 和 none。
- prompt=login 強制使用者在該請求上輸入其認證,從而否定單一登入。
-  prompt=none 恰恰相反 - 它確保使用者不會看到任何互動式提示。 如果無法透過單一登入以靜默方式完成要求,AD FS 會傳回「interaction_required」錯誤。
login_hint optional 如果您事先知道使用者的使用者名稱,可以用此項目來預先填入使用者登入頁面上的使用者名稱/電子郵件地址欄位。 應用程式通常會在重新驗證期間使用此參數,因為已在先前的登入中使用 upn 宣告從 id_token 擷取了使用者名稱。
domain_hint optional 如果包含此值,則會略過使用者在登入頁面上所經歷的網域型探索程式,從而帶來稍微簡化的使用者體驗。

此時,系統會要求使用者輸入其認證並完成驗證。 使用者驗證之後,AD FS 授權端點會使用 response_mode 參數中指定的方法,將回應傳送至指定的 redirect_uri 給應用程式。

成功回應

當使用 response_mode=fragment and response_type=id_token+token 時,成功的回應如下所示:

// Line breaks for legibility only

GET https://localhost/myapp/#
access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZEstZnl0aEV...
&token_type=Bearer
&expires_in=3599
&scope=openid
&id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZstZnl0aEV1Q...
&state=12345
Parameter Description
access_token 如果 response_type 包含 token ,則該參數也會包含在內。
token_type 如果 response_type 包含 token ,則該參數也會包含在內。 一律 Bearer為 。
expires_in 如果 response_type 包含 token ,則該參數也會包含在內。 指出令牌有效的秒數,以供快取之用。
範圍 表示 access_token 有效的範圍。
id_token 如果 response_type 包含 id_token ,則該參數也會包含在內。 已簽署的 JSON Web 令牌 (JWT)。 應用程式可以將此權杖的區段解碼,以索取已登入使用者的相關資訊。 應用程式可以快取並顯示值,但不應依賴這些值來取得任何授權或安全性界限。
狀態 如果要求中包含 state 參數,則回應中應該會出現相同的值。 應用程式必須確認要求與回覆中的狀態值完全相同。

重新整理令牌

隱式授權不提供重新整理令牌。 id_tokens和access_tokens都會在短時間內過期,因此您的應用程式必須準備好定期刷新這些代幣。 若要刷新任一型別的權杖,您可以執行與上一節相同的隱藏iframe請求,使用 prompt=none 引數來控制身分平台的行為。 如果您想收到新的 id_token,請務必使用 response_type=id_token

授權碼授與流程

Note

Microsoft 強烈建議遷移到 Microsoft Entra ID,而不是升級為較新版本的 AD FS。 更多關於 Microsoft Entra ID 裡的授權代碼授予流資訊,請參閱 Microsoft 身份平台的授權代碼授予流

您可以在 Web 應用程式中使用 OAuth 2.0 授權碼授與,以取得受保護資源 (例如 Web API) 的存取權。 如需 OAuthh 2.0 授權碼流程的說明,請參閱 OAuth 2.0 規格的第 4.1 節。 其用來在大部分的應用程式類型 (包括 Web 應用程式和原生安裝的應用程式) 中執行驗證和授權。 此流程可讓應用程式安全地取得 access_tokens,以用來存取信任 AD FS 的資源。

通訊協議圖表

概略地說,原生應用程式的驗證流程看起來像這樣:

授權碼授與流程的圖表。

要求授權碼

授權碼流程的開頭是用戶端將使用者導向至 /authorize 端點。 在此要求中,用戶端會指出其需要向使用者取得的權限:

// Line breaks for legibility only

https://adfs.contoso.com/adfs/oauth2/authorize?
client_id=00001111-aaaa-2222-bbbb-3333cccc4444
&response_type=code
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&response_mode=query
&resource=https://webapi.com/
&scope=openid
&state=12345
Parameter Required/optional Description
client_id required AD FS 指派給應用程式的應用程式 (用戶端) 識別碼。
response_type required 必須包含用於授權碼流程的程式碼。
redirect_uri required 您的應用程式的 redirect_uri,是您的應用程式可以接收和發送驗證回應的地方。 它必須完全符合您在 AD FS 中為用戶端註冊的其中一個 redirect_uris。
資源 optional Web API 的 URL。
附註 – 如果使用 MSAL 用戶端程式庫,則不會傳送資源參數。 相反地,資源 URL 會作為範圍參數的一部分傳送: scope = [resource url]//[scope values, for example, openid]
如果資源未傳遞到此處或範圍內,AD FS 會使用預設資源 urn:microsoft:userinfo。 userinfo 資源原則 (例如 MFA、發行或授權原則) 無法自訂。
範圍 optional 以空格分隔的範圍清單。
response_mode optional 指定應該用來將所產生權杖傳回給應用程式的方法。 可以是下列其中一種方法:
- query
- fragment
- form_post
query 將程式碼作為查詢字串參數提供給重新導向 URI。 如果您要要求程式碼,則您可以使用查詢、片段或 form_post。  form_post 會執行包含程式碼的 POST,並將其發送到您的重新導向 URI。
狀態 optional 包含在要求中的值將在權杖回應中傳回。 它可以是您想要之任何內容的字串。 隨機產生的唯一值通常用於 防止跨站台要求偽造攻擊。 此值也可以在驗證請求發生之前編碼使用者在應用程式中的狀態資訊,例如他們所在的頁面或檢視。
提示 optional 指出所需的使用者互動類型。 目前唯一有效的值是 sign-in 和 none。
- prompt=login 強制使用者在該請求上輸入其認證,從而否定單一登入。
-  prompt=none 恰恰相反 - 它確保使用者不會看到任何互動式提示。 如果無法透過單一登入以靜默方式完成要求,AD FS 會傳回「interaction_required」錯誤。
login_hint optional 如果您事先知道使用者的使用者名稱,可以用此項目來預先填入使用者登入頁面上的使用者名稱/電子郵件地址欄位。 應用程式通常會在重新驗證期間使用此參數,並在先前的登入過程中已透過upn宣告從id_token擷取使用者名稱。
domain_hint optional 如果包含此值,則會略過使用者在登入頁面上所經歷的網域型探索程式,從而帶來稍微簡化的使用者體驗。
code_challenge_method optional 使用的方法是用來為 code_challenge 參數編碼 code_verifier。 可以是下列值之一:
- 純文本
- S256
如果排除此值,而 code_challenge 包含在內,則假設 code_challenge 為純文本。 AD FS 同時支援純文本和 S256。 如需詳細資訊,請參閱 PKCE RFC
code_challenge optional 用於透過原生用戶端中的 Proof Key for Code Exchange (PKCE) 確保授權碼授與安全性。 如果包含 code_challenge_method,則此為必要參數。 如需詳細資訊,請參閱 PKCE RFC

此時,系統會要求使用者輸入其認證並完成驗證。 使用者驗證之後,AD FS 會使用參數中redirect_uri指定的方法,在指定的 response_mode處傳回應用程式的回應。

成功回應

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

GET https://adfs.contoso.com/common/oauth2/nativeclient?
code=AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrq...
&state=12345
Parameter Description
字碼 應用程式要求的 authorization_code。 應用程式可以使用授權碼來要求目標資源的存取權杖。 authorization_code 壽命短暫。 它們通常會在大約 10 分鐘後過期。
狀態 如果要求中包含 state 參數,則回應中應該會出現相同的值。 應用程式必須確認要求與回覆中的狀態值完全相同。

要求存取權杖

現在您已取得 authorization_code,並已獲得使用者權限,您可以將 access_token 的程式碼兌換為所需資源。 將 POST 要求傳送至 /token 端點以兌換碼:

// Line breaks for legibility only

POST /adfs/oauth2/token HTTP/1.1
Host: https://adfs.contoso.com/
Content-Type: application/x-www-form-urlencoded

client_id=00001111-aaaa-2222-bbbb-3333cccc4444
&code=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq3n8b2JRLk4OxVXr...
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&grant_type=authorization_code
&client_secret=JqQX2PNo9bpM0uEihUPzyrh    // NOTE: Only required for confidential clients (web apps)
Parameter Required/optional Description
client_id required AD FS 指派給應用程式的應用程式 (用戶端) 識別碼。
grant_type required 授權碼流程必須使用 authorization_code
字碼 required 您在流程中第一個階段取得的 authorization_code
redirect_uri required 用來取得 redirect_uri 的相同 authorization_code 值。
client_secret Web 應用程式的必要參數 您在 AD FS 中進行應用程式註冊時所建立的應用程式密碼。 您不應該在原生應用程式中使用應用程式密碼,因為 client_secrets 無法可靠地儲存在裝置上。 Web 應用程式和 Web API 需要此參數,它們能夠將client_secret安全地儲存在伺服器端。 用戶端密碼必須在傳送之前先進行 URL 編碼。 這些應用程式也可以透過簽署 JWT 並將其新增為client_assertion參數來使用金鑰型驗證。
code_verifier optional 用來取得 authorization_code 的相同的 code_verifier。 如果在授權碼授與要求中使用 PKCE,則此為必要參數。 如需詳細資訊,請參閱 PKCE RFC。 此選項適用於 AD FS 2019 和更新版本。

成功回應

成功的令牌回應如下所示:

{
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...",
    "token_type": "Bearer",
    "expires_in": 3599,
    "refresh_token": "AwABAAAAvPM1KaPlrEqdFSBzjqfTGAMxZGUTdM0t4B4...",
    "refresh_token_expires_in": 28800,
    "id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJhdWQiOiIyZDRkMTFhMi1mODE0LTQ2YTctOD...",
}
Parameter Description
access_token 要求的存取憑證。 應用程式可以使用此權杖向受保護的資源 (Web API) 進行驗證。
token_type 表示權杖類型的值。 AD FS 唯一支援的類型是承載者 (Bearer)。
expires_in 存取權杖的有效時間 (以秒為單位)。
refresh_token OAuth 2.0 刷新權杖。 應用程式可以在目前的存取權杖到期後,使用此權杖來取得其他存取權杖。 Refresh_tokens存留時間長,可用來長時間保留對資源的存取權。
refresh_token_expires_in 刷新權杖的有效時間有多久(以秒為單位)。
id_token 一個 JWT。 應用程式可以將此權杖的區段解碼,以索取已登入使用者的相關資訊。 應用程式可以快取並顯示值,但不應依賴這些值來取得任何授權或安全性界限。

使用存取令牌

GET /v1.0/me/messages
Host: https://webapi.com
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...

重新整理權杖授與流程

Access_tokens 的存留期較短,您必須在過期後重新整理,才能繼續存取資源。 若要這麼做,您可以向 /token 端點提交另一個 POST 要求,但這次提供 refresh_token,而不是程式碼。 刷新權杖適用於客戶端已獲取存取權杖的所有許可權。

刷新權杖沒有確定的存留時間。 一般而言,刷新權杖的存留期相對較長。 不過,在某些情況下,刷新權杖可能會過期、被撤銷,或者沒有執行所需動作的足夠的權限。 您的應用程式必須預期並正確處理權杖發行端點所傳回的錯誤。

雖然刷新權杖在用來獲取新的存取權杖時不會被撤銷,但您仍應丟棄舊的刷新權杖。 OAuth 2.0 規範說:“授權服務器可以發出新的刷新令牌,在這種情況下,客戶端必須丟棄舊的刷新令牌並將其替換為新的刷新令牌。 授權伺服器在向用戶端發出新的重新整理權杖之後,可以撤銷舊的重新整理權杖。」當新的重新整理權杖存留期長於先前的重新整理權杖存留期時,AD FS 會發出重新整理權杖。 若要檢視 AD FS 重新整理權杖存留期的其他資訊,請參閱 AD FS 單一登入設定

// Line breaks for legibility only

POST /adfs/oauth2/token HTTP/1.1
Host: https://adfs.contoso.com
Content-Type: application/x-www-form-urlencoded

client_id=00001111-aaaa-2222-bbbb-3333cccc4444
&refresh_token=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq...
&grant_type=refresh_token
&client_secret=JqQX2PNo9bpM0uEihUPzyrh      // NOTE: Only required for confidential clients (web apps)
Parameter Required/optional Description
client_id required AD FS 指派給應用程式的應用程式 (用戶端) 識別碼。
grant_type required 必須是 refresh_token 用於授權碼流程的此階段。
資源 optional Web API 的 URL。
附註 – 如果使用 MSAL 用戶端程式庫,則不會傳送資源參數。 相反地,資源 URL 會作為範圍參數的一部分傳送: scope = [resource url]//[scope values, for example, openid]
如果資源未傳遞到此處或範圍內,AD FS 會使用預設資源 urn:microsoft:userinfo。 userinfo 資源原則 (例如 MFA、發行或授權原則) 無法自訂。
範圍 optional 以空格分隔的範圍清單。
refresh_token required 您在流程第二個階段中取得的 refresh_token。
client_secret Web 應用程式的必要參數 您在您應用程式的應用程式註冊入口網站中建立的應用程式密碼。 此參數不應用於原生應用程式中,因為 client_secrets 無法可靠地儲存在裝置上。 Web 應用程式和 Web API 需要此參數,它們能夠將client_secret安全地儲存在伺服器端。 這些應用程式也可以透過簽署 JWT 並將其新增為client_assertion參數來使用金鑰型驗證。

成功回應

成功的令牌回應如下所示:

{
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...",
    "token_type": "Bearer",
    "expires_in": 3599,
    "refresh_token": "AwABAAAAvPM1KaPlrEqdFSBzjqfTGAMxZGUTdM0t4B4...",
    "refresh_token_expires_in": 28800,
    "id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJhdWQiOiIyZDRkMTFhMi1mODE0LTQ2YTctOD...",
}
Parameter Description
access_token 要求的存取憑證。 應用程式可以使用此權杖來對受保護的資源 (例如 Web API) 進行驗證。
token_type 表示權杖類型的值。 AD FS 唯一支援的類型是承載者 (Bearer)。
expires_in 存取權杖的有效時間 (以秒為單位)。
範圍 access_token 所適用的範圍。
refresh_token OAuth 2.0 刷新權杖。 應用程式可以在目前的存取權杖到期後,使用此權杖來取得其他存取權杖。 Refresh_tokens存留時間長,可用來長時間保留對資源的存取權。
refresh_token_expires_in 刷新權杖的有效時間有多久(以秒為單位)。
id_token 一個 JWT。 應用程式可以將此權杖的區段解碼,以索取已登入使用者的相關資訊。 應用程式可以快取並顯示值,但不應依賴這些值來取得任何授權或安全性界限。

OAuth 的 PKCE(授權碼交換驗證金鑰)支援

使用授權碼授與的 OAuth 公用用戶端容易受到授權碼攔截攻擊,如 RFC 7636 中所述。 為了減輕這些攻擊,從 Windows Server 2019 開始,AD FS 支援 OAuth 授權碼授與流程的程式代碼交換證明金鑰 (PKCE)。

PKCE 支援規格會將更多參數新增至 OAuth 2.0 授權和存取權杖要求。 下圖顯示用戶端在 Windows Server 2019 中連絡 AD FS 時的 PKCE 程式大綱。

用戶端與 AD FS 2019 之間的 PKCE 關聯圖表。

在標示為 A 的區段中,用戶端會建立並記錄名為 code_verifier 的秘密,並衍生名為 t(code_verifier)的已轉換密碼版本,也稱為 code_challenge。 然後,用戶端會在 OAuth 2.0 授權要求中傳送密碼以及 t_m 轉換方法。

在標示為 B 的區段中,授權端點會如往常回應,但會記錄 t(code_verifier) 秘密和轉換方法。

在標示為 C 的區段中,用戶端會像往常一樣傳送存取權杖要求中的授權碼,但包含 code_verifier 區段 A 中產生的密碼。

在標示為 D 的區段中,AD FS 會 code_verifier轉換秘密,並將它與區段 B 中的秘密進行 t(code_verifier) 比較。如果其值不相等,AD FS 會拒絕存取。

如何在 Windows Server 2019 中為相同的規則原則選擇多個驗證提供者

AD FS 已經支援根據宣告規則原則 (RP) 觸發額外的驗證。 您可以為特定 RP 或全域層級設定這些原則。 您可以以系統管理員身分開啟 PowerShell,並執行 Set-AdfsRelyingPartyTrust Cmdlet,傳遞 AdditionalAuthenticationRulesAdditionalAuthenticationRulesFile 參數,以設定特定 RP 的額外驗證原則。 若要全域設定,系統管理員可以使用 Set-AdfsAdditionalAuthenticationRule Cmdlet。 設定額外的原則可讓您針對相同的應用程式使用多個驗證提供者。

聲明規則提供選項來選擇驗證提供者以進行額外的驗證,這在客戶在提供者之間切換或針對特定應用程式需要不同的提供者時,非常有用。 從 Windows Server 2019 開始,您可以使用宣告規則來決定要叫用哪些其他驗證提供者來進行額外的驗證。 此功能在兩種情況下很有用:

  • 使用者正在從一個身份驗證提供者轉換到另一個身份驗證提供者。 當您將用戶上線至較新的驗證提供者時,他們可以使用群組來控制服務所使用的額外驗證提供者。

  • 使用者需要特定應用程式的特定額外驗證提供者,但也需要使用其他應用程式的不同方法。

您可以從其他驗證原則執行下列命令來設定這些設定:

Set-AdfsAdditionalAuthenticationRule -AdditionalAuthenticationRules 'c:[type == "http://schemas.microsoft.com/ws/2012/01/insidecorporatenetwork", value == "false"] => issue(type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", value = "http://schemas.microsoft.com/claims/multipleauthn" );' 

若要設定此規則,您必須從其他驗證原則發出宣告 http://schemas.microsoft.com/claims/authnmethodsproviders 。 此宣告的值應該是 驗證提供者的 Name 變數。

您也可以修改此規則組態,協助使用者從一個驗證提供者轉換到另一個驗證提供者。 例如,假設您想要修改您管理的一個群組,以使用 Microsoft Entra 多重要素驗證 (MFA),以及一個群組以使用憑證作為額外的驗證提供者。

如果您想要追蹤有多少人註冊 MFA 和憑證驗證,您可以執行如下命令,並將值取代為與您的組織相關的值:

'c:[type == "http://schemas.microsoft.com/ws/2012/01/insidecorporatenetwork", Value == "false"] => issue(type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", Value = "http://schemas.microsoft.com/claims/multipleauthn" ); 

 c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid", Value == "S-1-5-21-608905689-872870963-3921916988-12345"] => issue(Type = "http://schemas.microsoft.com/claims/authnmethodsproviders", Value = "AzureMfaAuthentication"); 

not exists([Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid", Value=="S-1-5-21-608905689-872870963-3921916988-12345"]) => issue(Type = "http://schemas.microsoft.com/claims/authnmethodsproviders", Value = "CertificateAuthentication");’ 

接下來,您可以執行下列命令,將第一個應用程式 (稱為 AppA) 設定為使用 MFA 作為額外的驗證提供者:

Set-AdfsRelyingPartyTrust -TargetName AppA -AdditionalAuthenticationRules 'c:[type == "http://schemas.microsoft.com/ws/2012/01/insidecorporatenetwork", Value == "false"] => issue(type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", Value = "http://schemas.microsoft.com/claims/multipleauthn" ); 

c:[] => issue(Type = "http://schemas.microsoft.com/claims/authnmethodsproviders", Value = "AzureMfaAuthentication");' 

最後,您可以執行下列命令,將第二個應用程式 (稱為 AppB) 設定為使用憑證作為額外的驗證提供者:

Set-AdfsRelyingPartyTrust -TargetName AppB -AdditionalAuthenticationRules 'c:[type == "http://schemas.microsoft.com/ws/2012/01/insidecorporatenetwork", Value == "false"] => issue(type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", Value = "http://schemas.microsoft.com/claims/multipleauthn" ); 

c:[] => issue(Type = "http://schemas.microsoft.com/claims/authnmethodsproviders", Value = "CertificateAuthentication");' 

系統管理員也可以制定規則,以允許多個額外的驗證提供者。 在此情況下,AD FS 會顯示已發出的驗證方法提供者,而且使用者可以選擇其中任何一個。 若要允許多個額外的驗證提供者,他們應該使用 值 http://schemas.microsoft.com/claims/authnmethodsproviders發出多個宣告。

如果宣告評估未傳回任何驗證提供者,AD FS 會恢復之前狀態並顯示一份清單,列出系統管理員在AD FS 上設定的所有額外驗證提供者。 然後,使用者必須手動選取適當的驗證提供者。

如果您慣用的驗證提供者不在清單中,您可以執行下列 Cmdlet 來檢視所有支援的提供者:

(Get-AdfsGlobalAuthenticationPolicy).AdditionalAuthenticationProvider

您用於宣告的 http://schemas.microsoft.com/claims/authnmethodsproviders 值應該是 AD FS 所提供的提供者清單中的其中一個提供者名稱。

AD FS 不支援在 AD FS Windows Server 2016 中的存取控制原則時啟用特定的額外驗證提供者。 當您將應用程式移出存取控制原則時,AD FS 會將對應的原則從存取控制原則複製到 AdditionalAuthenticationRulesIssuanceAuthorizationRules。 如果系統管理員想要使用特定的驗證提供者,他們應該停止使用存取控制原則,改為修改 AdditionalAuthenticationRules

代理者流程

Note

Microsoft 強烈建議遷移到 Microsoft Entra ID,而不是升級為較新版本的 AD FS。 更多關於 Microsoft Entra ID 的 On-Behalf-Of 流程資訊,請參閱 Microsoft 身份平台 裡的 On-Behalf-Of 流程。

OAuth 2.0 代替流程 (OBO) 用於處理應用程式叫用一個服務/Web API,而該 API 接著需要再呼叫另一個服務/Web API 的使用案例。 其概念是透過要求鏈傳播委派的使用者身分識別和權限。 若要讓中階層服務向下游服務提出已驗證的請求,它必須代表使用者從 AD FS 取得存取權杖。

通訊協議圖表

假設使用者使用上一節所述的 OAuth 2.0 授權碼授與流程在應用程式上進行驗證。 此時,應用程式持有一個 API A 的存取權杖 (權杖 A),其中包含使用者的宣告,並同意存取中層 Web API (API A)。 請確定用戶端要求存取權杖中的「user_impersonation」範圍。 現在,API A 必須向下游 Web API (API B) 提出已驗證的要求。

接下來的步驟會構成 OBO 流程,我們會透過下圖的協助加以說明。

顯示 On-Behalf-Of 流程的圖表。

  1. 用戶端應用程式會使用權杖 A 向 API A 提出要求。(當您在 AD FS 中設定 OBO 流程時,請確定已選取範圍 user_impersonation ,且用戶端在要求中要求 user_impersonation 範圍。
  2. API A 會向 AD FS 權杖發行端點進行驗證,並要求權杖以存取 API B。(當您在 AD FS 中設定此流程時,請確定 API A 也已註冊為伺服器應用程式,其用戶端識別碼與 API A 中的資源識別碼具有相同的值。
  3. AD FS 權杖發行端點會使用權杖 A 來驗證 API A 的認證,並發出 API B 的存取權杖 (權杖 B)。
  4. 令牌 B 設定在 API B 的請求授權標頭中。
  5. API B 會傳回來自受保護資源的資料。

服務間存取權杖請求

若要要求存取權杖,請使用下列各節所述的參數,對 AD FS 權杖端點進行 HTTP POST。

第一個案例:請求存取權杖並使用共享密鑰

對於共用祕密,服務對服務存取權杖要求會包含下列參數:

Parameter Required/optional Description
grant_type required 憑證請求的類型。 對使用 JWT 的請求,此值必須為 urn:ietf:params:oauth:grant-type:jwt-bearer。
client_id required 當您將第一個 Web API 註冊為伺服器應用程式 (中介層應用程式) 時,您設定的用戶端識別碼。 它應該與第一個分支中使用的資源識別碼相同,也就是第一個 Web API 的 URL。
client_secret required 您在 AD FS 中進行伺服器應用程式註冊時所建立的應用程式祕密。
判斷提示 required 要求中使用的權杖的值。
requested_token_use required 指定應該如何處理要求。 在 OBO 流程中,必須將值設定為 on_behalf_of。
資源 required 當您將第一個 Web API 註冊為伺服器應用程式 (中介層應用程式) 時提供的資源識別碼。 資源識別碼應該是第二個 Web API 的中介層應用程式代表用戶端進行呼叫時所使用的 URL。
範圍 optional 令牌要求的範圍以空格分隔的清單。
Example

下列 HTTP POST 請求存取權杖和更新權杖。

// Line breaks for legibility only

POST /adfs/oauth2/token HTTP/1.1
Host: adfs.contoso.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
&client_id=https://webapi.com/
&client_secret=BYyVnAt56JpLwUcyo47XODd
&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIm…
&resource=https://secondwebapi.com/
&requested_token_use=on_behalf_of
&scope=openid

第二個案例:含有憑證的存取權杖要求

含有憑證的服務對服務存取權杖要求會包含下列參數:

Parameter Required/optional Description
grant_type required 憑證請求的類型。 對使用 JWT 的請求,此值必須為 urn:ietf:params:oauth:grant-type:jwt-bearer。
client_id required 當您將第一個 Web API 註冊為伺服器應用程式 (中介層應用程式) 時,您設定的用戶端識別碼。 它應該與第一個分支中使用的資源識別碼相同,也就是第一個 Web API 的 URL。
client_assertion_type required 此值必須為 urn:ietf:params:oauth:client-assertion-type:jwt-bearer。
client_assertion required 一個斷言(JSON Web Token,JWT),需要您建立並使用您所註冊為應用程式認證的憑證以進行簽署。
判斷提示 required 要求中使用的權杖的值。
requested_token_use required 指定應該如何處理要求。 在 OBO 流程中,必須將值設定為 on_behalf_of。
資源 required 當您將第一個 Web API 註冊為伺服器應用程式 (中介層應用程式) 時提供的資源識別碼。 資源識別碼應該是第二個 Web API 的中介層應用程式代表用戶端進行呼叫時所使用的 URL。
範圍 optional 令牌要求的範圍以空格分隔的清單。

請注意,參數幾乎相同。 此範例與使用共享祕密的請求類似,不同之處在於 client_secret 參數被以下兩個參數取代:client_assertion_type 和 client_assertion。

Example

下列 HTTP POST 要求以憑證獲取 Web API 的存取權杖。

// Line breaks for legibility only

POST /adfs/oauth2/token HTTP/1.1
Host: https://adfs.contoso.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer
&client_id= https://webapi.com/
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=eyJhbGciOiJSUzI1NiIsIng1dCI6Imd4OHRHeXN5amNS…
&resource=https://secondwebapi.com/
&requested_token_use=on_behalf_of
&scope= openid

服務對服務存取令牌回應

成功回應是具有下列參數的 JSON OAuth 2.0 回應。

Parameter Description
token_type 表示權杖類型的值。 AD FS 唯一支援的類型是承載者 (Bearer)。
範圍 在令牌中授予的存取範圍。
expires_in 存取權杖的有效時間 (以秒為單位)。
access_token 要求的存取憑證。 呼叫服務可以使用此權杖來驗證接收服務。
id_token 一個 JWT。 應用程式可以將此權杖的區段解碼,以索取已登入使用者的相關資訊。 應用程式可以快取並顯示值,但不應依賴這些值來取得任何授權或安全性界限。
refresh_token 所要求存取權杖的刷新權杖。 目前的存取權杖到期後,呼叫服務可以使用此權杖來要求另一個存取權杖。
Refresh_token_expires_in 刷新令牌的有效時間長度(以秒為單位)。

成功的回應範例

下列範例顯示在請求網路 API 存取權杖時的成功回應。

{
  "token_type": "Bearer",
  "scope": openid,
  "expires_in": 3269,
  "access_token": "eyJ0eXAiOiJKV1QiLCJub25jZSI6IkFRQUJBQUFBQUFCbmZpRy1t"
  "id_token": "aWRfdG9rZW49ZXlKMGVYQWlPaUpLVjFRaUxDSmhiR2NpT2lKU1V6STFOa"
  "refresh_token": "OAQABAAAAAABnfiG…"
  "refresh_token_expires_in": 28800,
}

使用存取令牌來存取受保護的資源

現在,中介層服務可以使用在上一個回應範例中取得的權杖,向下游 Web API 提出經過驗證的要求。 在 Authorization 標頭中設定權杖。

Example

GET /v1.0/me HTTP/1.1
Host: https://secondwebapi.com
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJub25jZSI6IkFRQUJBQUFBQUFCbmZpRy1tQ…

用戶端認證授與流程

Note

Microsoft 強烈建議遷移到 Microsoft Entra ID,而不是升級為較新版本的 AD FS。 更多關於 Microsoft Entra ID 的客戶端憑證授予流資訊,請參閱 Microsoft 身份平台裡的客戶端憑證授予流。

您可以使用 RFC 6749 中指定的 OAuth 2.0 用戶端認證授與,使用應用程式的身分識別來存取 Web 託管資源。 這類型的授權常用於必須在背景中運行的伺服器對伺服器互動,無需與使用者直接互動。 這些類型的應用程式通常稱為精靈或服務帳戶。

OAuth 2.0 用戶端認證授與流程可允許 Web 服務 (機密用戶端) 在呼叫其他 Web 服務時,使用自己的認證來驗證,而不是藉由模擬使用者。 在此案例中,用戶端通常是中介層 Web 服務、精靈服務或網站。 為了獲得更高層級的保證,AD FS 也允許呼叫服務使用憑證 (而不是共用密碼) 作為認證。

通訊協議圖表

下圖顯示用戶端認證授與流程。

用戶端認證流程的圖表。

請求令牌

若要使用用戶端認證授與來取得權杖,請將要求傳送 POST 至 /token AD FS 端點,如下列各節所示。

第一個案例:請求存取權杖並使用共享密鑰

POST /adfs/oauth2/token HTTP/1.1
// Line breaks for legibility only

Host: https://adfs.contoso.com
Content-Type: application/x-www-form-urlencoded

client_id=00001111-aaaa-2222-bbbb-3333cccc4444
&client_secret=qWgdYAmab0YSkuL1qKv5bPX
&grant_type=client_credentials
Parameter Required/optional Description
client_id required AD FS 指派給應用程式的應用程式 (用戶端) 識別碼。
範圍 optional 您想要使用者同意的範圍清單 (以空格分隔)。
client_secret required 您在應用程式註冊入口網站中為應用程式產生的用戶端密碼。 用戶端密碼必須在傳送之前先進行 URL 編碼。
grant_type required 必須設定為 client_credentials

第二個案例:含有憑證的存取權杖要求

POST /adfs/oauth2/token HTTP/1.1

// Line breaks for legibility only

Host: https://adfs.contoso.com
Content-Type: application/x-www-form-urlencoded

&client_id=00001111-aaaa-2222-bbbb-3333cccc4444
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=eyJhbGciOiJSUzI1NiIsIng1dCI6Imd4OHRHeXN5amNScUtqRlBuZDdSRnd2d1pJMCJ9.eyJ{a lot of characters here}M8U3bSUKKJDEg
&grant_type=client_credentials
Parameter Required/optional Description
client_assertion_type required 此值必須設定為 urn:ietf:params:oauth:client-assertion-type:jwt-bearer。
client_assertion required 一個斷言(JSON Web Token,JWT),需要您建立並使用您所註冊為應用程式認證的憑證以進行簽署。
grant_type required 必須設定為 client_credentials
client_id optional AD FS 指派給應用程式的應用程式 (用戶端) 識別碼。 這是client_assertion的一部分,所以這裡不需要。
範圍 optional 您想要使用者同意的範圍清單 (以空格分隔)。

使用代幣

現在您已取得權杖,可使用權杖對資源提出要求。 當權杖過期時,請對 /token 端點重複提出要求,以取得全新的存取權杖。

GET /v1.0/me/messages
Host: https://webapi.com
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...

Note

Microsoft 強烈建議遷移到 Microsoft Entra ID,而不是升級為較新版本的 AD FS。 更多關於 Microsoft Entra ID 的資源擁有者密碼憑證授予流資訊,請參閱 Microsoft 身份平台裡的資源擁有者密碼憑證授予流。

資源擁有者密碼認證 (ROPC) 授與可讓應用程式直接處理其密碼來登入使用者。 ROPC 流程需要高度的信任和使用者參與。 只有在您無法使用其他更安全的流程時,才應使用此流程。

通訊協議圖表

下圖顯示 ROPC 流程。

ROPC 流程圖。

授權要求

ROPC 流程是一個單一請求,它會將用戶端識別和使用者的憑證傳送至 IDP,然後接收傳回的令牌。 在這麼做之前,用戶端必須要求使用者的電子郵件地址 (UPN) 和密碼。 要求成功之後,用戶端應會立即從記憶體中安全地釋出使用者認證。 絕對不能儲存它們。

// Line breaks and spaces are for legibility only

POST /adfs/oauth2/token HTTP/1.1
Host: https://adfs.contoso.com
Content-Type: application/x-www-form-urlencoded

client_id=00001111-aaaa-2222-bbbb-3333cccc4444
&scope= openid
&username=myusername@contoso.com
&password=SuperS3cret
&grant_type=password
Parameter Required/optional Description
client_id required 用戶端識別碼。
grant_type required 必須設為密碼。
使用者名稱 required 使用者的電子郵件地址。
密碼 required 使用者的密碼。
範圍 optional 以空格分隔的範圍清單。

成功的驗證回應

下列範例會顯示成功的令牌回應:

{
    "token_type": "Bearer",
    "scope": "openid",
    "expires_in": 3599,
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIn...",
    "refresh_token": "AwABAAAAvPM1KaPlrEqdFSBzjqfTGAMxZGUTdM0t4B4...",
    "refresh_token_expires_in": 28800,
    "id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJhdWQiOiIyZDR..."
}
Parameter Description
token_type 一律設定為 Bearer。
範圍 如果傳回存取權杖,此參數會列出存取權杖適用的範圍。
expires_in 所含存取權杖的有效時間 (以秒為單位)。
access_token 針對所要求的範圍發出。
id_token 一個 JWT。 應用程式可以將此權杖的區段解碼,以索取已登入使用者的相關資訊。 應用程式可以快取並顯示值,但不應依賴這些值來取得任何授權或安全性界限。
refresh_token_expires_in 所含重新整理權杖的有效期限(以秒計算)。
refresh_token 如果原始範圍參數包含 offline_access,則會發出此參數。

您可以使用刷新權杖來取得新的存取權杖和刷新權杖,使用本文中授權碼授與流程一節所述的相同流程。

裝置代碼流程

Note

Microsoft 強烈建議遷移到 Microsoft Entra ID,而不是升級為較新版本的 AD FS。 更多關於 Microsoft Entra ID 的裝置代碼流資訊,請參閱 Microsoft 身份平台裡的裝置代碼流。

裝置代碼授與可讓使用者登入輸入受限的裝置,例如智慧型電視、IoT 裝置或印表機。 若要啟用此流程,裝置會讓使用者在其他裝置的瀏覽器中造訪網頁以進行登入。 使用者登入後,裝置就能視需要取得訪問令牌和重新整理令牌。

通訊協議圖表

整個裝置程式碼流程與下圖所示的流程類似。 本文稍後會說明每個步驟。

顯示裝置程式碼流程的圖表。

裝置授權要求

用戶端必須先向驗證伺服器確認用來起始驗證的裝置和使用者代碼。 用戶端從 /devicecode 端點收集此要求。 在此要求中,用戶端也應包含需要向使用者取得的權限。 從傳送此要求開始,使用者只有 15 分鐘的時間登入 (expires_in 的一般值),因此只有在使用者指出已準備好登入時,才提出此要求。

// Line breaks are for legibility only

POST https://adfs.contoso.com/adfs/oauth2/devicecode
Content-Type: application/x-www-form-urlencoded

client_id=00001111-aaaa-2222-bbbb-3333cccc4444
scope=openid
Parameter Condition Description
client_id required AD FS 指派給應用程式的應用程式 (用戶端) 識別碼。
範圍 optional 以空格分隔的範圍清單。

裝置授權回應

成功的回應是 JSON 物件,其中包含允許使用者登入的必要資訊。

Parameter Description
device_code 用來在用戶端與授權伺服器之間驗證會話的長字串。 用戶端會使用此參數來向授權伺服器要求存取權杖。
user_code 向使用者顯示的一個短字串,用於識別次要裝置上的會話。
verification_uri 使用者應使用 user_code 前往該 URI 以進行登入。
verification_uri_complete 使用者應該帶著 user_code 前往指定的 URI,來進行登入。 它預先填入user_code,因此使用者不需要輸入該值。
expires_in Device_code 和 user_code 到期之前的秒數。
間隔 用戶端在每次輪詢要求之間應等待的秒數。
訊息 人類看得懂的字串,其中包含使用者的指示。 您可以以?mkt=xx-XX的形式在請求中包含查詢引數,以填入適當的語言文化代碼,以將其本地化。

驗證使用者

用戶端收到user_code和verification_uri之後,會向使用者顯示這些詳細數據,指示他們使用行動電話或電腦瀏覽器登入。 此外,客戶端可以使用 QR 代碼或類似的機制來顯示 verification_uri_complete,這樣就可以自動代替使用者輸入 user_code。 當使用者在 verification_uri 進行驗證時,客戶端應該使用 device_code 輪詢要求的 /token 端點以獲取 token。

POST https://adfs.contoso.com /adfs/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type: urn:ietf:params:oauth:grant-type:device_code
client_id: 00001111-aaaa-2222-bbbb-3333cccc4444
device_code: GMMhmHCXhWEzkobqIHGG_EnNYYsAkukHspeYUk9E8
Parameter Required/optional Description
grant_type required 必須是urn:ietf:params:oauth:grant-type:device_code。
client_id required 必須符合初始要求中使用的 client_id。
字碼 required 裝置授權請求中傳回的 device_code。

成功的驗證回應

成功的權杖回應可以包含下列參數:

Parameter Description
token_type 一律為 Bearer
範圍 如果傳回存取權杖,此參數會列出存取權杖適用的範圍。
expires_in 包含存取令牌有效的秒數。
access_token 針對所要求的範圍發出。
id_token 如果原始範圍參數包含 openid 範圍,則會發出此參數。
refresh_token 如果原始範圍參數包含 offline_access,則會發出此參數。
refresh_token_expires_in 包含的刷新權杖有效時間,以秒為單位。

如需逐步解說文章的完整清單,請參閱 AD FS 開發,其中會提供如何使用相關流程的逐步指示。