LINEヤフー Tech Blog

LINEヤフー株式会社のサービスを支える、技術・開発文化を発信しています。

ヤフーのAndroidアプリにおけるパスキー対応(4つの方法と採用判断)

はじめまして。LINEヤフー株式会社の石井です。
ヤフーのAndroidアプリにログイン機能を提供する社内向けのSDKの開発を担当しています。

近年、ログインの簡単さやセキュリティなどの観点でパスキーが注目されています。
ヤフーのAndroidアプリでもパスキーを使ったログイン機能をご利用いただけますが、その実装を担っているのは、ログイン関連の機能全般を提供するID連携SDKです。

Androidアプリでパスキーに対応する方法はいくつかあります。
ID連携SDKでは、過去のバージョンとの互換性やユーザー体験を考慮し、現時点では WebView上のWebAuthn APIリクエストをフックし、パスキー周りをネイティブ実装する方法 を採用しています。
この記事では、その判断に至るまでの変遷を振り返りながら、Androidアプリでのパスキー対応における選択肢と採用判断のポイントをご紹介します。

※ここでのID連携SDKとは、Yahoo!デベロッパーネットワークで公開しているYahoo! ID連携 v2 Android SDKとは別のものです。
※FIDO認証には公開鍵を管理し認証を検証するFIDOサーバーが必要ですが、この記事ではそれらが用意されている前提のもと、Androidアプリ側での実装に焦点を当てています。

パスキーとは

2026年4月時点で、FIDO Alliance: Passkeys (Passkey Authentication)のQ&Aにある「WHAT IS PASSKEY?」では以下のように説明されています。

From a technical standpoint, passkeys are FIDO credentials for passwordless authentication.

FIDO Allianceの定義では、パスキーは技術的にはFIDOクレデンシャルであると位置づけられています。

FIDOクレデンシャルには、大きく Discoverable credentialNon-discoverable credential の2種類があります。
詳細な説明は省きますが、Discoverable credentialはユーザー識別子を含むもの、Non-discoverable credentialはユーザー識別子を含まないものです。
また、Discoverable credentialのうち、デバイス間で同期できるものは 同期パスキー と呼ばれます。

本記事では、以降も必要に応じてこれらの用語を使います。

Androidでのパスキー対応の方法

2026年4月時点で、Androidアプリでパスキーによる認証を実現する方法は大きく4つあります。

方法説明アプリ側の技術的難易度
カスタムタブカスタムタブを使ったWebAuthnによる認証
WebView + WebKitのWebAuthnサポート利用AndroidX WebKit 1.12.0で追加されたWebAuthnサポート機能を使ったWebAuthnによる認証
WebView + パスキー周りをネイティブ実装WebAuthnリクエストをネイティブにブリッジし、パスキーの登録・認証をアプリ側独自のネイティブ実装で処理する方法中〜高
ネイティブ実装ログイン画面、パスキーの登録・認証をすべてネイティブで実装中〜高

冒頭で言及したように、ヤフーのAndroidアプリ(ID連携SDK)では、現状 「WebView + パスキー周りをネイティブ実装」 を採用しています。
ここからは、その方法を選んだ背景を時系列で振り返ります。

ヤフーのAndroidアプリ(ID連携SDK)のパスキー対応

2020年10月:FIDO認証を使った再認証機能を追加

この時はまだ「パスキー」という用語は存在しておらず、Non-discoverable credentialによるFIDO認証機能が提供できるという状況でした。

ID連携SDKではログイン機能はOAuthベースで実現しているため、カスタムタブかWebViewを使い、WebAuthnによってFIDO認証を実現できることが理想でした。
しかし、それには以下のような課題がありました。

  • カスタムタブの場合、アプリでログイン中のIDとカスタムタブ(ブラウザアプリ)でログイン中のIDが異なっていた場合に、再認証時にログイン中のIDが意図せず変わってしまう
  • WebViewの場合、当時はWebKitなどによるWebAuthnサポートはなく、それ以外の対応方法の情報も少なく、実装難易度が高かった

