C#のAPIに認証・認可を追加する方法!JWTでセキュリティを強化しよう
生徒
「C#でAPIを作れるようになりました!でも、誰でもアクセスできてしまうのが少し不安です…。」
先生
「素晴らしい悩みですね。Webの世界では、勝手に入られないように『鍵』をかけることが非常に重要です。」
生徒
「鍵ですか?どうやってAPIに鍵をかければいいのでしょうか?」
先生
「それが『認証』と『認可』です。今回はJWTという仕組みを使って、安全なAPI通信を作る方法を一緒に学びましょう!」
1. 認証と認可の基本を理解しよう
WebAPIを作る上で避けて通れないのが、セキュリティの確保です。まずは「認証(Authentication)」と「認可(Authorization)」という二つの言葉の違いを、現実世界の例えで解説します。
認証とは、「あなたは誰ですか?」を確認することです。会員証を見せたり、IDとパスワードを入力したりする行為がこれに当たります。例えるなら、会社に入る時に社員証を見せて、自分が従業員であることを証明するのと同じです。
認可とは、「その人は何ができるのか?」を確認することです。社員証を見せて会社に入れたとしても、機密情報の部屋まで入れるわけではありませんよね。このように「特定の操作をする権限があるか」を判断するのが認可です。
C#のASP.NET Coreというフレームワークを使うと、この複雑な仕組みを比較的簡単に実装できます。特に現代のWeb開発では、JWTという技術が標準的に使われています。
2. JWTとは何か?その仕組みをわかりやすく解説
JWTは「JSON Web Token」の略称です。コンピューターの世界で通信をする際、毎回毎回「私は誰々です」と証明書を提示するのは大変です。そこで、最初にログインした時に「あなたは正当なユーザーですよ」という証明書を、暗号化されたデータの形(これがJWTです)として発行します。
このJWTをクライアント(ブラウザやアプリなど)が受け取り、次からサーバーに何かをお願いするたびに、このトークン(デジタルな通行手形のようなもの)を添えるのです。サーバーは、その通行手形の中身を見て、「ふむ、これは本物だな。では要求に応じよう」と判断します。
JWTのメリットは、サーバー側で毎回データベースを確認しなくても、持ってきたトークンの中身が正しいかを計算だけで検証できるため、処理が速いことです。初心者の方でも、まずはこの「通行手形を受け取って、使うたびに見せる」という流れを理解すれば大丈夫です。
3. プロジェクトに認証機能を追加する準備
まずはC#のプロジェクトで、JWTの認証機能を使えるように設定します。ASP.NET Coreには、認証のための便利なライブラリがあらかじめ用意されています。
プロジェクトのプログラムで、認証サービスを追加します。これが「鍵を開けるための仕組み」を有効にする操作です。
// Program.csなどの設定ファイルに認証を追加します
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "JwtBearer";
options.DefaultChallengeScheme = "JwtBearer";
})
.AddJwtBearer("JwtBearer", options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "my-site",
ValidAudience = "my-site",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("秘密の鍵をここに設定します"))
};
});
ここで重要なのは「秘密の鍵」です。これがトークンを偽造されないためのガードレールになります。この文字列は誰にも知られないように厳重に管理しなければなりません。
4. ログインAPIを作ってJWTを発行しよう
認証機能を使うためには、最初にJWTを発行するAPIが必要です。ユーザーが正しいユーザー名とパスワードを入力した時に、サーバー側でこのトークンを作成して返却します。
[HttpPost("login")]
public IActionResult Login([FromBody] LoginRequest request)
{
// ここでユーザー名とパスワードをチェックします
if (request.Username == "admin" && request.Password == "password")
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.UTF8.GetBytes("秘密の鍵をここに設定します");
var descriptor = new SecurityTokenDescriptor
{
Expires = DateTime.UtcNow.AddHours(1), // 1時間だけ有効
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(descriptor);
return Ok(new { token = tokenHandler.WriteToken(token) });
}
return Unauthorized();
}
この処理では、もしパスワードが正しければトークンを作り返します。もし間違っていれば、HTTPステータスコードの401(Unauthorized=許可されていません)を返します。これが「認証」の基本ステップです。
5. 特定の機能に制限をかける「認可」の実装
認証ができたら、次は「認可」です。例えば、商品の一覧を見るのは誰でもいいけれど、商品の追加や削除は管理者だけができるようにしたい、といったケースです。
C#では、非常に簡単に「この機能はログインした人しか使えない」と指定できます。それが「属性(Attribute)」という便利な機能です。
[Authorize] // これを書くだけで、ログインしていない人はアクセス拒否されます
[HttpGet("secret-data")]
public IActionResult GetSecretData()
{
return Ok("あなただけが知っている秘密の情報です!");
}
このコードにある[Authorize]という記述が「認可」の魔法です。このタグをAPIのメソッドやコントローラーの頭につけるだけで、ASP.NET Coreが自動的に「このリクエストにJWTはついているか?」「そのトークンは本物か?」をチェックしてくれます。
6. 開発時に知っておくべき注意点とセキュリティ
最後に、安全にAPIを運用するためのポイントをいくつかお伝えします。パソコン初心者の方でも、これだけは覚えておいてください。
一つ目は、通信の暗号化です。APIの通信が暗号化されていないと、悪意のある人が途中で通信を盗み見て、大切なトークンを奪い取る可能性があります。必ず「HTTPS」という通信方法を使いましょう。
二つ目は、秘密鍵の管理です。ソースコードの中に直接パスワードを書くと、万が一コードを誰かに公開した時に、鍵が盗まれてしまいます。環境変数と呼ばれる、別の場所に鍵を保存する仕組みを使うのがプロの常識です。
三つ目は、トークンの有効期限です。一度発行したトークンは、いつまでも使えるわけではありません。通常は数時間から数日程度で使えなくなるように設定し、安全を保ちます。
セキュリティ対策は終わりのない道のりですが、まずはこれらの基本をしっかり守るだけで、非常に堅牢なシステムを作ることができます。C#のAPI開発は、このような細やかな気配りがコードの美しさに繋がります。