Dot-Net-Core

如何使用 .AddJwtBearer() 在 .NET Core Web API 中驗證 AWS Cognito JWT

  • March 1, 2022

我在弄清楚如何在我的 .NET Core Web API 中驗證 AWS Cognito 提供給客戶端的 JWT 時遇到了一些麻煩。

我不僅不知道變數Microsoft.IdentityModel.Tokens.TokenValidationParameters應該是什麼,而且一旦我終於知道了,我不知道如何從中檢索 JWT 密鑰集https://cognito-idp.{region}.amazonaws.com/{pool ID}/.well-known/jwks.json

最後,儘管進行了大量隨機Google搜尋和反複試驗,我找到了一個(看似不是非常有效的解決方案)的解決方案。然而,我花了太多時間去做這件事。引用這一點,再加上 AWS 文件嚴重缺乏這一事實,我決定發布此問答,以幫助其他人在未來更輕鬆地找到此解決方案。

如果有更好的方法可以做到這一點,有人告訴我,因為除了下面列出的答案之外,我還沒有找到一種方法來做到這一點。

答案主要在於正確定義TokenValidationParameters.IssuerSigningKeyResolver(此處看到的參數等:https ://docs.microsoft.com/en-us/dotnet/api/microsoft.identitymodel.tokens.issuersigningkeyresolver?view=azure-dotnet )。

這就是告訴 .NET Core 驗證發送的 JWT 的內容。還必須告訴它在哪裡可以找到鍵列表。不一定要對密鑰集進行硬編碼,因為它經常由 AWS 輪換。

一種方法是從方法內的 URL 獲取和序列化列表IssuerSigningKeyResolver。整體.AddJwtBearer()可能看起來像這樣:

Startup.cs ConfigureServices() 方法:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
               .AddJwtBearer(options =>
               {
                   options.TokenValidationParameters = new TokenValidationParameters
                   {
                       IssuerSigningKeyResolver = (s, securityToken, identifier, parameters) =>
                       {
                           // get JsonWebKeySet from AWS
                           var json = new WebClient().DownloadString(parameters.ValidIssuer + "/.well-known/jwks.json");
                           // serialize the result
                           var keys = JsonConvert.DeserializeObject<JsonWebKeySet>(json).Keys;
                           // cast the result to be the type expected by IssuerSigningKeyResolver
                           return (IEnumerable<SecurityKey>)keys;
                       },

                       ValidIssuer = "https://cognito-idp.{region}.amazonaws.com/{pool ID}",
                       ValidateIssuerSigningKey = true,
                       ValidateIssuer = true,
                       ValidateLifetime = true,
                       ValidAudience = "{Cognito AppClientID}",
                       ValidateAudience = true
                   };
               });

如果你使用AWS Amplify等JS庫,你可以通過觀察結果在瀏覽器控制台中看到ValidIssuer和等參數ValidAudience``Auth.currentSession()

利用上面實現的 JWT 身份驗證以及使用[Authorize]控制器上的標記,從 JS 客戶端到 .NET Core Web API 的 REST 獲取請求可能如下所示:

使用 @aws-amplify/auth 節點包的 JS 客戶端:

// get the current logged in user's info
Auth.currentSession().then((user) => {
fetch('https://localhost:5001/api/values',
 {
   method: 'GET',
   headers: {
     // get the user's JWT token given to it by AWS cognito 
     'Authorization': `Bearer ${user.signInUserSession.accessToken.jwtToken}`,
     'Content-Type': 'application/json'
   }
 }
).then(response => response.json())
.then(data => console.log(data))
.catch(e => console.error(e))
})

引用自:https://stackoverflow.com/questions/53244446