はじめに
Webアプリケーション開発において、認証(Authentication) と 認可(Authorization) は必ずと言っていいほど登場するセキュリティの基本概念です。しかし、この2つは混同されやすく、正確に説明できないエンジニアも少なくありません。
この記事でわかること:
- 認証と認可それぞれの意味と役割の違い
- 具体例や図を使った直感的な理解
- コードレベルでの両者の違い(401 vs 403 の使い分けも含む)
- 現場でよくある落とし穴
認証(Authentication)とは?
認証とは、「あなたは誰ですか?」を確認する仕組みです。
英語の Authentication を略して AuthN と書くこともあります。
身近な例で理解する
ホテルのチェックインを想像してください。フロントスタッフは「ご予約のお客様ですか?」と確認するため、身分証明書の提示を求めます。これが認証です。あなたが「誰であるか」を証明するプロセスです。
Webアプリでは、ログイン画面でメールアドレスとパスワードを入力する行為がこれに相当します。
認証の種類
認証方式は大きく3種類に分類できます。
| 分類 | 内容 | 例 |
|---|---|---|
| 知識認証 | 本人だけが知っていること | パスワード、PINコード、秘密の質問 |
| 所持認証 | 本人だけが持っているもの | スマートフォン(SMS認証)、物理トークン |
| 生体認証 | 本人の身体的特徴 | 指紋、顔認証、虹彩 |
複数の方式を組み合わせる 多要素認証(MFA) は、現代のセキュリティのベストプラクティスとなっています。
認可(Authorization)とは?
認可とは、「あなたは何をしていいですか?」を決める仕組みです。
英語の Authorization を略して AuthZ と書くこともあります。
身近な例で理解する
先ほどのホテルの例を続けましょう。チェックインが完了した(=認証済み)お客様でも、他の客室には入れませんし、スタッフ専用エリアにも立ち入れません。どの部屋に入れるか、どのエリアを使えるかを制御するのが認可です。
Webアプリでは、ログイン済みの一般ユーザーが管理者ページ(/admin)にアクセスしようとしたとき、「権限がありません」と弾く仕組みがこれに相当します。
認可の基本的な考え方:RBAC
代表的な認可モデルに RBAC(Role-Based Access Control:ロールベースアクセス制御) があります。ユーザーにロール(役割)を割り当て、ロールごとに許可する操作を定義します。
ユーザー → ロール → 権限(パーミッション)
例:
田中さん → admin ロール → 全ページ閲覧・編集・削除
鈴木さん → viewer ロール → 全ページ閲覧のみ
佐藤さん → editor ロール → 自分の記事の閲覧・編集
認証と認可の違いを整理する
比較表
| 項目 | 認証(AuthN) | 認可(AuthZ) |
|---|---|---|
| 問い | あなたは誰ですか? | あなたは何をしていいですか? |
| 目的 | 本人確認 | アクセス制御 |
| タイミング | 先に行う | 認証の後に行う |
| 失敗時のHTTPステータス | 401 Unauthorized |
403 Forbidden |
| 例 | ログイン | 管理者ページへのアクセス制限 |
フローで見る認証と認可
コードで見る認証と認可
PythonのFlaskを使った簡単な例で、両者の違いを実装レベルで確認しましょう。
認証チェック:ログインしているかどうか
from functools import wraps
from flask import request, jsonify
def require_auth(f):
"""認証チェック:有効なトークンを持っているか確認する"""
@wraps(f)
def decorated(*args, **kwargs):
token = request.headers.get("Authorization")
user = verify_token(token) # トークンを検証してユーザーを取得
if user is None:
# 認証失敗 → 401 Unauthorized
return jsonify({"error": "ログインが必要です"}), 401
return f(user, *args, **kwargs)
return decorated
認可チェック:必要な権限を持っているか
def require_role(role):
"""認可チェック:指定されたロールを持っているか確認する"""
def decorator(f):
@wraps(f)
def decorated(user, *args, **kwargs):
if user.role != role:
# 認可失敗 → 403 Forbidden
return jsonify({"error": "この操作を行う権限がありません"}), 403
return f(user, *args, **kwargs)
return decorated
return decorator
ルートへの適用
@app.route("/admin")
@require_auth # まず認証チェック
@require_role("admin") # 次に認可チェック
def admin_page(user):
return jsonify({"message": f"ようこそ、管理者 {user.name} さん"})
401 と 403 の使い分けまとめ
401 Unauthorized →「誰かわからない」 → ログインしてください
403 Forbidden →「誰かはわかる」 → でもあなたには権限がありません
この2つを混同して両方 403 で返したり、すべて 401 で返したりするコードを見ることがありますが、クライアント側の適切なハンドリングのためにも正しく使い分けることが大切です。
Tips:現場でよくある落とし穴
落とし穴1:認証だけして認可を忘れる
ログイン機能を実装した後、「ログインしてさえいれば全ページOK」という設計にしてしまうケースがあります。しかし、ユーザー種別によってアクセスできるリソースを分けるべき場合は必ず認可も実装しましょう。
悪い例:
ログイン済み → /admin にアクセス可能(一般ユーザーも!)
良い例:
ログイン済み かつ admin ロール → /admin にアクセス可能
落とし穴2:フロントエンドだけで認可を制御する
「管理者でなければボタンを表示しない」という制御をフロントエンドだけで行うのは危険です。APIエンドポイント側でも必ず認可チェックを行ってください。フロントエンドのチェックはあくまでUX向上のためのものです。
フロントエンド:UIの表示・非表示(UX目的)
バックエンド:実際のアクセス制御(セキュリティ目的)← 必須
落とし穴3:JWTのペイロードを信頼しすぎる
JWT(JSON Web Token)を使った認証では、ペイロードにユーザー情報が含まれます。
しかし、ペイロードを信頼するには、下記の要素も必要です。
まず署名を検証し、トークンが改ざんされていないことを確認します。そのうえで、少なくとも次のクレームも検証し、「このシステム向けに発行された、現在も有効なトークン」であることを確認します。
| クレーム | 確認する内容 |
|---|---|
iss(Issuer) |
信頼する発行者が発行したか |
aud(Audience) |
自分のシステム向けに発行されたか |
exp(Expiration Time) |
有効期限が切れていないか |
署名だけを検証してクレームを確認しないと、別のサービス向けに発行されたトークンや、期限切れのトークンを受け入れてしまう可能性があります。
# 悪い例:署名もクレームも検証せずにペイロードを読む
import base64, json
payload = json.loads(base64.b64decode(token.split(".")[1] + "=="))
# 良い例:署名に加えて発行者・受け取り手・有効期限を検証する
import jwt
payload = jwt.decode(
token,
SECRET_KEY,
algorithms=["HS256"],
issuer="https://auth.example.com",
audience="my-api",
options={"require": ["iss", "aud", "exp"]},
)
まとめ
この記事で学んだことを振り返ります。
-
認証(AuthN) は「あなたは誰ですか?」を確認する仕組みで、失敗時は
401 -
認可(AuthZ) は「あなたは何をしていいですか?」を制御する仕組みで、失敗時は
403 - 認証は認可より先に行う
- フロントエンドだけでなく、バックエンドでも必ず認可チェックを実装する
- JWTを使う場合は署名に加えて
iss・aud・expなどのクレームも検証する
次のステップ
認証・認可の基礎を理解したら、以下のトピックに進むとさらに理解が深まります。
- OAuth 2.0 / OpenID Connect:外部サービスを使った認証・認可の標準プロトコル
- JWT(JSON Web Token):トークンベース認証の詳細
- RBAC / ABAC:より高度なアクセス制御モデル
- AWS IAM / GCP IAM:クラウドにおける認可の実践