はじめに
日本で Web サービスを提供するなら、LINE からのアクセスは無視できない。しかし LINE アプリ内ブラウザには厄介な問題がある。Google OAuth 認証が正常に動作しないことがあるのだ。
この問題に、2つのプロダクト開発で同時に遭遇した。同じ日に同じ問題を踏んだことで、汎用的な解決策を考えるきっかけになった。
問題の発見
2026年1月6日、Wakulier の開発日記にはこう書いた。
LINE内ブラウザ警告とOAuthエラーログの改善 LINEアプリ内ブラウザではGoogle OAuthが動作しないことがある。事前に警告を表示
同じ日、CancelNavi でも同様の対応をしていた。
アプリ内ブラウザでのログイン警告モーダルを追加 ユーザーが「ログインできない」と困惑するのを防ぎたい
LINE でサービスの URL をシェアすると、多くのユーザーは LINE アプリ内でそのままリンクを開く。そこで「Google でログイン」を押しても、認証フローが途中で止まったり、エラーになったりする。
ユーザーからすれば「なぜかログインできない」という体験になる。これは避けたい。
なぜ動かないのか
LINE 内ブラウザ(LINE IAB: In-App Browser)は、通常のブラウザとは異なる制約がある。
- サードパーティ Cookie の制限: OAuth のセッション管理に影響
- リダイレクト処理の違い: 認証後のコールバックが正しく処理されないことがある
- JavaScript API の制限: 一部の API が利用できない
Google OAuth に限らず、多くの OAuth 認証で同様の問題が発生する。
解決策: 事前警告 + 外部ブラウザ誘導
Claude Code と対処方針を検討し、「動かないものを動かす」のではなく、「動かない環境を避ける」アプローチを取った。
1. アプリ内ブラウザの検出
User-Agent に含まれる特徴的な文字列で検出する。
function isInAppBrowser(): boolean {
const ua = navigator.userAgent || navigator.vendor;
// LINE, Facebook, Instagram などの主要アプリ内ブラウザを検出
const inAppPatterns = [
/Line/i, // LINE
/FBAN/i, // Facebook
/FBAV/i, // Facebook
/Instagram/i, // Instagram
];
return inAppPatterns.some(pattern => pattern.test(ua));
}
開発日記には「完璧な検出は難しいが、主要なアプリはカバー」と書いた。100% の精度は不要で、主要なケースをカバーできれば十分だ。
2. 警告バナーの表示(ランディングページ)
アプリ内ブラウザを検出したら、ページ上部に警告バナーを表示する。
{isInAppBrowser && (
<div className="bg-yellow-500/10 border border-yellow-500/30 rounded-lg p-4">
<p className="text-yellow-400 text-sm">
LINE アプリ内で開いています。
ログインには Safari や Chrome などの外部ブラウザをご利用ください。
</p>
<button onClick={openInExternalBrowser}>
外部ブラウザで開く
</button>
</div>
)}
3. 外部ブラウザ誘導モーダル(ログイン画面)
ログインボタンを押す前に、外部ブラウザで開くよう促すモーダルを表示する。
開発日記には UX の試行錯誤が記録されていた。
「ログインボタンを押す前」に警告するか、「押した後」に警告するか 最初はログインボタン押下後に表示していたが、クリック前に表示する方がスムーズと判断
押した後に警告すると、「なぜ動かないんだ」というフラストレーションが先に来る。事前に案内する方がユーザー体験として良い。
4. 外部ブラウザで開く
iOS と Android で挙動が異なるため、プラットフォームに応じた対応が必要になる。
function openInExternalBrowser(url: string) {
// iOS Safari で開く
if (/iPhone|iPad|iPod/.test(navigator.userAgent)) {
// x-safari-https:// スキームは廃止されているため
// URL をコピーして手動で開くよう案内するのが確実
copyToClipboard(url);
showToast("URL をコピーしました。Safari で開いてください。");
return;
}
// Android は intent:// スキームで外部ブラウザを開ける場合がある
// ただし LINE の仕様変更で動作しないケースもある
window.location.href = url;
}
完璧な自動遷移は難しい。Claude Code で複数パターンを試した結果、「URL をコピーして、Safari/Chrome で開いてください」という案内が最も確実だった。
学んだこと
1. アプリ内ブラウザは「敵」ではない
LINE からのアクセスを敵視するのではなく、その環境での最適な体験を提供する姿勢が大切だ。
2. User-Agent 検出は「完璧」ではないが「実用的」
開発日記にも書いたが、100% の精度は不要。主要なケースをカバーできれば、大多数のユーザーを救える。
3. 事前告知が最善
問題が起きてから対処するより、問題が起きる前に案内する方がユーザー体験として優れている。
まとめ
LINE 内ブラウザで OAuth が動かない問題は、日本の Web サービス開発では避けて通れない。
対処の基本方針は以下の通り。
- User-Agent で検出: 主要なアプリ内ブラウザをカバー
- 事前に警告: ログイン前に外部ブラウザ誘導
- URL コピー機能: 確実に外部ブラウザで開けるよう案内
「動かないものを無理に動かす」のではなく、「動く環境に誘導する」というアプローチが現実的だ。
関連記事
Zeronova(ゼロノバ)
Product Manager / AI-Native Builder
Web/IT業界19年以上・20以上のWebサービスを担当したPdM。東証プライム上場企業の子会社代表として事業経営を経験。現在はAIを駆使して企画から実装まで完結させる個人開発を実践中。