導入:ブラウザではログインできるのに、WebViewだと失敗する
SNSログイン(Google / X / Facebook / LINE など)をアプリ内でやりたい。
で、WebViewでログイン画面を開く。
……すると、こうなります。
- ブラウザでは成功するのにWebViewだと弾かれる
- ログイン後に真っ白、または無限リダイレクト
- 「このブラウザはサポートされていません」的な表示
- 途中でCookieが消えて最初に戻る
これ、WebViewでSNSログインをやる限り、かなりの確率で踏みます。
結論から言うと、原因はだいたい Cookie / UA / リダイレクト のどれか、もしくは複合です。
この記事では、WebViewでSNSログインが失敗する原因を「切り分け順」でまとめます。
闇雲に設定を盛ると余計壊れるので、順番が大事です。
先に結論(3行)です。
- まずCookie(特にサードパーティCookieとSameSite)を疑う
- 次にUA(アプリ内ブラウザ判定で弾かれる系)を疑う
- 最後にリダイレクト(shouldOverrideUrlLoading/フラグメント/intent起動)を疑う
前提:SNSログインは「WebView前提じゃない」ことが多い
まず厳しめの現実から。
SNSログインは、多くの場合「ブラウザ(システムブラウザ)での実行」を前提に作られています。
WebViewは自由度が高い反面、セキュリティ制約やCookie制約が強く、提供側が明示的に非サポートにしているケースもあります。
つまり、WebViewで通らない時に「アプリ側で何とかすれば必ず通る」とは限りません。
それでも、実務ではどうしてもWebViewでやらざるを得ないケースがあるので、現実的な対策を詰めていきます。
切り分けの最短ルート:まず「失敗のタイプ」を決める
原因特定のスピードが上がるので、最初に症状を分類します。
タイプA:ログイン後に元の画面に戻れない(真っ白/無限ループ)
リダイレクト処理かCookieが濃厚です。
タイプB:ログイン画面が最初から弾かれる(非対応ブラウザ/セキュリティ警告)
UAやWebView判定(アプリ内ブラウザ拒否)が濃厚です。
タイプC:途中まで進むが、認可画面や同意画面で失敗する
Cookie(SameSiteやサードパーティ)か、リダイレクト途中のintent処理が濃厚です。
原因1:Cookie(9割ここ)
WebViewでSNSログインが失敗する最大原因はCookieです。
1-1. サードパーティCookieがブロックされている
SNSログインはドメインをまたいだ遷移が多く、サードパーティCookieが絡みやすいです。
WebView側でサードパーティCookieが無効だと、認証セッションが維持できずに詰みます。
チェック:サードパーティCookieを許可しているか
val cm = CookieManager.getInstance()
cm.setAcceptCookie(true)
cm.setAcceptThirdPartyCookies(webView, true)
ただし、何でも許可すれば良いわけではありません。
許可するなら「ログイン画面で必要な範囲に限定」し、ログイン後に戻すなど、運用設計が必要です。
1-2. SameSite の影響でCookieが送られない
最近はSameSite制約が強く、クロスサイト遷移でCookieが送られないケースがあります。
ブラウザではうまくいくのにWebViewではダメ、が起きる代表例です。
この場合、アプリ側で出来ることは限られます。
Web側(認証側)がSameSite=None; Secure を適切に設定していないと、根本的に詰む可能性があります。
1-3. Cookieが「保存されていない」または「突然消える」
WebViewのプロセスが落ちたり、アプリ側でCookieをクリアしたりすると、途中でセッションが消えます。
チェックポイント
- ログイン開始前に CookieManager.removeAllCookies を呼んでいないか
- WebViewを画面回転で作り直していないか
- プロセスキル後の復元でWebViewが再生成されていないか
Cookieを明示的にflushする(必要な場面のみ)
CookieManager.getInstance().flush()
「ログイン直後に戻りURLへ飛ぶ直前」など、タイミングが重要な場面で効くことがあります。
ただし多用は避けます。
1-4. カスタムタブ/外部ブラウザとCookieが共有されない
WebViewとChrome(Custom Tabs含む)はCookieジャーが別の場合があります。
「外部ブラウザでログイン済みなのにWebViewだけ未ログイン」は、ここが原因のことが多いです。
これをアプリ側で完全に合わせるのは難しく、設計として「ログインはWebViewではなくCustom Tabsに寄せる」方が現実的な場合もあります。
原因2:User-Agent(UA)で弾かれる
SNSログインは「この環境は安全か」を見ています。
WebViewはUAや環境情報で「アプリ内ブラウザ」と判定され、弾かれることがあります。
2-1. WebView判定で「サポート外」になる
典型は「このブラウザはサポートされていません」系です。
Web側がWebViewを拒否している可能性があります。
2-2. UAをカスタムして壊している
UAを上書きしていると、予期せぬ判定に引っかかります。
特に「デフォルトUAを捨てて独自UAだけにする」は危険です。
正しいUAカスタムの基本:末尾に追加
val defaultUa = webView.settings.userAgentString
webView.settings.userAgentString = "$defaultUa MyApp/${BuildConfig.VERSION_NAME}"デフォルトUAを残すと、ブラウザ判定が壊れにくいです。
2-3. UA変更のタイミングが遅い
UAは loadUrl の前に設定しないと、最初のリクエストに反映されません。
ログインで最初のリクエストが重要なので、ここで詰みます。
原因3:リダイレクト(shouldOverrideUrlLoading/intent/フラグメント)
ログインが通っているのに「戻れない」「真っ白」は、だいたいリダイレクト処理が壊れています。
3-1. shouldOverrideUrlLoading で握りつぶしている
ありがちなのが、全URLを自前で処理しようとして false/true の返し方を間違えるパターンです。
基本方針
- WebViewに表示させたい遷移は WebView に任せる(基本 false)
- アプリで処理したいURLだけ拾う(特定スキームや特定host)
例:アプリに戻るURLだけ拾う
webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(
view: WebView,
request: WebResourceRequest
): Boolean {
val url = request.url.toString()
// 例:myapp://callback を拾う
if (url.startsWith("myapp://callback")) {
// アプリ側で処理
handleCallback(url)
return true // WebViewには任せない
}
return false // WebViewに任せる
}
}3-2. フラグメント(#)以降に重要情報がある
OAuth系は、#(フラグメント)にトークンや情報が乗る場合があります。
HTTPリクエストではサーバに送られないので、アプリ側でURLを正しく扱わないと情報が取れません。
WebViewでフラグメントが消える/変なエンコードになると、ログイン後の処理が破綻します。
3-3. intent:// や market:// が混ざる
ログイン途中で別アプリ起動(認証アプリ、パスワードマネージャなど)が挟まる場合があります。
WebViewでこれを処理できずに詰むことがあります。
この場合は、intentスキームを検知して外部に逃がす設計が必要です。
追加で疑うべき原因(実務で多い)
4) TLS/SSLハンドシェイク失敗
特定端末や古いWebViewでTLSが合わず、ログイン先に到達できないケースがあります。
Logcatに SSLHandshakeException が出ているならここです。
5) WebViewのデバッグ不足(何が起きているか見えてない)
WebViewはログが見えづらいので、通信・Cookie・リダイレクトを可視化した方が早いです。
- Chrome DevTools(WebViewのリモートデバッグ)
- Proxyツールで通信を見る(HTTPS復号)
- User-Agent、Cookieの差分を記録する
最短で直すための「切り分け手順」
- ブラウザでは成功するか(Web側の問題切り分け)
- WebViewのCookie許可(特にサードパーティ)を確認
- UAをデフォルト+末尾追加に戻す
- shouldOverrideUrlLoading を「拾うURLだけ拾う」に修正
- フラグメント/intentスキームが混ざっていないか確認
この順番でやると、最短で原因に刺さりやすいです。
デバッグ/確認チェックリスト
- サードパーティCookieを必要な範囲で許可している
- Cookieが途中で消えていない(clear/再生成/プロセスキル)
- UAはデフォルトを残して末尾追加
- UA設定はloadUrl前
- shouldOverrideUrlLoadingは特定URLだけ拾う
- フラグメントやintentスキームの扱いを確認
- 通信可視化(DevTools/Proxy)を使っている
よくある質問(Q&A)
Q. どうしてもWebViewでSNSログインしたい
可能なこともありますが、提供側が非サポートの場合は詰む可能性があります。
その場合は、ログインだけCustom Tabsに寄せる設計を検討した方が安全です。
Q. Cookieを全部許可すれば解決する?
一時的に通ることはありますが、セキュリティと整合性のリスクが上がります。
必要な範囲で許可し、ログイン後に戻す、など運用設計が必要です。
Q. UAをChromeっぽく偽装すれば通る?
通ることもありますが、提供側の規約や仕様に触れる可能性があります。
まずは「デフォルトUAを壊していないか」を疑うのが安全です。
まとめ:原因はだいたいCookie/UA/リダイレクト
- WebViewログイン失敗の最大原因はCookie(サードパーティ/SameSite)
- 次にUA(WebView拒否/カスタムで壊す)
- 最後にリダイレクト処理(shouldOverrideUrlLoading/intent/フラグメント)
迷ったら:Cookieを見て、UAを戻して、拾うURLだけ拾う。
この3点で、だいたい前に進みます。