簡體   English   中英

.Net Core 3.1 合並 JWT 和 OpenIDConnect 身份驗證

[英].Net Core 3.1 Merging JWT and OpenIDConnect Authentication

簡短版本:我在將 .NET Core MVC 網站中的正確身份驗證配置合並在一起時遇到問題,以允許我的用戶針對 Azure Active Directory 進行身份驗證,但也允許守護進程連接(來自控制台應用程序)。

長版:我有一個 .NET Core MVC 網站,當在 Startup.cs 的 ConfigureServices 方法中使用以下內容時,它對 Azure Active Directory 進行身份驗證非常好:

 services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddSignIn("AzureAd", Configuration, options => Configuration.Bind("AzureAd", options));

我還試圖讓我的 .NET 核心控制台應用程序調用 API(作為守護程序連接)到上述 MVC 網站(所有都在我的 Microsoft Azure 帳戶的應用程序注冊部分配置) 我可以將控制台應用程序連接到 MVC 網站,它會在 controller 中成功命中操作結果,但前提是我在網站的 Startup.cs 的 ConfigureServices 方法中使用以下內容:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
   .AddProtectedWebApi("AzureAd", Configuration, options => Configuration.Bind("AzureAD", options));

這是架構圖...

基本上,如果我只使用 OpenIdConnect 選項,我的 web 用戶可以訪問該網站,但我的控制台應用程序被拒絕。 如果我只使用 JwtBearer 選項,那么我的控制台應用程序可以連接,但我的 web 用戶被拒絕。

我整天都在用 Google-Bing,我正在努力讓這兩種配置的混搭工作,而不會將另一個淘汰。

我曾嘗試使用 .AddJwtBearer() 方法,但完全被它弄糊塗了:

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
   .AddSignIn("AzureAd", Configuration, options => Configuration.Bind("AzureAd", options))
   .AddJwtBearer(options => Configuration.Bind("AzureAD", options));

這些如何協同工作,這樣兩者都可以就位,我的 web 應用程序可以通過瀏覽器運行,並且控制台應用程序(守護程序)也可以工作? 我可以將兩者都綁定到我的 appsettings.json 文件嗎?

順便說一句,appsettings.json 文件如下所示:

{
  "AzureAd": {
  "Instance": "https://login.microsoftonline.com/",
  "Domain": "zzzzzzzzzzzzzz.onmicrosoft.com",
  "TenantId": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy",
  "ClientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "CallbackPath": "/signin-oidc",
  "SignedOutCallbackPath ": "/signout-callback-oidc",
  "ClientSecret": "myAzureClientSecret"
  }
}

更新 2020-06-15:在為 AGES 開啟/關閉此功能后,我找到了一個合適的解決方案,因此我將賞金積分授予@michael-shterenberg。 此外,我現在知道我可以從 @gary-archer 和他令人印象深刻的博客網站中學到很多東西。 我只是碰巧從邁克爾的投入中獲得了成功。

這是 Startup.cs 文件的 mods,在上圖中的 ASP.NET Core MVC Web App 中:

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddSignIn("AzureAd", Configuration, options =>     
          Configuration.Bind("AzureAd", options))
            .AddJwtBearer(o =>
            {
                o.Authority = "https://login.microsoftonline.com/common";
                o.TokenValidationParameters.ValidateAudience = false;
                o.TokenValidationParameters.ValidateIssuer = false;
            });

services.AddAuthorization(options =>
    {
        options.AddPolicy("UserAndApp", builder =>
        {                    
             builder.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);

builder.AuthenticationSchemes.Add(OpenIdConnectDefaults.AuthenticationScheme);

             builder.RequireAuthenticatedUser();
        });
    });

...再加上在我試圖從守護程序應用程序調用的 Controller 上使用以下屬性。

[Authorize("UserAndApp")]

我的用戶仍然可以使用 Azure Active Directory 進程登錄網站,現在我的自動化進程也可以登錄。

