綴Photo に Google / Apple のログインを足したときの、設計判断のメモです。勉強のため。
もともとメール + パスワードのログインを作っていたが、2026-05-11 に OAuth のみに切り替えてメール認証は削除した。その切り替えと合わせて「Google でログイン」「Apple でログイン」を足したときの話で、一番効いた理解は、増えるのは入口だけで、出口はいじらないだった。
入口が増えるだけ、出口は変えない
ログインを「本人確認(入口)」と「トークンを発行してブラウザに持たせる(出口)」に分けて考えます。
ここで一つ決めた。ソーシャルログイン用のライブラリ(dj-rest-auth)にも Cookie をセットする機能もあるが、それは使わず、メール + パスワード時代に作っていた自前の set_token_cookies() に出口を一本化することにした。
# 入口(本人確認)は Google でも Apple でも、出口はこの1関数に集約する
class AppleLoginView(SocialLoginView): # dj-rest-auth: ログイン用の API を生やす土台
adapter_class = AppleOAuth2Adapter # allauth: Apple と実際に話す係
def get_response(self):
user = self.user
refresh = RefreshToken.for_user(user) # SimpleJWT: JWT の実物を作る
# ↓ ここが「出口」。既存ログインと同じ関数を通す=Cookie 名も有効期限もズレない
return set_token_cookies( # 自前: JWT を Cookie に載せる出口
Response({"detail": "login ok"}), # DRF: HTTP レスポンスの器
refresh,
)この短いクラスに、4つのライブラリが同居しています。設定ファイルで詰まったとき「どのライブラリの設定を直せばいいのか」が分からなくなるのは、これが1か所に混ざって見えているからで、行ごとに出所を貼ると読めるようになります(それぞれの係は最後にまとめた)。
出口が2系統あると、Cookie の名前や有効期限が微妙にズレて「片方のログインだけ挙動が違う」という静かなバグになります。
Google と Apple は対称じゃない
「ソーシャルログイン」とひとくくりにしていたけど、Google と Apple は手触りがかなり違った。並べてみて初めて分かった差。
| Apple | ||
|---|---|---|
| 受け取るトークン | access_token | id_token |
| ローカルで試せる | できる(localhost 可) | できない(https 必須) |
| Client ID | 1つで Web / アプリ共通 | 2つ(Web 用と アプリ用で別) |
| 必要なもの | Google Cloud(無料) | Apple Developer(年99ドル) |
特に効いたのは下2つ。Client ID とは「このアプリは綴Photoです」と名乗る名札のこと。Google は名札1枚で Web もアプリも通るが、Apple は Web 用(Service ID)とアプリ用(Bundle ID)で別の名札を要求します。Google の「1個で両方いける」感覚のまま進めると詰まります。
env の置き場所も Google と Apple で変えた。
もう一つの罠。.p8 の中身は改行を含むので、env には \n でエスケープして1行で入れて、読むときに実際の改行へ戻します。
# .p8 は PEM 形式の秘密鍵 = 元々複数行のテキスト。env は改行を持てないので \n に変換して1行で入れ、読むときに戻す
"certificate_key": os.environ.get("APPLE_CERTIFICATE_KEY", "").replace("\\n", "\n"),誰が何の係か
詰まったとき効いたのは、ライブラリの役割を分けて覚えること。
- allauth … 外部サービス(Google / Apple)に本人確認を委託する係
- dj-rest-auth … 本人確認のあとに JWT を返す API を生やす橋渡し係
- SimpleJWT … JWT そのものを作る・検証する係(メール + パスワードのときから変わらない)
- DRF(Django REST Framework) … そもそも API を作るための土台。ログイン専用の部品ではなく、
Responseのような「HTTP で受け答えする道具」を提供している係
紛らわしいのが DRF と dj-rest-auth が別物なところで、名前が似ているせいで「DRF が JWT を生やしてくれる」と読み違えやすいです。生やすのは dj-rest-auth の方で、DRF はその下にある土台にすぎません。
トークンの本体(SimpleJWT)は前から同じ。腑に落ちると設定ファイルのどの行が何のためにあるかが読めるようになった。
この記事は2026年6月時点の自分の理解で書いています。仕様や認識が変わってる可能性があります。