如何使用 .AddJwtBearer() 在 .NET Core Web API 中驗證 AWS Cognito JWT
我在弄清楚如何在我的 .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)) })