by WebSurfer
4. April 2026 12:35
.NET 10 の ASP.NET Core Web API プロジェクトにデフォルトでインストールされている Microsoft.AspNetCore.OpenApi (以降「組込み OpenAPI」と書きます) と SwaggerUI (UI だけ) を使って [Authorize] ボタンを表示し、ベアラートークン (JWT) を使っての認証に必要な操作を行うことができるよう実装してみました。

先の記事「.NET 10 ASP.NET Core Web API で Swagger を使用」では SwaggerGen + SwaggerUI を使って実装しましたが、.NET 10 で組込み OpenAPI が使える状況ではそれは本筋ではなさそうですので。
過去はどうしていたのかも知っておいた方が理解しやすいと思いますので、.NET 8 からの経緯を以下に書きます。
-
Visual Studio のテンプレートを使って作成する .NET 8 の ASP.NET Core Web API プロジェクトでは Swashbuckle.AspNetCore がデフォルトでインストールされている。
-
Swashbuckle の SwaggerGen が OpenAPI ドキュメントを生成し、SwaggerUI が OpenAPI ドキュメントを解釈してブラウザ上で API のテストを行うことができる UI を提供していた。(参考: Swashbuckle と ASP.NET Core を始めよう)
-
.NET 9 以降では ASP.NET Core Web API プロジェクトには組込み OpenAPI が含まれるようになった。それゆえ Swashbuckle は含まれなくなった。(参考: Announcement: Swashbuckle.AspNetCore is being removed in .NET 9 )
-
SwaggerUI は、組込み OpenAPI が生成する OpenAPI ドキュメントを解釈して UI を提供できる。したがって、組込み OpenAPI + SwaggerUI (UI だけ) で .NET 8 の時と同様にブラウザ上で API のテストができる。(参考: ローカルのアドホック テストに Swagger UI を使用する)
-
ただし、 [Authorize] ボタンを表示し、ベアラートークンを使っての認証に必要な操作を行うことができるようするためには OpenAPI ドキュメントのカスタマイズが必要 (Security Scheme と Security Requirement の追加が必要)。
-
OpenAPI ドキュメントをカスタマイズするには、組込み OpenAPI + SwaggerUI の場合、トランスフォーマーを用いる。(参考: OpenAPI ドキュメントのトランスフォーマー)
-
Program.cs でトランスフォーマーを実装し、OpenAPI ドキュメントに Security Scheme と Security Requirement を追加すれば、前者により [Authorize] ボタンの表示とトークンの設定、後者によりベアラートークンの送信ができるようになる。
ということで、下の画像の通り、組込み OpenAPI (Microsoft.AspNetCore.OpenApi 10.0.5) と Swashbuckle.AspNetCore.SwaggerUI 10.1.7 をインストールし、[Authorize] ボタンを表示して認証に必要な操作を行うことができるよう実装してみました。

トランスフォーマーを実装した Program.cs のコードは以下の通りです。「方法1」のコードは Securing OpenAPI and Swagger UI with OAuth in .NET 10 を参考に、「方法2」のコードはドキュメント トランスフォーマーを使用するを参考にしました。下のコード例では、「方法2」の登録をコメントアウトしてありますので、「方法1」のみが有効になっています。どちらの方法でも OpenAPI ドキュメントのカスタマイズ結果は同じになります。
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi;
using System.Text;
namespace WebApi3
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
// JWT 認証の設定
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!))
};
});
builder.Services.AddAuthorization();
// OpenAPI ドキュメントのトランスフォーマー設定(方法1)
builder.Services.AddOpenApi(options =>
{
options.AddDocumentTransformer((document, context, cancellationToken) =>
{
// OpenAPI ドキュメントの基本情報を設定(無くても可)
document.Info = new OpenApiInfo
{
Title = "ASP.NET Core Web API",
Version = "v1",
Description = "ASP.NET Core Web API with JWT authentication. " +
"Target Framework is .NET 10. " +
"Built‑in OpenAPI + SwaggerUI are used."
};
// Security Scheme を追加(JWT Bearer)
document.Components ??= new OpenApiComponents();
document.Components.SecuritySchemes ??=
new Dictionary<string, IOpenApiSecurityScheme>();
document.Components.SecuritySchemes.Add("Bearer",
new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT",
Description = "Please enter token"
});
// Security Requirement を追加
document.Security ??= new List<OpenApiSecurityRequirement>();
document.Security.Add(
new OpenApiSecurityRequirement
{
// インデクサ初期化子
[new OpenApiSecuritySchemeReference("Bearer", document)] = []
}
);
return Task.CompletedTask;
});
});
// OpenAPI ドキュメントのトランスフォーマー設定(方法2)
//builder.Services.AddOpenApi(options =>
//{
// options.AddDocumentTransformer<JwtSecurityTransformer>();
//});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/openapi/v1.json", "v1");
});
}
app.UseHttpsRedirection();
// 認証と認可のミドルウェアを追加
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
}
// 方法2に用いる Transformer の実装
// IAuthenticationSchemeProvider をコンストラクタへの DI で
// 受け取ることで、登録されている認証スキームに Bearer が含
// まれることを確認してから Security Scheme を追加する
internal sealed class JwtSecurityTransformer(IAuthenticationSchemeProvider provider)
: IOpenApiDocumentTransformer
{
public async Task TransformAsync(OpenApiDocument document,
OpenApiDocumentTransformerContext context,
CancellationToken cancellationToken)
{
// OpenAPI ドキュメントの基本情報を設定(無くても可)
document.Info = new OpenApiInfo
{
Title = "ASP.NET Core Web API",
Version = "v1",
Description = "ASP.NET Core Web API with JWT authentication. " +
"Target Framework is .NET 10. " +
"Built‑in OpenAPI + SwaggerUI are used."
};
// Security Scheme を設定(JWT Bearer)
var authenticationSchemes = await provider.GetAllSchemesAsync();
if (authenticationSchemes.Any(authScheme => authScheme.Name == "Bearer"))
{
var securitySchemes = new Dictionary<string, IOpenApiSecurityScheme>
{
// インデクサ初期化子
["Bearer"] = new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT",
Description = "Please enter token"
}
};
document.Components ??= new OpenApiComponents();
document.Components.SecuritySchemes = securitySchemes;
}
// Security Requirement を設定
document.Security = [
new OpenApiSecurityRequirement
{
[new OpenApiSecuritySchemeReference("Bearer", document)] = []
}
];
}
}
}
上のトランスフォーマーにより OpenAPI ドキュメントに Security Scheme と Security Requirement が追加されます。下の画像を見てください。赤枠が OpenAPI ドキュメント上の Security Scheme 部分、青枠が Security Requirement 部分になります。

SwaggerUI は、上の赤枠部分を解釈して [Authorize] ボタンの表示とトークンの設定、青枠部分を解釈してベアラートークンの送信ができる実装を追加します。