ディープリンク(Universal Links/App Links)
URLをタップしたらブラウザではなくアプリの目的の画面が直接開く。なりすまし防止・遅延ディープリンク・検証ファイルの原理を一本で押さえられる。
- カスタムスキームは任意アプリが同名を登録でき横取りされる危険があるのに対し、Universal Links/App LinksはHTTPS URLとサーバー上の検証ファイルでドメイン所有権を証明し、なりすましを原理的に防ぐ。
- 検証はiOSがapple-app-site-association、AndroidがassetlinksJSONを対象ドメインの決まったパスから取得し、アプリのApp ID/署名フィンガープリントと突き合わせて成立する。
- 未インストール時にどの画面を開くべきかを保持する遅延ディープリンクは、OS標準機能では解決できずクリップボードや確率的マッチングに頼るため、精度と正確性のトレードオフを設計で引き受ける必要がある。
URLでアプリの特定画面を開くという課題
ディープリンクとは、Webページの1URLが特定のコンテンツを指すのと同じように、1本のURLをアプリ内の特定の画面・状態へ直接対応づける仕組みです。メールのボタン、SNSの共有リンク、他アプリからの遷移がホーム画面ではなく目的の商品ページや会話画面をそのまま開くために不可欠です。実現方式は大きく2系統あり、両者の本質的な違いは「そのリンクを本当に自分のアプリが受け取ってよいと、誰がどう保証するか」に集約されます。
横にスクロール
カスタムスキームとその弱点
古くからある方式がmyapp://product/42のようなカスタムURLスキームです。アプリはインストール時にOSへmyappというスキームを登録し、OSはそのスキームのURLが開かれたときに登録アプリを起動します。仕組みは単純ですが、致命的な弱点があります。スキーム名はグローバルに一意ではなく、複数のアプリが同じ名前を登録できてしまうのです。
iOSではどのアプリが起動するかが不定になり、Androidでは選択ダイアログ(ディスアンビゲーション)が出るか、後から入れた悪意あるアプリが同名スキームを奪って正規アプリになりすませます。決済トークンや認証コードをこのURLに載せると、横取りアプリに漏洩する経路が生まれます。加えて、対象アプリが未インストールならスキームURLは何も解決できず、ブラウザ側ではエラーになるだけでフォールバック先も自前で用意する必要があります。
OAuthのリダイレクトなどでカスタムスキームを使う場合、認可コードやトークンが同名スキームを登録した別アプリに渡る危険があります。iOS/Androidともにこのリスクへの対処としてPKCEやクレーム済みHTTPSリダイレクト(後述のUniversal Links/App Links)の利用が推奨されており、スキーム単体での機密受け渡しは避けるべきです。
Universal Links/App Links:HTTPSと所有権証明
この問題を解決するのがiOSのUniversal LinksとAndroidのApp Linksです。両者はhttps://example.com/product/42という通常のHTTPS URLをそのままディープリンクとして使います。ポイントは、そのドメインを本当に所有する開発者だけがリンクを受け取れるよう、OSがドメイン側に置かれた検証ファイルを取得して所有権を確認する点です。カスタムスキームがアプリ側の一方的な宣言だったのに対し、こちらはドメイン(サーバー)側の署名済み宣言とアプリ側の宣言を突き合わせる双方向の検証になっています。
| 観点 | カスタムスキーム | Universal Links / App Links |
|---|---|---|
| URL形式 | myapp:// など独自スキーム | https:// の通常URL |
| 所有権の検証 | なし(名前を登録するだけ) | ドメイン上の検証ファイルとアプリ側宣言を照合 |
| なりすまし | 同名登録で横取り可能 | ドメイン所有者しか受け取れず原理的に防止 |
| 未インストール時 | 解決できずエラー | 同じURLが普通にWebページとして開く |
| 主な用途 | レガシー・アプリ間連携の一部 | 外部からアプリへの正規の入口 |
副次的だが重要な利点として、未インストール時に同一URLがそのままWebページとして開くことが挙げられます。1本のHTTPS URLがアプリでもWebでも意味を持つため、リンク切れが起きず、Web側にフォールバックUIやインストール誘導を自然に置けます。
検証ファイルの実体
所有権証明の核心が、ドメインの決まったパスに配置する検証ファイルです。OSはアプリのインストール時(およびアプリ更新時)にこれを取得し、内容をアプリの識別子と照合します。
iOSはhttps://example.com/.well-known/apple-app-site-association(AASA、拡張子なし・Content-Type: application/json・リダイレクト不可)を取得します。中身は対象のApp IDと、そのアプリが扱うパスのパターンを列挙したJSONです。
{
"applinks": {
"details": [
{
"appIDs": ["TEAMID.com.example.app"],
"components": [
{ "/": "/product/*", "comment": "商品ページ" },
{ "/": "/account/*", "exclude": true }
]
}
]
}
}
Androidはhttps://example.com/.well-known/assetlinks.jsonを取得します。こちらはパッケージ名に加えて、アプリ署名証明書のSHA-256フィンガープリントを含める点が決定的で、署名鍵まで一致しないと検証が通りません。
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example.app",
"sha256_cert_fingerprints": ["AB:CD:EF:..."]
}
}]
アプリ側も対応する宣言が必要です。iOSはentitlementsのAssociated Domainsにapplinks:example.comを登録し、Androidはマニフェストのintent-filterにandroid:autoVerify="true"を付けます。サーバー側ファイルとアプリ側宣言の両方が揃って初めて検証が成立し、片方でも欠ければリンクはブラウザで開くだけになります。署名フィンガープリントの照合が絡むため、この仕組みは /mobile-development/mobile-app-signing-provisioning/ のコード署名基盤と地続きです。同じドメイン検証はApp ClipやInstant Appの起動経路でも使われ、/mobile-development/mobile-app-clip-instant-apps/ と共通の土台になっています。
リンクがアプリで開かない障害の大半は、実装ではなく検証ファイルの公開設定に起因します。AASAへのリダイレクト、誤ったContent-Type、CDNキャッシュで古いファイルが配られる、AndroidでPlay App Signingの再署名後フィンガープリントが実際の配布鍵と食い違う、といった点が典型です。iOSはAASA取得をApple運営のCDN経由で行うため、公開直後は反映に時間差が出ることも押さえておく必要があります。
遅延ディープリンク(Deferred Deep Linking)
ここで難問になるのが、アプリが未インストールの状態でリンクが押された場合です。理想は、ストアからインストールを完了して初回起動したときに、本来開くはずだった/product/42へ直接遷移させることです。これを遅延ディープリンクと呼びます。
問題は、ストアのインストールという行程がリンク情報を運ばないことです。ユーザーがWebでリンクを踏み、ストアへ飛び、アプリを入れて起動する間に、「どの画面を開きたかったか」という文脈はOSの標準機能では引き継がれません。そのため各種手法で橋渡しします。
- クリップボード方式: Web側で遷移先情報を一時的にクリップボードへ書き、初回起動時にアプリが読み取る。確実だが、OSがクリップボードアクセス時に通知を出すためプライバシー面の配慮が要る。
- 確率的マッチング(フィンガープリント): IPアドレス・端末機種・OSバージョン・画面サイズなどの組み合わせでクリック時と起動時を確率的に突き合わせる。identifierを使わないが精度が完全ではなく、誤マッチの可能性が残る。
- 決定的マッチング: iOSのApp Clipや一部のAPIのように、OS・ストアが公式に文脈を受け渡せる限定的な経路を使う。精度は高いが適用範囲が狭い。
インストール前のブラウザ上のセッションと、インストール後のアプリのプロセスは、OSのサンドボックス境界で完全に分離された別コンテキストです。両者を横断してユーザーを一意に紐づける公式かつ普遍的な手段は、プライバシー保護のため意図的に用意されていません。だからこそ、正確だが利用に制約のあるクリップボード方式か、制約は緩いが確率的で不正確な指紋照合か、というトレードオフを設計者が引き受けることになります。
アプリ内ルーティングへの受け渡し
検証を通ってリンクがアプリに届いた後は、URLを解析してアプリ内の画面遷移へ変換します。届き方はプラットフォームで異なります。iOSはインストール済みならNSUserActivity(continueUserActivity)としてUniversal Linksを受け取り、AndroidはUri付きのIntentとしてActivityに配送されます。届く経路はアプリの状態(起動中か、起動時か)で変わるため、両OSのライフサイクルコールバックを踏まえた設計が要ります(/mobile-development/ios-app-lifecycle-states/、/mobile-development/android-activity-lifecycle/)。
実装上の要点は、URLからルーティング先を決めるロジックを起動経路から独立させることです。「コールドスタートで届いたURL」「起動中に届いたURL」「アプリ内で生成した遷移」がすべて同じルーターを通る構造にすると、経路ごとの分岐が消えて堅牢になります。擬似コードで示すと次のようになります。
route(url):
path, params = parse(url) # /product/42 → ("product", {id:42})
if not authorized(path): # 認証が要る画面なら
save_pending(url) # URLを退避してログイン画面へ
go(login); return
screen = map(path) # パスを画面へ対応づけ
navigate(screen, params) # ナビゲーションスタックへ積む
ディープリンクのURLは外部から与えられる入力です。パスやパラメータを検証せずに画面遷移や処理へ渡すと、意図しない内部画面の露出、パラメータ改ざんによる他ユーザー資源へのアクセス、無限リダイレクトなどを招きます。ホワイトリスト方式で許可するパスと型を明示的に定義し、想定外は安全な既定画面へ落とす設計が必須です。
カスタムスキームは名前登録だけで横取り可能、Universal Links/App LinksはHTTPS URLとドメイン上の検証ファイルで所有権を証明しなりすましを防ぐ、が最重要の対比です。検証ファイルはiOSがapple-app-site-association、AndroidがassetlinksJSONで、後者は署名フィンガープリントまで照合します。遅延ディープリンクはOS標準では解決できずクリップボードや確率的マッチングに依存すること、届いたURLは必ず検証してからルーティングに渡すことも区別して覚えておく必要があります。
まとめ
ディープリンクの設計は、リンクを「誰が受け取ってよいか」をどう保証するかという一点に貫かれています。カスタムスキームはアプリの一方的宣言に依存するため横取りに弱く、Universal Links/App LinksはHTTPS URLとドメイン上の検証ファイル(apple-app-site-association/assetlinks.json)による双方向の所有権証明でなりすましを原理的に排除します。未インストール時の文脈を運ぶ遅延ディープリンクはサンドボックス境界ゆえに本質的に難しく、精度と正確性のトレードオフを設計で引き受けます。そして検証を通った後は、外部入力であるURLを必ず検証してから、起動経路に依存しない単一のルーターでアプリ内遷移へ変換することが、堅牢な実装の要になります。
モバイル開発の記事ガイド
ディープリンク(Universal Links/App Links)を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
ディープリンク
比較で見る軸
難易度: advanced / カテゴリ: モバイル開発 / タグ数: 6
導入後に効く点
検証はiOSがapple-app-site-association、AndroidがassetlinksJSONを対象ドメインの決まったパスから取得し、アプリのApp ID/署名フィンガープリントと突き合わせて成立する。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- モバイル開発
- タグ数
- 6
判断チェックリスト
- 自社の用途が「ディープリンク / Universal Links」に近いか確認する。
- 強みである「カスタムスキームは任意アプリが同名を登録でき横取りされる危険があるのに対し、Universal Links/App LinksはHTTPS URLとサーバー上の検証ファイルでドメイン所有権を証明し、なりすましを原理的に防ぐ。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。