そのため、FIDO2 APIを使いネイティブ実装でFIDOクレデンシャルの作成や認証機能を提供する形になりました。
ログイン機能をOAuthベースで実現しているという事情もあり、初回ログイン時のFIDO認証はセキュリティや工数の都合で断念し、再認証時のみFIDO認証を行う仕様としました。
この時点では、OAuthベースの構成とWebViewの制約を踏まえると、ネイティブ実装が現実的な選択肢でした。

2024年3月:同期パスキーに対応

この頃にはすでにパスキーが広がりはじめ、Android上でもCredential Manager APIにより、扱いやすくなっていました。

前述の通り、ID連携SDKではNon-discoverable credentialを作成し登録している状況でした。
つまり、機種変更をするとそのFIDOクレデンシャルは利用できなくなり、新しい端末で再度登録しなければなりません。
一方で、同期パスキーであれば、Googleパスワードマネージャーなどの認証情報プロバイダーを介して複数端末で同期されるため、機種変更したとしても登録済みのFIDOクレデンシャルを引き継ぐことができます。

そうしたユーザー体験の向上を目的に、Googleが推奨するCredential Manager APIを使って同期パスキーに対応することにしました。
ただ、対応に際しては以下の課題がありました。

  • Credential Manager APIでパスキーが使えるのはAndroid 9(APIレベル28)以降
  • Credential Manager APIではNon-discoverable credentialを使って認証ができない

2つ目の課題はつまり、認証処理をCredential Manager APIに完全に置き換えてしまうと、それまでFIDO認証を利用していたユーザーが、アップデート後にFIDO認証できなくなり、再度FIDOクレデンシャルの登録が必要になってしまうということです。

これらの課題に対してはFIDO2 APIとCredential Manager APIを使い分けることで対応しました。
後続の章では、この使い分けに関するポイントをご紹介します。

2025年3月:初回ログイン時のパスキー認証機能を追加

より安全性の高い認証の需要が高まるにつれ、Yahoo! JAPAN IDとしても初回ログイン時にパスキーを使った認証を使えるようにする必要性が出てきました。

この頃には、WebViewでWebAuthnを実現する場合、「WebView + パスキー周りをネイティブ実装」する方法が公式に案内されていました。

具体的なフローは後続の章で説明しますが、Webからのパスキー作成・認証のリクエストを受け取り、ネイティブ実装でFIDO2 APIとCredential Manager APIを使いFIDOクレデンシャルの作成や取得を行うことで実現しました。

2026年2月:WebKitのWebAuthnサポートに移行を試みるが…

現在では、WebViewでWebAuthn認証を実現する方法として、WebKitのWebAuthnサポートを利用する方法が公式に案内されています。
単純なパスキーの作成・認証であれば、アプリ側の実装はほとんど不要になっています。
ID連携SDKでもパスキー関連の煩雑なネイティブ実装を削除すべく、リファクタリングを試みました。
しかし、Android 14以上の端末での挙動にいくつか課題があり、現時点での対応は見送りました。
具体的にどのような課題があったかを後続の章でご紹介します。

パスキー対応 それぞれの方法のポイント

ここから、それぞれの方法の特徴と採用判断のポイントを見ていきます。

カスタムタブ

OAuthベースでログインを実装しており、ログイン画面をカスタムタブで表示している場合は、この方法が最もシンプルです。
Web側でWebAuthnに対応すればよく、他の方法で必要になるデジタルアセットリンクの設置や設定も不要です。

ただし、(パスキーでの認証に限った話ではないですが)アプリでログイン中のIDとカスタムタブ(ブラウザアプリ)でログイン中のIDが異なっていた場合に再認証時にIDが変わる可能性があるため、このリスクを許容できるか、あるいは何らかの方法で対策を行えることが、採用の条件になってくるかと思います。
ID連携SDKではこの部分がネックとなり採用には至りませんでした。

