FlaskでAPI専用の認証レイヤーを作る設計パターンを徹底解説!初心者でも理解できる安全なAPIの作り方
生徒
「FlaskでAPIを作りたいんですが、誰でもアクセスできてしまうと困りますよね?どうやって安全にすればいいんですか?」
先生
「その通りです。APIは認証がとても重要で、専用の認証レイヤーを設計するのが基本になります。」
生徒
「認証レイヤーってどんなものなんでしょうか?難しい言葉が多くてよくわかりません。」
先生
「簡単に言うと、家の玄関に付いている鍵のような役割ですね。家に入る前に鍵を確認するように、APIにアクセスする前にもユーザーの身元を確認する部分のことです。今日はその仕組みを理解できるようにゆっくり説明していきます。」
1. API専用の認証レイヤーとは何か?初心者向けにわかりやすく解説
API専用の認証レイヤーとは、APIにアクセスする前に必ず通過しなければならない安全のための「関所」のようなものです。みなさんが遊園地に入るとき、まずチケットを確認しますよね。それと同じで、APIでもアクセスのたびに正しいユーザーかどうかを識別する仕組みが必要になります。
特にFlaskでAPIを作る場合、画面を持たないためブラウザのログイン画面がありません。このため、APIを利用するプログラムが毎回正しい情報を送ってきたかどうかを確かめる必要があります。この仕組みが認証レイヤーです。
認証レイヤーはFlaskのアプリ全体を守る盾のような役割を持ち、どれだけAPIが増えても、このレイヤーを通過しなければ内部のデータや処理には触れられません。初心者にとっては少し難しく感じるかもしれませんが、仕組みを理解すれば安全にAPIを設計できるようになります。
2. APIの認証にトークンが使われる理由
一般的なWebサイトのように「ユーザー名とパスワードを毎回送る」という仕組みでは、APIでは安全性が足りません。そこで使われるのがトークンという技術です。トークンとは、ログイン成功時に渡される一時的な通行証のようなものです。
例えば、映画館で一度チケットを買うと入場証をもらえますよね。入場証があればスタッフに何度も支払い確認を見せなくても入れます。APIでも同じで、一度認証するとトークンが発行され、それをAPIが受け取ることで正しいユーザーかどうか確認できます。
Flaskではこのトークンを使うことで、パスワードを毎回送らなくてよくなり、安全で効率の良いAPIを作ることができます。
3. Flaskで作る認証レイヤーの基本パターン
FlaskでAPI専用認証レイヤーを設計するときは、大きく分けて三つのステップがあります。
① ログインAPIを用意してトークンを発行する
ユーザー名とパスワードが正しければトークンを作成します。
② 認証レイヤーをミドルウェアとして実装する
APIを実行する前に必ずトークンの検証を行う仕組みを作ります。
③ 個々のAPI処理ではユーザー情報を利用するだけにする
認証はレイヤー側に任せ、API本体は本来の処理だけに集中できます。
このようにレイヤーを分離することで、APIが増えても同じ方法で認証を扱えるため、管理が格段に楽になります。
4. トークンを発行するFlaskのサンプル
以下は認証レイヤーで使うトークンを発行するもっともシンプルな例です。コードは読み物として見てみてください。
from flask import Flask, request, jsonify
import jwt, datetime
app = Flask(__name__)
SECRET = "secret-key"
@app.route("/login", methods=["POST"])
def login():
user = request.json.get("username")
pw = request.json.get("password")
if user == "user" and pw == "pass":
token = jwt.encode({
"sub": user,
"exp": datetime.datetime.utcnow() + datetime.timedelta(minutes=20)
}, SECRET, algorithm="HS256")
return jsonify({"token": token})
return jsonify({"error": "invalid"}), 401
5. 認証レイヤーとしてAPIの前でトークンを検証する
API専用認証レイヤーは、実際にはFlaskのリクエスト処理を「横からチェックする仕組み」です。全てのAPIに同じチェックを書いていくのは大変なので、共通の関数でまとめて処理します。
def require_token(view):
def wrapper(*args, **kwargs):
token = request.headers.get("Authorization")
try:
jwt.decode(token, SECRET, algorithms=["HS256"])
return view(*args, **kwargs)
except:
return jsonify({"error": "forbidden"}), 403
return wrapper
このように装飾のように認証チェックを付与できるため、APIに認証を付ける作業がとても楽になります。
6. 認証レイヤーを使ったAPIの実行イメージ
実際のAPIでは次のように使います。
@app.route("/items")
@require_token
def items():
return jsonify({"items": ["apple", "banana"]})
このように認証レイヤーを共通化すると、安全なAPIを構築しつつ管理も簡単になります。Flaskは柔軟な設計ができるため、認証をレイヤーとして切り出すことでアプリ全体が整理され、初心者でも無理なく安全なAPI設計ができるようになります。