ソーシャルログインのセットアップ
Google・Apple のソーシャルログインをすばやく設定します。
ひと目でわかる
Unveily SDK はプランによってソーシャルログインで使えるプロバイダーが異なります。
| ソーシャル | Basic | Standard | Pro |
|---|---|---|---|
| ✅ | ✅ | ✅ | |
| Apple(iOS) | ✅ | ✅ | ✅ |
| Apple(Android) | ✅ | ✅ | ✅ |
| Kakao | — | ✅ | ✅ |
| Naver | — | ✅ | ✅ |
| LINE | — | ✅ | ✅ |
| Meta | — | — | ✅ |
Google と Apple はどちらも Firebase Auth を通じて処理されます — カスタムバックエンドは不要です。
両プロバイダーとも Firebase Console で設定し、同一の google-services.json が両方に適用されます。
SDK は Google および Apple ログイン時に Firebase ID Token(idToken)を返します。
サーバー側では Firebase Admin SDK の verifyIdToken() で検証できます。
iOS のプロバイダー対応状況
現在 iOS では Apple と Google ログインのみが動作します。iOS で Kakao・Naver・LINE・Meta を呼び出すと、今後の iOS SDK アップデートまで SDK_NOT_READY エラーが返される場合があります。Android はすべてのプロバイダーに対応しています。Apple/Google は両プラットフォームで動作します。
また、iOS の Apple ログインは idToken に加えて authorizationCode(Apple 専用)を返します。上記の「Google + Apple は idToken を返す」という記述は Firebase 経路(Android および iOS の Firebase 処理分)を指します。
1. キー設定ファイル
assets/config/social_login_config.json に各ソーシャルの SDK キーを入力します。
{
"kakao": {
"nativeAppKey": "ここにKakaoネイティブアプリキーを入力"
},
"naver": {
"clientId": "ここにNaverクライアントIDを入力",
"clientSecret": "ここにNaverクライアントシークレットを入力",
"appName": "アプリ名"
},
"line": {
"channelId": "ここにLINEチャンネルIDを入力"
},
"meta": {
"appId": "ここにMetaアプリIDを入力",
"clientToken": "ここにMetaクライアントトークンを入力"
}
}- キーが空の場合、そのソーシャルは自動的に無効になります。
- Google・Apple:
google-services.json+ Firebase Console で設定します。このファイルへの追加項目は不要です。
2. build.gradle.kts のプレースホルダーを修正する
Kakao と Meta はディープリンクのコールバックのために、build.gradle.kts の manifest placeholder を更新する必要があります。
// app/build.gradle.kts — defaultConfig 内
defaultConfig {
// Kakao: "kakao" + nativeAppKey
manifestPlaceholders["kakaoScheme"] = "kakaoここにKakaoネイティブアプリキーを入力"
// Meta: "fb" + appId
manifestPlaceholders["facebookLoginProtocolScheme"] = "fbここにMetaアプリIDを入力"
}3. ソーシャルボタンの表示制御
assets/config.json の socialLogin セクションでボタンの表示・非表示を切り替えます。
{
"socialLogin": {
"google": true,
"apple": true,
"kakao": true,
"naver": true,
"line": false,
"meta": false
}
}true: ボタンを表示します(ただし、プランでも許可されている場合のみ動作します)false: ボタンを非表示にします
4. 開発者コンソールへの登録手順
- Firebase Console → プロジェクトを作成
- Authentication → ログイン方法 → Google を有効にする
google-services.jsonをダウンロードしてapp/フォルダーに置き換えます
Apple(iOS および Android)
iOS・Android どちらも Apple サインインは Firebase Auth を通じて処理されます — 同一の Firebase プロジェクトが両プラットフォームをカバーします。
- Apple Developer → Certificates, Identifiers & Profiles:
- Services ID を作成(逆ドメイン形式、例:
com.yourcompany.app) - Sign In with Apple を有効にした Key を作成 → Team ID・Key ID をメモし、
.p8キーをダウンロード
- Services ID を作成(逆ドメイン形式、例:
- Firebase Console → Authentication → ログイン方法 → Apple を有効にする
- Team ID・Services ID・Key ID を入力し、
.p8秘密鍵の内容を貼り付けます
- Team ID・Services ID・Key ID を入力し、
- 同一の
google-services.jsonが Google と Apple の両方に適用されます — 追加ファイルは不要です。
Firebase が Apple の OAuth フロー全体(Android の Chrome カスタムタブを含む)を内部で処理します。 サーバー側のコールバックエンドポイントやカスタム URL スキームは不要です。
Kakao
- Kakao 開発者コンソール → マイアプリケーション → アプリケーションを追加
- アプリキー → ネイティブアプリキー をコピー
- プラットフォーム → Android → パッケージ名とマーケット URL を登録
- Kakao ログイン → 有効化 → 同意項目の設定(ニックネーム・メールなど)
social_login_config.json→kakao.nativeAppKeyを入力build.gradle.kts→manifestPlaceholders["kakaoScheme"] = "kakao{ネイティブアプリキー}"を修正
Naver
- Naver 開発者センター → Application → アプリケーションを登録
- 使用する API → ネアロ(Naver ID でログイン) を選択
- Android → パッケージ名を登録
- Client ID / Client Secret をコピー
social_login_config.json→naver.clientId・naver.clientSecret・naver.appNameを入力
LINE
- LINE Developers → Providers → Create → Channel を作成
- Channel の種類 → LINE Login を選択
- Android Package Name を登録
- Channel ID をコピー
social_login_config.json→line.channelIdを入力
Meta(Facebook)
- Meta for Developers → My Apps → Create App
- 製品を追加 → Facebook Login を選択
- 設定 → 基本設定 → アプリ ID と クライアントトークン をコピー
- Android → パッケージ名とキーハッシュを登録
social_login_config.json→meta.appId・meta.clientTokenを入力build.gradle.kts→manifestPlaceholders["facebookLoginProtocolScheme"] = "fb{アプリID}"を修正
5. JS Bridge API
ログイン
window.unveilyBridge.auth.socialLogin({
provider: 'google' // 'apple' | 'kakao' | 'naver' | 'line' | 'meta'
});ログインのコールバック
ページに以下の関数を宣言しておくと、結果を受け取れます。
function onSocialLoginResult(result) {
if (result.success) {
console.log(result.provider); // 'google' | 'apple' | 'kakao' | ...
console.log(result.uid); // Firebase UID(Google/Apple)またはソーシャルの固有 ID
console.log(result.displayName); // 名前(null の場合あり)
console.log(result.email); // メール(null の場合あり)
console.log(result.profileImage); // プロフィール画像の URL(null の場合あり)
console.log(result.idToken); // Firebase ID Token(Google + Apple のみ。Kakao/Naver/LINE/Meta は null)
// idToken を使って Firebase Admin SDK でサーバー側検証を行います
} else {
console.error(result.error);
// 主なエラーコード:
// FEATURE_NOT_ALLOWED → プランが対応していない(result.requiredTier を含む)
// PROVIDER_DISABLED → config.json で false に設定されている
// SDK_NOT_CONFIGURED → social_login_config.json にキーが未入力
// SDK_NOT_READY → iOS で未対応のプロバイダー(Kakao/Naver/LINE/Meta)
// LOGIN_CANCELLED → ユーザーがログイン画面を閉じた
}
}ログアウト
window.unveilyBridge.auth.logout({ provider: 'google' });連携解除(ソーシャルプロバイダーの切り離し)
該当のソーシャルプロバイダーとの連携のみを解除します。アカウント自体は削除されません。
window.unveilyBridge.auth.revoke({ provider: 'kakao' });Google / Apple の連携解除
revoke は Firebase の user.unlink() を呼び出します — 該当プロバイダーの連携のみ解除されます。
Firebase アカウントはそのまま維持されます。
アカウント削除(退会)はサーバー側で user.delete() を呼び出す別途の処理が必要です。
ログアウト・連携解除のコールバック
function onSocialAuthResult(result) {
// result.success — true/false
// result.action — 'logout' | 'revoke'
// result.provider — 'google' | 'apple' | 'kakao' | ...
// result.error — 失敗時のエラーコード
}6. エラーコード参照
| エラーコード | 説明 |
|---|---|
FEATURE_NOT_ALLOWED | 現在のプランで許可されていないソーシャル(requiredTier を含む) |
PROVIDER_DISABLED | config.json でそのソーシャルが false になっている |
SDK_NOT_CONFIGURED | social_login_config.json のキーが空 |
SDK_NOT_READY | iOS でまだ対応していないプロバイダー(Kakao/Naver/LINE/Meta — 今後の iOS SDK アップデートで対応予定) |
LOGIN_CANCELLED | ユーザーがログイン画面を閉じた |
UNKNOWN_PROVIDER | サポートされていない provider の値 |
GOOGLE_ID_TOKEN_NULL | Google ID トークンの発行失敗 |
FIREBASE_AUTH_FAILED | Firebase サインイン認証情報が拒否された |
APPLE_NO_USER | Apple サインイン成功後、Firebase がユーザーを返さなかった |
APPLE_ERROR | Apple サインイン失敗(一般) |
GOOGLE_REVOKE_FAILED | Google プロバイダーの連携解除失敗 |
APPLE_REVOKE_FAILED | Apple プロバイダーの連携解除失敗 |
NAVER_NO_TOKEN | Naver アクセストークンがない |
LINE_INIT_FAILED | LINE SDK の初期化失敗 |
7. profileImage の処理ルール
| ソーシャル | 提供有無 |
|---|---|
ほぼ常に提供(ない場合は null) | |
| Apple | 常に null(元から提供なし) |
| Kakao | 同意項目の設定時に提供 |
| Naver | 同意項目の設定時に提供 |
| LINE | ユーザーのプロフィール公開設定時に提供 |
| Meta | 公開プロフィールの設定時に提供 |
null の場合は、お客様側でデフォルト画像を表示するように処理してください。
function onSocialLoginResult(result) {
const avatar = result.profileImage
?? '/images/default-avatar.png';
document.getElementById('avatar').src = avatar;
}8. Apple の displayName キャッシュ
Apple は初回ログイン時のみユーザー名を提供します。SDK はこれをローカルにキャッシュします。
| 動作 | 処理 |
|---|---|
| 初回ログイン(displayName あり) | キャッシュに保存して渡す |
| 再ログイン(displayName が null) | キャッシュした値で代替して渡す |
| ログアウト | キャッシュを保持(再ログインに備えて) |
| 連携解除(revoke) | キャッシュを削除(再連携時に Apple が新しく提供) |
| プラットフォーム | キャッシュ保存場所 | キーの形式 |
|---|---|---|
| iOS | UserDefaults | apple_name_{uid} |
| Android | SharedPreferences("unveily_apple_name_cache") | apple_name_{uid} |
9. 完成例
// ログインボタンのクリック
document.getElementById('btn-google').addEventListener('click', () => {
window.unveilyBridge.auth.socialLogin({ provider: 'google' });
});
// 結果の処理
function onSocialLoginResult(result) {
if (!result.success) {
if (result.error === 'FEATURE_NOT_ALLOWED') {
alert(`${result.requiredTier} プラン以上でご利用いただけます。`);
} else if (result.error !== 'LOGIN_CANCELLED') {
alert('ログインに失敗しました。');
}
return;
}
// サーバーに送信 — Google/Apple は idToken でサーバー側検証を行います
sendToServer(result);
}
async function sendToServer(result) {
await fetch('/api/auth/social', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
provider: result.provider,
uid: result.uid,
idToken: result.idToken, // Firebase ID Token(Google/Apple)— サーバー側検証用
email: result.email,
displayName: result.displayName
})
});
}サーバー側の Firebase ID Token 検証
Google および Apple ログインの場合、Firebase Admin SDK を使ってサーバー側で idToken を検証します。
// npm install firebase-admin
import admin from 'firebase-admin';
admin.initializeApp({ credential: admin.credential.applicationDefault() });
app.post('/api/auth/social', async (req, res) => {
const { provider, uid, idToken, email, displayName } = req.body;
// Google および Apple の Firebase ID Token を検証
if (idToken) {
const decoded = await admin.auth().verifyIdToken(idToken);
if (decoded.uid !== uid) return res.status(401).json({ error: 'UID mismatch' });
}
// uid でユーザーを検索または作成
let user = await db.users.findOne({ socialProvider: provider, socialId: uid });
if (!user) {
user = await db.users.create({ socialProvider: provider, socialId: uid, email, name: displayName });
}
req.session.userId = user.id;
res.json({ ok: true, user: { id: user.id, name: user.name } });
});// NuGet: FirebaseAdmin
using FirebaseAdmin;
using FirebaseAdmin.Auth;
[HttpPost("auth/social")]
public async Task<IActionResult> SocialLogin([FromBody] SocialLoginRequest request)
{
// Google および Apple の Firebase ID Token を検証
if (!string.IsNullOrEmpty(request.IdToken))
{
var decoded = await FirebaseAuth.DefaultInstance.VerifyIdTokenAsync(request.IdToken);
if (decoded.Uid != request.Uid)
return Unauthorized(new { error = "UID mismatch" });
}
var user = await _userService.FindOrCreateBySocialAsync(
request.Provider, request.Uid, request.Email, request.DisplayName);
HttpContext.Session.SetInt32("UserId", user.Id);
return Ok(new { ok = true, user = new { user.Id, user.Name } });
}// Maven: com.google.firebase:firebase-admin
@PostMapping("/api/auth/social")
public ResponseEntity<?> socialLogin(@RequestBody SocialLoginRequest request,
HttpSession session) throws FirebaseAuthException {
// Google および Apple の Firebase ID Token を検証
if (request.getIdToken() != null) {
FirebaseToken decoded = FirebaseAuth.getInstance().verifyIdToken(request.getIdToken());
if (!decoded.getUid().equals(request.getUid()))
return ResponseEntity.status(401).body(Map.of("error", "UID mismatch"));
}
User user = userService.findOrCreateBySocial(
request.getProvider(), request.getUid(), request.getEmail(), request.getDisplayName());
session.setAttribute("userId", user.getId());
return ResponseEntity.ok(Map.of("ok", true, "userId", user.getId()));
}<?php
// composer require kreait/firebase-php
use Kreait\Firebase\Factory;
$data = json_decode(file_get_contents('php://input'), true);
$provider = $data['provider'];
$uid = $data['uid'];
$idToken = $data['idToken'] ?? null;
$email = $data['email'] ?? null;
$displayName = $data['displayName'] ?? null;
// Google および Apple の Firebase ID Token を検証
if ($idToken) {
$firebase = (new Factory)->withServiceAccount('/path/to/serviceAccount.json');
$auth = $firebase->createAuth();
$decoded = $auth->verifyIdToken($idToken);
if ($decoded->claims()->get('sub') !== $uid) {
http_response_code(401);
echo json_encode(['error' => 'UID mismatch']);
exit;
}
}
$stmt = $pdo->prepare('SELECT * FROM users WHERE social_provider = ? AND social_id = ?');
$stmt->execute([$provider, $uid]);
$user = $stmt->fetch();
if (!$user) {
$pdo->prepare('INSERT INTO users (social_provider, social_id, email, name) VALUES (?, ?, ?, ?)')
->execute([$provider, $uid, $email, $displayName]);
$userId = $pdo->lastInsertId();
} else {
$userId = $user['id'];
}
$_SESSION['user_id'] = $userId;
echo json_encode(['ok' => true, 'userId' => $userId]);