自分のアプリのログインの形を、毎回頭がこんがらがるので整理した記録です。難しい話というより、混ぜて考えてた2つを分けたら一気にほどけた、という整理。
ここで言う「web」は、綴ったものを web でも見られるように開発中のアプリ(紡Book)のことです。
綴Photo は、モバイルアプリと、それを見せる web でできています。「アプリに本物のログインを足す」をずっと考えていて、調べるたびに頭が混乱していた。原因は単純で、別々の2つを1つの塊として考えていたから。分けたらほどけたので残しておく。
モバイルにログインを足す一連の作業のうち、「誰が認証するか」と「どう戻すか」の方式だけを抜き出して整理した回。
混乱の元:「誰が認証するか」と「どう戻すか」は別の話
ログインには2つの問いがあります。
- 誰がログインさせるか(本人確認の本体)
- その結果をどうアプリに渡すか(戻り道)
これを混ぜると「アプリにログイン機能を作る」が一個の重い塊に見えます。分けると、別々に決められます。しかも①は、自分の場合まるごと web に投げられます。
①誰が認証するか:web に丸投げ。アプリは Google を持たない
アプリは Google と直接喋りません。アプリはブラウザで自分の web のログイン画面を開きます。web 側で Google ログイン(これは前から動いています)。アプリは結果だけ受け取ります。
うまみは、アプリに Google の設定(OS ごとのクライアント登録、Console 作業)を一切入れずに済むこと。後で Apple を足すのも web 側だけで済みます。
②どう戻すか:ブラウザからアプリへ。ここが今回の本題
ブラウザとアプリは別プロセスだから、ログイン後にブラウザが引換券をアプリへ渡す道が要ります。これが戻り道。
ここで大事な気づき。どの方式でも、アプリが「この戻り道は自分が受け取る」と OS に登録するのは避けられません(後述の custom scheme でも登録は必須)。これが「結局ネイティブ認証に戻ったのでは?」という勘違いの元だった。でもこれは認証じゃなくて、ただの配管。
戻り道の作り方は2つ。
- (a) custom scheme(
アプリ名://)=軽い。でも OS はこのスキームを誰が登録したか検証しない=別アプリが同じアプリ名://を後から登録でき、引換券がそっちに落ちうる(横取り)。
- (b) App Links / Universal Links=OS が「この https の戻り道を受け取れるのは、ドメイン側が正規と認めた署名のアプリだけ」を検証する https リンク。custom scheme に無かった“登録主の検証”が入るのが差。
App Links = “検証済みの表札が付いた郵便受け”
2つの方式で「受け取り手を誰が決めるか」を並べると、差が1箇所しかないのが見えます。
効いているのは端末の側にある何かではなく、ドメインを持っている自分が「このアプリ」と先に名指ししてあることです。名指しの相手はアプリの署名(開発者の鍵の指紋)なので、鍵を持たない偽アプリはそこに入れません。
だから偽アプリは https://tsuzuphoto.com/... の戻り道を横取りできない=引換券が偽の郵便受けに落ちません。「横取り→乗っ取り」を構造で塞げます。
大事なのは、これは「誰かを認証していいか」を確かめているんじゃなく、「引換券を本物のアプリにだけ届ける」配達保証だということ。認証は①の web のまま。「OS の認証を作る」じゃなく「OS に正しい配達先を保証させる」が近いです。
App Links を選んだ理由と、その代償
2つの方式を並べると、何を取って何を捨てたかが見える。
| 方式 | 軽さ | 横取り耐性 | localhost で試せる |
|---|---|---|---|
| custom scheme(アプリ名://) | 軽い | 運用でしか下げられない(構造では消えない) | 試せる |
| App Links(検証済み https) | 重い(本番ドメイン検証が要る) | 構造で消せる | 試せない(トンネル/staging が要る) |
custom scheme の横取りは運用(明示確認・state=行きの要求と返ってきた結果が同じ一件かを照合する番号札・短命 code)でしか下げられません。App Links なら構造で消せます。公開を見据えるなら構造で消したいので、App Links を選んだ。
これは前に web の中継をレビューしたとき(③)に「custom scheme を足す日が本当の山場」と後回しにした穴の、回収でもある。custom scheme を足さず App Links に倒したので、あの穴は取り付ける前に塞げた。
代償もある。表の通り、App Links は本番の https ドメインに対して OS が検証する=localhost で dev 確認できません。実機確認にはトンネル(開発中の自分の PC を一時的に本物のドメインとして外から触れるようにする仕組み)か staging(本番そっくりの練習用サーバ)が要ります。custom scheme なら localhost で回せた分のトレードオフで、ここは「堅さ」を取った。
今日入れたのは web 側の土台(許可リストと戻り道ページ)を AI に入れてもらった分だけ。戻り道の https リンクを許可リストに入れる(完全一致=同じドメインでも別パスは弾く)のと、戻り道のフォールバックページ。
# App Links/Universal Links: 自ドメインの検証済み戻り道だけ(完全一致)。
# ↑ host も path もピッタリ一致だけ許可=同じ tsuzuphoto.com でも別パスには引換券を出さない
# (ドメイン内に open-redirect の隙を作らない)。
# parsed = 戻ってきた URL を「https / ドメイン / パス」の部品にバラしたもの
if (
parsed.scheme == "https" # 暗号化された https か
and parsed.hostname in _HTTPS_RETURN_HOSTS # ドメインが自分のか(例 {"tsuzuphoto.com"})
and parsed.path == _HTTPS_RETURN_PATH # パスもピッタリ同じか("/app-login/return")
):
return True残り(ドメイン直下の検証ファイル設置、アプリ側の登録)は、必要な値(アプリの署名情報など)が揃ってから。
学びポイント
- 「ログインを作る」を「誰が認証するか」と「どう戻すか」に分けます。 混ぜると重い塊に見えるが、分けると別々に決められて、しかも①は web に丸投げできます。
- 戻り道の OS 登録は「ネイティブ認証」じゃなく「配管」。 どの方式でも要ります。App Links はその配管を”検証済み”にするだけで、認証そのものとは別。
- App Links は認証じゃなく「正しい配達先の保証」。 ここを混同すると「結局ネイティブに戻った?」と勘違いする(した)。
- 堅さには代償があります。 軽さ(custom scheme・localhost で試せる)と堅さ(App Links・横取りを構造で消す)はトレードオフ。今回は公開を見据えて堅さを選んだ。
おわりに
形が見えたら、重く感じていたログインが「web に丸投げ+検証済みの戻り道」の2部品に分解できた。web 側の土台は今日 AI に入れてもらった。残りはアプリ側の登録と検証ファイルで、それは値が揃ってから。分けて考える、が今回の一番の収穫だった。
この記事は2026年6月時点の自分の理解で書いています。仕様や認識が変わってる可能性があります。