WebView + WebKitのWebAuthnサポート利用

OAuthベースでログインを実装しており、ログイン画面をWebViewで表示している場合は、この方法が有力です。
アプリ側の実装を大きく増やさずに対応できるのがメリットです。

やることは、

  1. デジタルアセットリンクを設置・設定する
  2. ライブラリの依存関係を追加する
  3. ログイン画面を表示するWebViewでWebAuthnサポートの設定を有効にする

これだけです。
具体的な実装方法はAndroid Developersの案内をご覧ください。

しかし、前述の通り、ID連携SDKではAndroid 14以上の端末での挙動に課題を感じ、この方法への移行は見送りました。
特に懸念を感じたのは以下の3点です。

Android 14以上では、パスキー未検出時のフィードバックがわかりづらい

パスキーが見つからなかった場合のユーザーフィードバックは、以下のような表示になります。

既存のID連携SDKやChromeWebKitのWebAuthnサポート利用時
既存のID連携SDKやChromeのエラー画面WebKitのWebAuthnサ��ポート利用時のエラー画面

既存のID連携SDKやChromeでは、全面に「パスキーがありません」という情報が表示され、ユーザー操作が必要な状態になっていることがわかりやすくなっています。
一方で、WebKitのWebAuthnサポートの場合は、「別の方法でログイン」というトースト表示が出るのみで、それ以外の画面も暗くならないため、処理が中断したことがわかりづらく、ユーザー操作が必要なことが伝わりづらくなっています。

そもそも、パスキーが見つからなければ、自動で他の認証手段へフォールバックできた方が体験としては良いですが、WebKitのWebAuthnサポートを使う場合、Credential Manager API周りの実装がWebKitに内包されており、現時点では、この挙動をアプリ側で制御する手段がないため、そのまま受け入れる必要があります。

Android 14以上では、優先サービス設定が「なし」だとFIDO認証できない

Android 14から端末の設定に「パスワード、パスキーと自動入力で優先的に使用するサービス」という設定項目が追加されています。

パスワード、パスキーと自動入力で優先的に使用するサービス
※Android 15の場合「設定」>「パスワード、パスキー、アカウント」>「優先するサービス」>「変更」

この設定が「なし」になっていると、パスキーを見つけられずエラーになりました。
Credential Manager APIは、Android 14以上ではフレームワークレベルで実装がされています。
その環境下ではこの設定とCredential Manager APIが密に紐づいており、設定が「なし」の状態で、CredentialManager.getCredentialを呼び出すとNoCredentialExceptionがスローされます。
一方で、FIDO2 APIでは設定が「なし」になっていても、パスキーを見つけることができます。

ID連携SDKの既存実装では、Credential Manager APIでNoCredentialExceptionが発生した場合には、FIDO2 APIにフォールバックしているため、FIDO認証に成功します。
Chromeも、同様の手法かどうかは不明ですが、FIDO認証に成功します。

意図的に変更しない限り「なし」になることはないはずなので、影響を受けるユーザーは少ないかもしれませんが、ID連携SDKの既存の実装やChromeではできていることができなくなるため、受け入れにくい挙動でした。

Android 14以上では、Non-discoverable credentialを扱えない

FIDOクレデンシャルがNon-discoverable credentialの場合、FIDO2 APIでないと認証ができません。
原因としては前述の問題と同様で、WebKitのWebAuthnサポートが、FIDO2 APIへのフォールバックをサポートしていないことによるものと考えられます。
FIDO2 APIへのフォールバックを実装している既存のID連携SDKではFIDO認証に成功します。
ChromeでもFIDO認証に成功します。

ID連携SDKでは、過去にNon-discoverable credentialを生成していた時期があり、影響を受けるユーザーが一定数いると考えられます。
そのため、ID連携SDKの既存実装やChromeでできていることができなくなる点は、互換性の観点から問題があると判断しました。