如果有人難以理解 Azure 應用程序注冊方面的所有這些工作原理,請嘗試這篇真正解釋性的博客文章:

使用承載身份驗證保護 .NET 核心 API

(我希望我早先看到這一點,當我試圖了解 Azure 應用程序注冊過程的工作原理時!)

這是對我有用的解決方案(在 ASP .NET Core 2.1 和 3.1 上測試)

  1. 不要設置默認身份驗證方案,因為您有 2 種類型(Cookie 和 JWT)。 即您對AddAuthentication的調用應該沒有參數:
services.AddAuthentication()
   .AddAzureAD(options => Configuration.Bind("AzureAd", options))
   .AddJwtBearer(o=> {
       o.Authority = "https://login.microsoftonline.com/common";
       o.TokenValidationParameters.ValidateAudience = false;
       o.TokenValidationParameters.ValidateIssuer = false;
});
  • 請注意,我明確沒有綁定您的 AD 配置,因為需要將/common應用於權限(或租戶 ID)
  • 此外,我將受眾和頒發者的驗證設置為 false,以便任何 AAD 令牌都可以用於測試。 您顯然應該設置正確的受眾/發行者
  • 我使用AddAzureAd而不是AddSignIn (您使用的是自定義外部庫嗎?)

    1. 創建一個接受兩種身份驗證方案的策略:
services.AddAuthorization(options =>
{
    options.AddPolicy("UserAndApp", builer =>
    {
        builer.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
        builer.AuthenticationSchemes.Add(AzureADDefaults.AuthenticationScheme);

        builer.RequireAuthenticatedUser();
    });
});
  • 將此替換為您現有的授權設置
    1. 在 controller 中使用新策略名稱:
[Authorize("UserAndApp")]
public class HomeController : Controller

關於機制的一些解釋:

您不想設置自動身份驗證方案,因為這將是授權中間件中運行的默認模式,而您有 2 種不同的類型

該策略將嘗試運行兩個身份驗證處理程序,如果其中一個成功,則身份驗證成功

注意:如果您使用無效的 Bearer 令牌發送請求,則兩個身份驗證處理程序都將失敗,在這種情況下, AzureADDefaults將“獲勝”,因為它實際上實現了質詢方法並將重定向您(狀態代碼 302),因此請確保處理這個在你的應用程序中

感覺架構不太對勁,需要把你的 Web Back End 執行的 2 個角色分開:

當前僅 WEB 架構

  • 您有一個使用身份驗證 cookies 的 Web UI 前端
  • 您有一個 Web 后端,需要 cookies 用於查看請求
  • 您有一個 Web 后端需要 cookies 來處理 API 請求
  • 您有一個無法使用 cookies 的控制台客戶端,因此無法調用 API 入口點

多客戶端架構

You'll need to update the web back end to include API entry points that are secured by OAuth 2.0 access tokens and not by cookies. 然后,控制台應用程序將能夠調用您的 web 后端。

.NET 核心子路徑

在 web 后端引入額外的 /api 子路徑。 UseWhen功能將允許您在不影響其他 web 后端行為的情況下執行此操作:

/*
 * Apply API behaviour to only subpaths, without impacting the rest of the app
 */ 
app.UseWhen(
ctx => ctx.Request.Path.StartsWithSegments(new PathString("/api")),
api => {
  api.useAuthentication();
  api.useJwtBearer();
});

示例 .NET 核心 API

有關使用子路徑的示例,請參閱我的Sample.Net Core API 啟動 class是 ASP.Net 中間件與不同子路徑的不同身份驗證處理連接的地方。

未來的可能性

一旦你有了上述邏輯分離,你可能會在未來進一步發展它,例如到一個完全無 cookie 的 model:

  • 僅基於令牌將 API 開發為完全獨立的組件
  • 將 Web UI 更新為使用客戶端安全庫的 SPA

我在https://authguidance.com的博客遵循這種方法,我的示例 API 都支持任何類型的客戶端。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM