使用 Azure AD 和 OpenID Connect 進行驗證

Azure Active Directory
App Service - Web Apps

範例程式碼

Surveys 應用程式會使用 OpenID Connect (OIDC) 通訊協定,透過 Azure Active Directory (Azure AD) 驗證使用者。 Surveys 應用程式會使用 ASP.NET Core,其具有內建的 OIDC 中介軟體。 下圖概括顯示使用者登入時會發生什麼情況。

Authentication flow

  1. 使用者在應用程式中按一下 [登入] 按鈕。 這個動作是由 MVC 控制器處理。
  2. MVC 控制器會傳回 ChallengeResult 動作。
  3. 中介軟體會攔截 ChallengeResult 並建立 302 回應,進而將使用者重新導向至 Azure AD 登入頁面。
  4. 使用者會向 Azure AD 進行驗證。
  5. Azure AD 會將 ID 權杖傳送至應用程式。
  6. 中介軟體會驗證 ID 權杖。 此時,使用者已在應用程式內驗證。
  7. 中介軟體會將使用者重新導向回到應用程式。

使用 Azure AD 註冊應用程式

若要啟用 OpenID Connect,SaaS 提供者會在自己的 Azure AD 租用戶內註冊應用程式。

若要註冊應用程式,請遵循快速入門:使用 Microsoft 身分識別平臺 註冊應用程式中的步驟。

若要在範例 Surveys 應用程式中啟用此功能,請參閱GitHub讀我檔案。 請注意:

  • 對於多租使用者應用程式,您必須明確設定多租使用者選項。 這可讓其他組織存取應用程式。

  • 回覆 URL 是 Azure AD 要做為 OAuth 2.0 回應傳送目的地的 URL。 在使用 ASP.NET Core 時,這必須符合您在驗證中介軟體中設定的路徑 (請參閱下一節)。

設定驗證中介軟體

本節說明如何在 ASP.NET Core 中設定驗證中介軟體,以便利用 OpenID Connect 進行多租用戶驗證。

在您的啟動類別中加入 OpenID Connect 中介軟體:

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
  .AddMicrosoftIdentityWebApp(
    options =>
    {
        Configuration.Bind("AzureAd", options);
        options.Events = new SurveyAuthenticationEvents(loggerFactory);
        options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.Events.OnTokenValidated += options.Events.TokenValidated;
    })
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddDownstreamWebApi(configOptions.SurveyApi.Name, Configuration.GetSection("SurveyApi"))
    .AddDistributedTokenCaches();

請注意,secrets.json 檔案中會提供部分設定。 檔案必須具有名為 AzureAd 的區段,且具有下列設定:

  • 實例。 對於多租用戶應用程式,將此選項設定為 https://login.microsoftonline.com。 這是 Azure AD 一般端點的 URL,可讓任何 Azure AD 租用戶的使用者進行登入。
  • ClientId。 當您在 Azure AD 中註冊應用程式時所得到之應用程式的用戶端識別碼。
  • TenantId。 用來在組織中登入使用者的 GUID。

以下是其他中介軟體選項的意義:

  • SignInScheme。 將此選項設定為 CookieAuthenticationDefaults.AuthenticationScheme。 此設定表示在驗證使用者之後,使用者宣告就會儲存在本機在 Cookie 中。 此 Cookie 是使用者在瀏覽器工作階段期間保持已登入狀態的方法。
  • 事件。 事件回呼;請參閱 驗證事件

起始驗證流程

若要在 ASP.NET MVC 中啟動驗證流程,請從控制器傳回ChallengeResult

[AllowAnonymous]
public IActionResult SignIn()
{
    return new ChallengeResult(
        OpenIdConnectDefaults.AuthenticationScheme,
        new AuthenticationProperties
        {
            IsPersistent = true,
            RedirectUri = Url.Action("SignInCallback", "Account")
        });
}

這會導致中介軟體傳回可重新導向至驗證端點的 302 (找到) 回應。

使用者登入工作階段

如上所述,當使用者第一次登入時,Cookie 驗證中介軟體會將使用者宣告寫入至 Cookie。 之後,系統會藉由讀取 Cookie 來驗證 HTTP 要求。

根據預設,Cookie 中介軟體會寫入工作階段 Cookie,當使用者關閉瀏覽器後便會遭到刪除。 使用者下次瀏覽網站時,則必須再次登入。 不過,如果您將 ChallengeResult 中的 IsPersistent 設定為 true,中介軟體便會寫入永續性 Cookie,讓該名使用者在關閉瀏覽器之後仍保持登入。 您可以設定 Cookie 到期日;請參閱控制 Cookie 選項。 持續性 Cookie 對使用者而言比較方便,但可能不適用於您希望使用者每次登入的一些應用程式 (例如,銀行應用程式)。

關於 OpenID Connect 中介軟體

ASP.NET 中的 OpenID Connect 中介軟體會隱藏大部分的通訊協定詳細資料。 本節包含一些有關實作的注意事項,這對於了解通訊協定流程很有幫助。

首先,讓我們從 ASP.NET 的角度 (忽略應用程式與 Azure AD 之間的 OIDC 通訊協定流程細節) 檢查驗證流程。 下圖顯示此程序。

Sign-in flow

在此圖中,有兩個 MVC 控制器。 帳戶控制器會處理登入要求,而首頁控制器會為首頁提供服務。

以下是驗證程序:

  1. 使用者按一下「登入」按鈕,而瀏覽器會傳送 GET 要求。 例如:GET /Account/SignIn/
  2. 帳戶控制器會傳回 ChallengeResult
  3. OIDC 中介軟體會傳回 HTTP 302 回應,並重新導向至 Azure AD。
  4. 瀏覽器會將驗證要求傳送至 Azure AD
  5. 使用者登入 Azure AD,而 Azure AD 會送回驗證回應。
  6. OIDC 中介軟體會建立宣告主體,並將它傳遞給 Cookie 驗證中介軟體。
  7. Cookie 中介軟體會將宣告主體序列化並設定 Cookie。
  8. OIDC 中介軟體會重新導向至應用程式的回呼 URL。
  9. 瀏覽器會遵循重新導向,並在要求中傳送 Cookie。
  10. Cookie 中介軟體會將此 Cookie 還原序列化為宣告主體,並設定 HttpContext.User 等於宣告主體。 要求會路由傳送至 MVC 控制器。

驗證票證

如果驗證成功,OIDC 中介軟體會建立驗證票證,其中包含保存使用者宣告的宣告主體。

注意

在整個驗證流程完成之前,HttpContext.User 仍會保有匿名主體,而「不是」已驗證的使用者。 匿名主體具有空的宣告集合。 在驗證完成且應用程式重新導向之後,Cookie 中介軟體將驗證 Cookie 還原序列化並將 HttpContext.User 設定為代表已驗證使用者的宣告主體。

驗證事件

在驗證過程中,OpenID Connect 中介軟體會引發一連串的事件:

  • RedirectToIdentityProvider。 緊接在中介軟體重新導向至驗證端點前呼叫。 您可以使用此事件來修改重新導向 URL;例如,以便新增要求參數。 請參閱新增系統管理員同意提示,以取得範例。
  • AuthorizationCodeReceived。 使用授權碼來呼叫。
  • TokenResponseReceived。 在中介軟體從 IDP 取得存取權杖後,但在其通過驗證前呼叫。 僅適用於授權碼流程。
  • TokenValidated。 在中介軟體驗證 ID 權杖之後呼叫。 此時,應用程式有一組關於使用者的已驗證宣告。 您可以使用此事件對宣告執行額外的驗證,或轉換宣告。 請參閱使用宣告
  • UserInformationReceived。 如果中介軟體從使用者資訊端點取得使用者設定檔,則會呼叫。 僅適用於授權碼流程,而且只有在中介軟體選項中的 GetClaimsFromUserInfoEndpoint = true 時使用。
  • TicketReceived。 在驗證完成時呼叫。 這是最後一個事件,並假設驗證成功。 在此事件處理之後,使用者就會登入應用程式。
  • AuthenticationFailed。 如果驗證失敗時,則會呼叫。 使用此事件來處理驗證失敗,例如,重新導向至錯誤頁面。

若要為這些事件提供回呼,請在中介軟體設定 [事件] 選項。 有兩種不同的方式可宣告事件處理常式:使用 lambda 內嵌,或在衍生自 OpenIdConnectEvents 的類別中內嵌。 如果事件回呼有任何實質邏輯,則建議使用第二種方法,如此才不會擾亂您的啟動類別。 我們的參考實作使用這種方法。

OpenID 連線端點

Azure AD 支援 OpenID Connect 探索,會由識別提供者 (IDP) 傳回已知端點的 JSON 中繼資料文件。 中繼資料文件包含的資訊如下:

  • 授權端點的 URL。 這是應用程式重新導向來驗證使用者的位置。
  • 「結束工作階段」端點的 URL,也就是應用程式即將登出使用者的位置。
  • 用以取得簽署金鑰的 URL,而用戶端會使用這些金鑰來驗證它從 IDP 取得的 OIDC 權杖。

根據預設,OIDC 中介軟體會知道如何擷取此中繼資料。 請在中介軟體中設定 [授權] 選項,中介軟體便會建構此中繼資料的 URL。 (您可以藉由設定 MetadataAddress 選項來覆寫中繼資料 URL)。

OpenID 連線流程

根據預設,OIDC 中介軟體會使用混合式流程搭配表單 POST 回應模式。

  • 「混合式流程」表示用戶端可以在同一回往返存取授權伺服器時取得 ID 權杖和授權碼。
  • 表單後回應模式 表示授權伺服器會使用 HTTP POST 要求,將識別碼權杖和授權碼傳送至應用程式。 這些值會使用表單 URL 方式進行編碼 (content type = "application/x-www-form-urlencoded")。

當 OIDC 中介軟體重新導向至授權端點時,重新導向 URL 會包含 OIDC 所需的所有查詢字串參數。 混合式流程:

  • client_id。 此值是在 ClientId 選項中設定。
  • scope = "openid profile",這表示它是 OIDC 要求而且我們想要使用者的設定檔。
  • response_type = 「code id_token」。 這會指定混合式流程。
  • response_mode = "form_post"。 這會指定表單 POST 回應。

若要指定不同的流程,請設定選項的 ResponseType 屬性。

app.AddAuthentication().AddOpenIdConnect(options =>
{
    options.ResponseType = "code"; // Authorization code flow

    // Other options
}

下一步