5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

.NET 8.0でAPIがJWTの検証に失敗するようになった場合は、JsonWebTokenを使うように構成を変更してみる

Last updated at Posted at 2024-03-21

はじめに

.NET 6.0から.NET 8.0へバージョンアップ後、JWTで認証を行っているWebAPIが常に401で終了する事象に遭遇しました。.NET 8.0への移行は基本的にはライブラリを.NET8.0に対応した最新版へ置き換えるだけで問題なく作業できましたが、こいつだけ対応に調査が必要だったのでメモを残しておきます。

2024/07/17追記
「現象1:invalid_tokenと表示されJWTの検証が失敗する」の対応方法に問題がありました。以前の実装ではJWTの署名検証が行われなくなるので注意してください。

原因は破壊的変更 セキュリティ トークン イベントが JsonWebToken を返すにある通り.NET8.0の破壊的変更が原因で、JWTを検証する内部の実装がJwtSecurityTokenからJsonWebTokensに置き換えられたためでした。

.NET6.0から8.0の破壊的変更は次のページにまとまっています。

現象1:invalid_tokenと表示されJWTの検証が失敗する

正しい署名がされたJWTであってもJWTの検証が失敗し、401が返却されます。

request
curl -X 'GET' \
  'http://localhost:5100/api/v1/Hello' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjNBQTdFQ...略...
response
HTTP/1.1 401 Unauthorized
Content-Length: 0
Date: Thu, 21 Mar 2024 00:29:22 GMT
Server: Kestrel
WWW-Authenticate: Bearer error="invalid_token", error_description="The signature key was not found"

ログには下記のようにセキュリティーキーが見つからないために、署名の検証が失敗したというメッセージが表示されます。

[09:19:27 INF] Failed to validate the token.
Microsoft.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException: IDX10500: Signature validation failed. No security keys were provided to validate the signature.
   at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateSignature(JsonWebToken jwtToken, TokenValidationParameters validationParameters, BaseConfiguration configuration)
   at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateSignatureAndIssuerSecurityKey(JsonWebToken jsonWebToken, TokenValidationParameters validationParameters, BaseConfiguration configuration)
   at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateJWSAsync(JsonWebToken jsonWebToken, TokenValidationParameters validationParameters, BaseConfiguration configuration)
[09:19:27 INF] Bearer was not authenticated. Failure message: IDX10500: Signature validation failed. No security keys were provided to validate the signature.

ブレーキングチェンジには、SecurityTokenの実装がJwtSecurityTokenからJsonWebTokenに変更されたため、コード内でJwtSecurityTokenをダウンキャストして使っていたり、SignatureValidatorを差し替えている場合に問題が発生するとあります。

2024/07/17追記
以前のJwonWebTokenを単純に返却する方法では、JWTの検証がスキップされJWTの偽装されても検知できません。以下の対応を検討してください。

今回はどちらにも当てはまらない状況でエラーが表示されました。調べていくと、Microsoft.IdentityModelから始まるライブラリが推移的に解決され、依存するライブラリのバージョンが崩れてしまったことが問題でした。
StackOverflowにコメントがありました。

Microsoft.IdentityModelから始まる複数のライブラリで異なるバージョンが選択されていたので、プロジェクトに明示的に参照したり、不要な参照を削除したりして同じバージョンを参照するように調整して対応しました。
また、Microsoft.IdentityModel.TokensSystem.IdentityModel.Tokens.Jwtの両方が参照されていたので、System.IdentityModel.Tokens.Jwtの参照を削除したところ正しく署名の検証がおこなわれつつ、JWTのエラーも発生しなくなりました。

現象2:JwtSecurityTokenHandlerでクレームのマッピングをクリアしている場合は、JsonWebTokenHandlerに置き換える

subクレームを直に参照して値を確認しているコードで、subクレームを参照できない問題が発生しました。
例えば、次のデコードされたJWTの場合、

{
  "iss": "https://*********",
  "aud": [ "https://****/resources" ],
  "scope": [ "openid", "profile" ],
  "amr": [ "pwd" ],
  "client_id": "****",
  "sub": "testuser@example.com",
  "idp": "local",
  
  ... 以下略 ...
}

クレームを.NETでウォッチすると次のように表示されました。
subクレームや、armクレームidpクレームなどがnameidentifierなどに変換されています。
image.png

Program.cs内でJwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear()を呼び出してマッピングを構成している部分があったので、JwtSecurityTokenHandlerからJsonWebTokenHandlerに変更しました。

-JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
+JsonWebTokenHandler.DefaultInboundClaimTypeMap.Clear();

image.png

おわりに

バージョンアップ時は破壊的変更をちゃんと読もう

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?