まとめると、Android 14以上の端末での

  • パスキーが見つからない場合のユーザーフィードバックが許容できる
  • パスキーの優先サービス設定がなしになっている場合に認証できないことを許容できる
  • Non-discoverable credentialを考慮する必要がない

以上、3点を満たせるのであればこの方法が良いでしょう。
※WebKitやCredential Manager APIの今後のバージョンアップによって、変わる可能性もあります。

WebView + パスキー周りの処理をネイティブ実装

WebKitのWebAuthnサポートに含まれている実装を、自前で行うのがこの方法になります。
WebKitでサポートされる前は、この方法がAndroid Developersで紹介されていました。
パスキー周りの処理を、サービス要件に合わせて柔軟に調整できるのがこの方法のメリットです。
たとえば、Credential Manager APIとFIDO2 APIの使い分け、認証失敗時のフォールバック、UIの制御などをアプリ側で細かく設計できます。
一方で実装コストは高いため、WebKitのサポートで要件を満たせるなら、そちらを選ぶほうが現実的です。

基本的なフローは以下のとおりです。

  1. WebViewにJavaScriptを挿入し、WebAuthn APIの呼び出しをフックする
    • PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
    • navigator.credentials.create()
    • navigator.credentials.get()
  2. フックしたメソッドが呼ばれたらネイティブ側にメッセージを送る
  3. ネイティブでメッセージを受け取り、Credential Manager APIやFIDO2 APIを使って対応する処理を行う
  4. 結果をWebに送り返す

フローの1でどのようなJavaScriptを挿入すれば良いかや、2・4のメッセージの送受信の実装方法は、Googleが公開しているサンプルコードが参考になります。

ネイティブ実装でのポイント

新規にパスキー対応を導入するケースであれば、Credential Manager APIだけで十分な場合がほとんどです。
しかし、Android 9未満でFIDO認証をサポートする場合や、Non-discoverable credentialを考慮する必要がある場合、Credential Manager APIとFIDO2 APIを使い分ける必要があります。

Credential Manager APIとFIDO2 APIの使い分け

Credential Manager APIとFIDO2 APIには以下のような違いがあります。

Credential Manager APIFIDO2 API
サポートされているFIDOクレデンシャルDiscoverable credentialNon-discoverable credential, Discoverable credential
サードパーティ製パスワードマネージャーの利用可否Android 14以上から可不可
サポートOSバージョンAndroid 9以上Android 7以上

これらを踏まえ、例えば、これまでにAndroidユーザーにNon-discoverable credentialを作成させていて、引き続きそのクレデンシャルでの認証をサポートしたいというような場合には、以下の使い分けが良いと思います。

OSバージョンFIDOクレデンシャル作成FIDOクレデンシャルを使った認証
Android 9未満FIDO2 APIFIDO2 API
Android 9〜13Credential Manager APIFIDO2 API
Android 14以上Credential Manager APICredential Manager API + FIDO2 API

特に重要なのは、Android 9以上における認証時の使い分けです。

Android 14以上での認証時はCredential Manager APIで試してパスキーが見つからなければFIDO2 APIにフォールバックする

GetCredentialRequestのオプションにpreferImmediatelyAvailableCredentialsというものがあり、これをtrueにするとCredential Manager APIでパスキーが見つからなくてもユーザーフィードバックは行われません。
これを利用し、Credential Manager APIでパスキーが見つかればそのまま認証、NoCredentialExceptionが発生したらFIDO2 APIにフォールバックする、という流れにすることで、FIDOクレデンシャルがNon-discoverable credential、Discoverable credentialのどちらであっても、さらにはGoogleパスワードマネージャーとサードパーティ製パスワードマネージャーのどちらで管理されていたとしても、シームレスに認証を実現できます。

