Capacitor アプリに認証機能を追加するには、認証元(自社バックエンド、Firebase・Supabase・Neon などのホスト型サービス、Auth0・Okta・Entra ID などの OIDC プロバイダー、または Better Auth のようなセルフホスト型ライブラリ)を選択します。プロバイダーのログインページを開く処理にはネイティブプラグインを使用し、サーバー側でトークンを検証した上で、得られたセッションを Keychain または Keystore に保存します。生体認証とパスキーを使えば、次回のサインインをすばやく行えます。
このガイドでは、一般的な選択肢ごとに適切な Capacitor プラグインとフローを対応付けています。ログイン呼び出し、トークン検証、セッション保存、生体認証によるロック解除など、どのアプリでも共通する部分は code でカバーしています。2026 年 10 月時点で Capacitor 8 に対応しています。各プロバイダーのステップバイステップガイドは以下にリンクしています。
Capacitor アプリが最終的に辿り着く認証フロー
どのプロバイダーを選んでも、流れは同じです:
- ユーザーを特定 :ネイティブのソーシャルシート、システムブラウザでのプロバイダーのログインページ、パスキーのプロンプト、またはメールとパスワードを送信するフォーム。
- 証明を取得:IDトークン、認可 code、または認証サーバーからのセッショントークン。
- サーバーで検証:署名、発行者、オーディエンス、有効期限を確認し、ユーザーを作成または検索します。
- セッションを発行:独自のトークンまたはプロバイダーのトークンを、リフレッシュ戦略とともに。
- 安全に保存 :デバイス内に保存し、API の呼び出しに付与します。
- すばやくロック解除 次回は生体認証ですばやくロック解除し、ログアウトとアカウント削除にも対応しましょう。
ステップ1と2はプロバイダーによって変わります。ステップ3〜6は、SDK が大部分を処理するフルホスト型 BaaS を除き、どのオプションでも自分で実装する必要があります。
WebViewのログインページが動かない理由
Capacitor アプリは、ローカルオリジンを持つ WKWebView (iOS) または Android WebView 内で Web code を実行します(capacitor://localhost または https://localhost)。その WebView 内でプロバイダーのログインページを読み込むと、3つの問題が発生します:
- Google が
disallowed_useragentを返し、ページの表示を拒否します。 - アプリ側でそのページが本物のプロバイダーだと証明できないため、RFC 8252 はネイティブアプリにシステムブラウザの使用を求めています。
- フルページリダイレクトが発生すると、バンドルされたアプリから離れてしまい、state が失われます。
そのため、以下のすべてのフローでは、ネイティブの SDK (Apple, Google, Facebook) か、システムブラウザのセッションを使用します(ASWebAuthenticationSession iOSではSFSafariViewController、AndroidではChrome Custom Tabs)を使用し、カスタムスキーム経由でアプリに戻ります。
選択肢のまとめ
| アプローチ | 最適な用途 | Capacitor プラグイン | バックエンドの実装 | ガイド |
|---|---|---|---|---|
| Appleでサインイン | サードパーティログインを導入したiOSアプリ | @capgo/capacitor-social-login |
IDトークンの検証 | Appleのガイド |
| Google Sign-In | コンシューマーアプリ、Android優先 | @capgo/capacitor-social-login |
IDトークンの検証 | Googleガイド |
| Auth0 | 多数の接続に対応したホスト型ログイン | @capgo/capacitor-social-login (OAuth2) |
アクセストークンの検証 | Auth0 ガイド |
| Okta | ワークフォースおよびB2B SSO | @capgo/capacitor-social-login (OAuth2) |
アクセストークンの検証 | Okta ガイド |
| Microsoft Entra ID | Microsoft 365 組織 | @capgo/capacitor-social-login (OAuth2) |
アクセストークンの検証、Graph | Entra ID ガイド |
| より優れた認証 | セルフホスト、独自のユーザーDB | better-auth クライアント + Social Login |
Better Auth サーバーの実行 | Better Auth ガイド |
| Supabase Auth | 組み込み認証付き Postgres バックエンド | Social Login + supabase-js |
最小限 | Supabase ガイド |
| Neon Auth | マネージド Better Auth 対応の Neon Postgres | @capgo/capacitor-neon |
最小限 | Neon プラグインのドキュメント |
| Firebase Authentication | すでに Firebase を使用しているアプリ | @capgo/capacitor-firebase-authentication |
最小限 | Firebase のドキュメント |
| パスキー | 独自ドメインでのパスワードレスログイン | @capgo/capacitor-passkey |
WebAuthn サーバー | Passkey ドキュメント |
| メールアドレスとパスワード | シンプルなアプリ、独自のバックエンド | なし (HTTP) | ハッシュ化、リセット、レート制限 | この記事 |
ネイティブのソーシャルログイン (Apple, Google, Facebook)
1つのプラグインで、主要な3つのコンシューマープロバイダーと汎用 OAuth2 エンジンをカバーしています:
bun add @capgo/capacitor-social-login
bunx cap sync
import { SocialLogin } from '@capgo/capacitor-social-login';
await SocialLogin.initialize({
apple: { clientId: 'com.example.app' },
google: {
webClientId: 'WEB_CLIENT_ID.apps.googleusercontent.com',
iOSClientId: 'IOS_CLIENT_ID.apps.googleusercontent.com',
},
});
const { result } = await SocialLogin.login({ provider: 'google', options: {} });
// send result.idToken to your server
使用しないプロバイダーをオフにするには capacitor.config.ts (plugins.SocialLogin.providers) これにより、SDKがアプリにコンパイルされるのを防げます。また、Facebookを使用しない場合は、Facebook SDK の広告ID権限も削除されます。
各プロバイダーにはネイティブの設定が必要です。AppleはXcodeでのCapabilityとServices ID、GoogleはAndroid向けにSHA-1フィンガープリントとリバースクライアントIDのURLスキームが必要です。 Apple と Google のガイドでは、すべてのステップとよくあるエラーを解説しています。
OAuth 2.0とOpenID ConnectによるエンタープライズSSO
Auth0、Okta、Microsoft Entra ID、Keycloak、Cognito、OneLogin、または独自のOIDCサーバーを使用する場合は、プラグインの oauth2 providerを使用してください。PKCEを使った認可 code フローを実行します。 ASWebAuthenticationSession iOSでは、AndroidではCustom Tabs上で実行されます。設定した場合: androidUseCustomTabs: true:
await SocialLogin.initialize({
oauth2: {
corp: {
issuerUrl: 'https://sso.example.com/realms/mobile', // OIDC discovery
clientId: 'mobile-app',
redirectUrl: 'com.example.app://oauth/corp',
scope: 'openid profile email offline_access',
pkceEnabled: true,
androidUseCustomTabs: true,
},
},
});
const { result } = await SocialLogin.login({
provider: 'oauth2',
options: { providerId: 'corp' },
});
同じマップに複数のプロバイダーを登録し、キーで1つを選ぶこともできます。 providerIdこれは、マルチテナントのB2Bアプリで各顧客が独自のIdPを持ち込めるようにする仕組みです。また、プラグインはリフレッシュ(SocialLogin.refresh)、ログアウトは id_token_hint、および Ionic Auth Connect 互換のラッパー(SocialLoginAuthConnect)は Auth Connect からの移行を検討するチーム向けです。各プロバイダーの手順: Auth0, Okta, Entra ID。プロトコルの背景については、こちらを参照: Capacitor アプリで OAuth2 を実装する 5 ステップ.
ホスト型バックエンド:Firebase、Supabase、Neon
データがすでに Firebase、Supabase、Neon にあるなら、その認証を使えばセキュリティルールや行レベルセキュリティが余計なつなぎ込みなしで機能します。
- Supabaseは:Social Login プラグインで ID トークンを取得し、
supabase.auth.signInWithIdToken({ provider: 'google', token }). Supabase が検証してセッションを返します。セットアップ全体: Supabase と Capacitor Social Login. - Neon: Neon Auth は、Neon ブランチ上で動作するマネージド Better Auth です。
@capgo/capacitor-neonは、メールとパスワード、メール OTP、Google、GitHub、Vercel OAuth によるシステムブラウザでのネイティブサインインに対応します。JWT を返します Neon Data API、これにより行レベルセキュリティが適用されます。セットアップ全体: Neon プラグインのドキュメント. - Firebase: どちらかを使用します
@capgo/capacitor-firebase-authentication、これはネイティブの Firebase Auth SDK をラップしたもの、または Social Login で ID トークンを取得し、JS の SDK で Firebase 認証情報を生成します。参照: Firebase の Google ログインのドキュメント.
セルフホスト: Better Auth
Better Auth は、ユーザーを独自のデータベースに保存するオープンソースの TypeScript 認証ライブラリです。WKWebView ではクロスサイトクッキーが信頼できないため、アプリのオリジンを信頼し、ベアラートークンに切り替えることで Capacitor で動作します。ソーシャルログインはネイティブプラグインと ID トークンの引き継ぎを通じて行われます。手順: Capacitor アプリで Better Auth を使用する方法.
パスキー
Passkeys は、iCloud キーチェーンまたは Google パスワードマネージャーに保存される鍵ペアでパスワードを置き換えます。アプリがウェブサイトドメインに関連付けられている必要があります (apple-app-site-association iOSでは適用され、 assetlinks.json Android) と WebAuthn サーバー。
@capgo/capacitor-passkey 標準の WebAuthn code を維持できます。relying party は以下で設定します capacitor.config.ts、起動時にシムを一度呼び出し、 navigator.credentials.create() と .get() ネイティブのパスキー API にルーティングされます:
import { CapacitorPasskey } from '@capgo/capacitor-passkey';
await CapacitorPasskey.autoShimWebAuthn();
// existing WebAuthn code keeps working
const assertion = await navigator.credentials.get({
publicKey: requestOptionsFromServer,
});
Better Authのようなライブラリや、Auth0、Oktaといったホスト型プロバイダーをWebAuthnサーバーとして利用できます。詳細は passkey pluginのページをご覧ください。.
自前のバックエンドでメール・パスワード認証
プラグインは不要で、単に fetchサーバー側の作業です。Argon2idやbcryptでのハッシュ化、ログイン試行のレート制限、確認・リセットメールの送信、アカウント削除の対応が含まれます。リセットや確認用のリンクはUniversal LinksとApp Linksでアプリ内に開き、スマホ上でリンクが正しい場所に開くようにしてください。これらすべてを自前で持つ理由がなければ、Better Authのようなライブラリやホスト型サービスを使う方が、同じ機能を低リスクで得られます。
常にサーバー側でトークンを検証してください
クライアントサイドのチェックはバイパスされる可能性があります。どのプロバイダーでも、セッションを作成する前にサーバーでトークンを検証する必要があります:
import { createRemoteJWKSet, jwtVerify } from 'jose';
type IssuerConfig = {
jwks: ReturnType<typeof createRemoteJWKSet>;
issuer: string | string[];
audience: string[];
};
const issuers: Record<'google' | 'apple', IssuerConfig> = {
google: {
jwks: createRemoteJWKSet(new URL('https://www.googleapis.com/oauth2/v3/certs')),
issuer: ['https://accounts.google.com', 'accounts.google.com'],
audience: ['WEB_CLIENT_ID.apps.googleusercontent.com', 'IOS_CLIENT_ID.apps.googleusercontent.com'],
},
apple: {
jwks: createRemoteJWKSet(new URL('https://appleid.apple.com/auth/keys')),
issuer: 'https://appleid.apple.com',
audience: ['com.example.app', 'com.example.app.signin'],
},
};
export async function verifyIdToken(provider: 'google' | 'apple', idToken: string) {
const cfg = issuers[provider];
const { payload } = await jwtVerify(idToken, cfg.jwks, {
issuer: cfg.issuer,
audience: cfg.audience,
});
return payload; // use payload.sub as the stable provider user ID
}
ユーザーはプロバイダーの sub ユーザーID(プロバイダー名も含む)で特定し、メールアドレスでは特定しないでください。プロバイダーが検証済みとマークした場合に限り、メールアドレスでアカウントをリンクしてください(email_verified: true)。MetaのLimited Loginトークンにはこのクレームが含まれていません。
セッションを安全に保存する
localStorage また、Capacitor Preferencesはプレーンファイルです。長期間有効なトークンは、Keychain (iOS) または Keystoreで暗号化されたストレージ (Android) に保存してください。 @capgo/capacitor-native-biometric 簡単な setData, getData と deleteData 方法があります:
bun add @capgo/capacitor-native-biometric
bunx cap sync
import { NativeBiometric } from '@capgo/capacitor-native-biometric';
export const sessionStore = {
async save(token: string) {
await NativeBiometric.setData({ key: 'session.token', value: token });
},
async load(): Promise<string | null> {
try {
const { value } = await NativeBiometric.getData({ key: 'session.token' });
return value;
} catch {
return null;
}
},
async clear() {
await NativeBiometric.deleteData({ key: 'session.token' }).catch(() => {});
},
};
アクセストークンの有効期限は短く設定し、リフレッシュトークンやサーバーセッションで更新してください。当社の セキュアなトークンストレージガイド では、ローテーションと失効について詳しく解説しています。
生体認証:ロック解除であり、本人確認ではない
Face IDや指紋認証は、端末を所持している人がロックを解除できることを証明するに過ぎません。保存済みセッションへのアクセスを制限するために使いましょう:
import { AccessControl, NativeBiometric } from '@capgo/capacitor-native-biometric';
// after a real login, offer biometric unlock
await NativeBiometric.setData({
key: 'session.refresh',
value: refreshToken,
accessControl: AccessControl.BIOMETRY_ANY,
});
// next app start
const { value } = await NativeBiometric.getSecureData({
key: 'session.refresh',
reason: 'Unlock your account',
});
// exchange `value` with your server for a fresh access token
を使用すると、 accessControl 設定すると、生体認証に成功した後にのみOSが値を返すため、保護はJavaScriptではなくKeychainやKeystore側で適用されます。サーバー側のセッション有効期限と組み合わせ、高リスクなアプリではroot化やjailbreakの検知も併用してください。詳細は Capacitor アプリでの生体認証.
配布方法の選択
| もしあなたが… | 使用する |
|---|---|
| iOSとAndroidでコンシューマーアプリをリリースしている | Social LoginでApple + Google、さらにメールやパスキーに対応したい |
| Microsoft 365を利用する企業に販売している | OAuth2プロバイダー経由でEntra IDを使用 |
| 顧客ごとに多数のエンタープライズIdPが必要 | Auth0 または Okta をブローカーとして使用、または複数の OAuth2 プロバイダーを providerId |
| すでに Supabase または Firebase を使用している | ネイティブ ID トークンによるサインインでその認証を利用 |
| すでに Neon を使用している | Neon Auth を通じて @capgo/capacitor-neon |
| ベンダーに依存しない独自のユーザーテーブルが欲しい | より優れた認証 |
| パスワードレスが欲しい | Passkeys、メールマジックリンクなどのフォールバック付き |
| 高速な再ログインが必要 | 上記いずれかの機能に追加して、保存済みセッションの生体認証ロック解除 |
ログインに影響する App Store と Play のルール
- Apple 4.8 ログインサービスサードパーティログインをメインのアカウントシステムとする場合、同等のプライバシー重視のオプションが必要です。Sign in with Apple がこれを満たします。
- Apple 5.1.1(v)アカウント作成にはアプリ内でのアカウント削除が必要であり、Sign in with Apple トークンは失効させる必要があります。参照: アカウント削除のコンプライアンス.
- Google Playのアカウント削除: アカウントを持つアプリは、アプリ内とPlay Consoleで申告したWebリンクの両方で削除を提供する必要があります。
- レビュアーアクセス: レビュアーには動作するデモアカウントを用意してください。ログインがSSOのみの場合は、テスト用のテナントユーザーを提供してください。
- Xcode 26: App Store Connectでは2026年4月から、Xcode 26とiOS 26 SDK で作成したビルドが必須になっているため、新しい認証機能を追加するリリースを提出する前にアップデートしてください。
認証の変更を安全にリリース
認証のバグは全ユーザーをブロックするため、迅速に修正したいところです。ネイティブの変更(entitlements、URL schemes、intent filters)にはストアビルドが必要ですが、プロバイダー設定、スコープ、エラーハンドリング、UIなどTypeScriptで完結するものはプッシュできます。 Capgo Live Updates 問題が起きたらロールバックできます。 Capgo のビルド 新しいネイティブリリースが必要なときは、クラウドで署名済みのiOS/Androidバイナリを生成します。
次のステップ
プロバイダーを選択し、該当するガイドに従ってください: