備忘録

備忘録

ASP.NETでJWTを利用して認証認可する方法

Ⅰ. はじめに

タイトルの通り「ASP.NETでJWTを利用して認証認可する方法」です。

Ⅱ. 環境

  • .NET 7

Ⅲ. 手順

1. 必要なパッケージをインストールする
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer --version 7.0.10
2. 新規Web APIプロジェクトを作成する

Program.cs

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Security.Claims;
using System.Text;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization();

var jwtIssuer = "https://example.com";
var jwtKey = "24f959f5ef4c4126a2996ba618bb46796070307b4837416091c9ed20bbd156a5";

builder.Services
  .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddJwtBearer(options =>
  {
    // HttpContext.Userにマップしない
    options.MapInboundClaims = false;

    options.TokenValidationParameters = new TokenValidationParameters
    {
      ValidIssuer = jwtIssuer,
      ValidAudience = jwtIssuer,
      IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtKey)),
    };
  });

var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();

// 認証不要
app.MapGet("/test001", (HttpContext context) =>
{
  return "test001";
});

// 認証必須
app.MapGet("/test002", (HttpContext context) =>
{
  var userId = context.User.FindFirstValue("user_id");
  return $"userId: {userId ?? "null"}";
}).RequireAuthorization();

app.Run();
3. 新規コンソールアプリケーションを作成する
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

var jwtIssuer = "https://example.com";
var jwtKey = "24f959f5ef4c4126a2996ba618bb46796070307b4837416091c9ed20bbd156a5";

var claims = new List<Claim>
{
    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString("N")),
    new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss:fff")),
    new Claim("user_id", "1000")
};

var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtKey));
var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha512);

var token = new JwtSecurityToken(
    jwtIssuer,
    jwtIssuer,
    claims,
    expires: DateTime.Now.AddDays(1),
    signingCredentials: signingCredentials
);

var jwt = new JwtSecurityTokenHandler().WriteToken(token);
Console.WriteLine(jwt);

実行結果

JWT生成結果

eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIwNTFjYzkwNjQ2Yzg0NWFjYWRiYjBjOWFhZjdiNjY2ZiIsImlhdCI6IjIwMjMvMDkvMTEgMTc6MDA6NDE6Mzg1IiwidXNlcl9pZCI6IjEwMDAiLCJleHAiOjE2OTQ1MDU2NDEsImlzcyI6Imh0dHBzOi8vZXhhbXBsZS5jb20iLCJhdWQiOiJodHRwczovL2V4YW1wbGUuY29tIn0.fm3nxVNH-dGV09cvlF_7779o_FhcG9HhArqJWWzHLIcZf531wXi_sfM9F40f27EqOiYZI7Bi1xxIvQEzzMi1rA
# 実行結果
認証不要
認証必須

FAQ

  • Q. algにnoneを指定したJWTを利用した場合は認可されますか?
    A. いいえ。されません。以下エラーが出力されます。
HTTP/1.1 401 Unauthorized
Content-Length: 0
Connection: close
Date: Mon, 11 Sep 2023 07:49:53 GMT
Server: Kestrel
WWW-Authenticate: Bearer error="invalid_token", error_description="The signature key was not found"