val credentialManager = CredentialManager.create(context)  
val getRequest = GetCredentialRequest(  
    credentialOptions = listOf(  
        GetPublicKeyCredentialOption(requestJson),  
    ),  
    preferImmediatelyAvailableCredentials = true,  
)  
try {
    val getResponse = credentialManager.getCredential(context, getRequest)
    val publicKeyCredential = getResponse.credential as PublicKeyCredential  
    return publicKeyCredential.authenticationResponseJson  
} catch (e: GetCredentialException) {  
    if (e !is NoCredentialException) {  
        throw e
    }  
    return getWithFido2Api(requestJson) // FIDO2 APIを使った認証処理
}
Android 14未満での認証時はFIDO2 APIを使う

Android 14未満ではpreferImmediatelyAvailableCredentialstrueを指定してもユーザーフィードバックが表示されてしまいます。

preferImmediatelyAvailableCredentialsがtrueのときのAndroid 13でのユーザーフィードバック

そのため、Credential Manager APIからのフォールバックではなく、最初からFIDO2 APIで認証を行う必要があります。
Android 13以下ではサードパーティ製のパスキーは利用できないため、FIDO2 APIによる認証で十分といえます。

ネイティブ実装

ログイン機能をネイティブUIで実装している場合は、この方法が基本になります。
実装のポイントは「WebView + パスキー周りの処理をネイティブ実装」のネイティブ実装部分のポイントと変わりません。

4つの方法の選び分け

方法判断ポイント
カスタムタブ・OAuthベースでカスタムタブを使いログイン機能を実装している
・アプリとブラウザでログイン中のIDが異なる場合の影響が軽微
WebView + WebKitのWebAuthnサポート利用・OAuthベースでWebViewを使いログイン機能を実装している
・パスキーが見つからない場合のユーザーフィードバックを許容できる
・優先サービス設定が「なし」の場合の挙動を許容できる
・Non-discoverable credentialを考慮する必要がない

※上記挙動はWebKit 1.15.0、CredentialManager 1.5.0で確認したもので、バージョンにより変わる可能性があります
WebView + パスキー周りをネイティブ実装・OAuthベースでWebViewを使いログイン機能を実装している
・WebKitのWebAuthnサポートだと要件を満たせない
ネイティブ実装・ネイティブでログイン機能を実装している
・パスキー認証体験を細かく制御したい

動作確認のポイント

Androidでのパスキー利用可否は、OSバージョンだけでなく、端末設定や認証情報プロバイダーの状態にも影響を受けます。
そのため、どの方法を採用する場合でも、十分な動作確認が重要です。

OSバージョンごとのパスキー周りの変化のポイントと、それに伴い動作確認で確認すべき観点をまとめました。

対象OSポイント確認すべき観点
Android 9未満Credential Manager APIが使えない・Non-discoverable credentialの作成・認証ができるか
 ※Discoverable credentialは作れない
Android 9〜13Credential Manager APIがGoogle Play開発者サービスに依存・端末へのGoogleアカウントでのログイン状況(Googleパスワードマネージャーの利用可否)による挙動の違い
・Google Play開発者サービスのストレージ関連の権限の許可状況による挙動の違い
・Non-discoverable credentialのサポートが必要な場合、Discoverable/Non-discoverableそれぞれでの認証可否
Android 14以上フレームワークレベルでのCredential Manager APIサポート・端末へのGoogleアカウントでのログイン状況(Googleパスワードマネージャーの利用可否)による挙動の違い
・サードパーティ製パスワードマネージャーの利用可否
・パスキー優先保存サービスの設定状況による挙動の違い
・Non-discoverable credentialのサポートが必要な場合、Discoverable/Non-discoverableそれぞれでの認証可否
バージョン問わず画面ロック・設定有無による挙動の違い

おわりに

本記事では、ID連携SDKでのパスキー対応の経験をもとに、Androidアプリにおける4つの実装方法と、その採用判断のポイントをご紹介しました。
特に、既存のFIDO認証資産があり、Non-discoverable credentialとの互換性を考慮する必要があるケースでは、単純に新しい仕組みに置き換えるだけでは解決できない場面があります。

本記事が、Androidアプリでのパスキー導入や見直しを検討する際の参考になれば幸いです。