跳过内容

__CAPGO_KEEP_0__社交登录仓库

GitHub

In this guide, you will learn how to setup Facebook Login with Capgo Social Login. You will need the following:

  • Facebook开发者账户
  • 您的应用程序的包名/捆绑ID
  • 生成密钥哈希(Android)的终端访问权限

通用设置

通用设置

如果您尚未创建Facebook应用程序,请遵循以下步骤:

  1. 创建Facebook应用

    遵循教程 创建应用

  2. 将Facebook登录添加到您的应用程序中

    在您的Facebook开发者控制台中,向您的应用程序添加Facebook登录产品

  3. 在发布应用程序之前,您需要遵循以下步骤 教程 发布它

重要信息

重要信息

这里是您需要的整合所需的关键信息的位置:

  1. CLIENT_TOKEN:

    Facebook开发者控制台显示客户令牌的位置
  2. APP_ID:

    Facebook开发者控制台显示应用ID的位置
  3. APP_NAME:

    Facebook开发者控制台显示应用名称的位置

此插件支持Facebook商业登录,用于商业相关功能和权限。商业账户可以请求额外的权限,包括Instagram和页面管理。

支持的商业权限包括:

  • instagram_basic - Instagram 基本显示访问 API
  • instagram_manage_insights - Instagram Insights访问
  • pages_show_list - 人员管理的页面列表
  • pages_read_engagement - 从页面读取互动数据
  • pages_manage_posts - 在页面管理帖子
  • business_management - 管理商业资产

查看 Facebook 权限参考 查看完整权限列表。

配置要求:

  1. 您的Facebook应用程序必须在Facebook开发者控制台中配置为商业应用程序。
  2. 商业权限可能需要Facebook应用程序审查在生产环境中使用之前。
  3. 您的应用程序必须遵守Facebook的商业用例政策。

Instagram基本访问

Instagram基本访问
await SocialLogin.initialize({
facebook: {
appId: 'your-business-app-id',
clientToken: 'your-client-token',
},
});
const res = await SocialLogin.login({
provider: 'facebook',
options: {
permissions: [
'email',
'public_profile',
'instagram_basic',
'pages_show_list',
'pages_read_engagement',
],
},
});
const profile = await SocialLogin.providerSpecificCall({
call: 'facebook#getProfile',
options: {
fields: ['id', 'name', 'email', 'instagram_business_account'],
},
});

页面管理

页面管理
const res = await SocialLogin.login({
provider: 'facebook',
options: {
permissions: [
'email',
'pages_show_list',
'pages_manage_posts',
'pages_read_engagement',
],
},
});
const profile = await SocialLogin.providerSpecificCall({
call: 'facebook#getProfile',
options: {
fields: ['id', 'name', 'accounts{id,name,instagram_business_account}'],
},
});

重要注意事项:

  • 您可以使用测试用户和开发应用程序测试商业权限,避免App Review。
  • 大多数商业权限在生产使用之前需要Facebook App Review。
  • 商业API具有不同的速率限制。请在发布前查看Facebook的当前平台文档。
  • 遵循 Facebook 商业集成指南 在配置应用程序时。
  1. 将互联网权限添加到您的 AndroidManifest.xml

    确保此行存在:

    <uses-permission android:name="android.permission.INTERNET"/>
  2. 生成您的 Android 密钥哈希

    这是 Facebook 需要的关键安全步骤。打开您的终端并运行:

    终端窗口
    keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64 -A

    当被提示输入密码时,请使用: android

  3. 将密钥哈希添加到您的 Facebook 应用

    1. 转到您的应用的 Facebook Developers 控制台
    2. 导航到设置 > 基本
    3. 滚动到“Android”部分
    4. 如果 Android 还没有添加,请点击“添加平台”,并填写详细信息
    5. 添加您生成的密钥哈希
    6. 对于生产环境,添加两种密钥哈希(debug 和 release)
  4. 更新您的 AndroidManifest.xml 以包含:

    <application>
    ...
    <activity android:name="com.facebook.FacebookActivity"
    android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
    android:label="@string/app_name" />
    <activity
    android:name="com.facebook.CustomTabActivity"
    android:exported="true">
    <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="FB[APP_ID]" />
    </intent-filter>
    </activity>
    </application>

iOS设置

iOS设置
  1. 在Facebook开发者控制台中添加iOS平台

    1. 前往您的应用程序的仪表板Facebook开发者
    2. 前往设置 > 基本
    3. 滚动到页面底部并点击“添加平台”
    4. 选择 iOS 并填写所需详细信息
  2. 打开您的 Xcode 项目并导航到 Info.plist

  3. 在 Info.plist 中添加以下条目:

    <key>FacebookAppID</key>
    <string>[APP-ID]</string>
    <key>FacebookClientToken</key>
    <string>[CLIENT-TOKEN]</string>
    <key>FacebookDisplayName</key>
    <string>[APP-NAME]</string>
    <key>LSApplicationQueriesSchemes</key>
    <array>
    <string>fbapi</string>
    <string>fb-messenger-share-api</string>
    </array>
    <key>CFBundleURLTypes</key>
    <array>
    <dict>
    <key>CFBundleURLSchemes</key>
    <array>
    <string>fb[APP-ID]</string>
    </array>
    </dict>
    </array>
  4. 修改 AppDelegate.swift

    import FBSDKCoreKit
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    // Initialize Facebook SDK
    FBSDKCoreKit.ApplicationDelegate.shared.application(
    application,
    didFinishLaunchingWithOptions: launchOptions
    )
    return true
    }
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
    // Called when the app was launched with a url. Feel free to add additional processing here,
    // but if you want the App API to support tracking app url opens, make sure to keep this call
    if (FBSDKCoreKit.ApplicationDelegate.shared.application(
    app,
    open: url,
    sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String,
    annotation: options[UIApplication.OpenURLOptionsKey.annotation]
    )) {
    return true;
    } else {
    return ApplicationDelegateProxy.shared.application(app, open: url, options: options)
    }
    }
    }

在您的应用程序中使用Facebook登录

标题:在您的应用程序中使用Facebook登录
  1. 在您的应用程序中初始化Facebook登录

    import { SocialLogin } from '@capgo/capacitor-social-login';
    // Initialize during app startup
    await SocialLogin.initialize({
    facebook: {
    appId: 'APP_ID',
    clientToken: 'CLIENT_TOKEN',
    }
    })
  2. 实现登录功能

    async function loginWithFacebook() {
    try {
    const result = await SocialLogin.login({
    provider: 'facebook',
    options: {
    permissions: ['email', 'public_profile'],
    limitedLogin: false // See Limited Login section below for important details
    }
    });
    console.log('Facebook login result:', result);
    // Handle successful login
    } catch (error) {
    console.error('Facebook login error:', error);
    // Handle error
    }
    }
  3. 获取用户资料

    成功登录后,您可以检索以下附加资料:

    async function getFacebookProfile() {
    try {
    const profileResponse = await SocialLogin.providerSpecificCall({
    call: 'facebook#getProfile',
    options: {
    fields: ['id', 'name', 'email', 'first_name', 'last_name', 'picture']
    }
    });
    console.log('Facebook profile:', profileResponse.profile);
    return profileResponse.profile;
    } catch (error) {
    console.error('Failed to get Facebook profile:', error);
    return null;
    }
    }
    // Example usage after login
    async function loginAndGetProfile() {
    const loginResult = await loginWithFacebook();
    if (loginResult) {
    const profile = await getFacebookProfile();
    if (profile) {
    console.log('User ID:', profile.id);
    console.log('Name:', profile.name);
    console.log('Email:', profile.email);
    console.log('Profile Picture:', profile.picture?.data?.url);
    }
    }
    }

    令牌类型限制: getProfile 仅当您具有 访问令牌 (标准登录允许跟踪)时,

此调用才会生效。如果用户拒绝跟踪或您正在使用有限登录(仅限 JWT 令牌),则此调用会失败。在这种情况下,请使用初始登录响应中提供的用户资料。

⚠️ Critical: 后端令牌处理

: 总是访问令牌,设置被忽略。 __CAPGO_KEEP_0__ __CAPGO_KEEP_0__

__CAPGO_KEEP_0__

__CAPGO_KEEP_0__
__CAPGO_KEEP_0____CAPGO_KEEP_0____CAPGO_KEEP_0__iOS 用户可以根据 App Tracking Transparency 选择接收 access tokens 或 JWT tokens,而 Android 用户始终接收 access tokens。
__CAPGO_KEEP_0__true__CAPGO_KEEP_0__iOS
任何false允许跟踪访问令牌
iOSfalse拒绝跟踪JWT令牌(自动覆盖)
Android任何N/A访问令牌(始终)

后端实现

后端实现
  1. 检测令牌类型并根据情况处理

    async function loginWithFacebook() {
    try {
    const loginResult = await SocialLogin.login({
    provider: 'facebook',
    options: {
    permissions: ['email', 'public_profile'],
    limitedLogin: false // iOS: depends on ATT, Android: ignored
    }
    });
    if (loginResult.accessToken) {
    // Access token (Android always, iOS when tracking allowed)
    return handleAccessToken(loginResult.accessToken.token);
    } else if (loginResult.idToken) {
    // JWT token (iOS only when tracking denied or limitedLogin: true)
    return handleJWTToken(loginResult.idToken);
    }
    } catch (error) {
    console.error('Facebook login error:', error);
    }
    }
  2. Firebase 集成示例

    import { OAuthProvider, FacebookAuthProvider, signInWithCredential } from 'firebase/auth';
    async function handleAccessToken(accessToken: string, nonce: string) {
    // For access tokens, use OAuthProvider (new method)
    const fbOAuth = new OAuthProvider("facebook.com");
    const credential = fbOAuth.credential({
    idToken: accessToken,
    rawNonce: nonce
    });
    try {
    const userResponse = await signInWithCredential(auth, credential);
    return userResponse;
    } catch (error) {
    console.error('Firebase OAuth error:', error);
    return false;
    }
    }
    async function handleJWTToken(jwtToken: string) {
    // For JWT tokens, send to your backend for validation
    try {
    const response = await fetch('/api/auth/facebook-jwt', {
    method: 'POST',
    headers: {
    'Content-Type': 'application/json',
    },
    body: JSON.stringify({ jwtToken })
    });
    const result = await response.json();
    return result;
    } catch (error) {
    console.error('JWT validation error:', error);
    return false;
    }
    }
  3. 后端 JWT 验证

    // Backend: Validate JWT token from Facebook
    import jwt from 'jsonwebtoken';
    import { Request, Response } from 'express';
    app.post('/api/auth/facebook-jwt', async (req: Request, res: Response) => {
    const { jwtToken } = req.body;
    try {
    // Verify JWT token with Facebook's public key
    // See: https://developers.facebook.com/docs/facebook-login/limited-login/token/validating/#standard-claims
    const decoded = jwt.verify(jwtToken, getFacebookPublicKey(), {
    algorithms: ['RS256'],
    audience: process.env.FACEBOOK_APP_ID,
    issuer: 'https://www.facebook.com' // From: https://www.facebook.com/.well-known/openid-configuration/?_rdr
    });
    // Extract user info from JWT
    const userInfo = {
    id: decoded.sub,
    email: decoded.email,
    name: decoded.name,
    isJWTAuth: true
    };
    // Create your app's session/token
    const sessionToken = createUserSession(userInfo);
    res.json({
    success: true,
    token: sessionToken,
    user: userInfo
    });
    } catch (error) {
    console.error('JWT validation failed:', error);
    res.status(401).json({ success: false, error: 'Invalid token' });
    }
    });
  4. 通用后端令牌处理器

    // Handle both token types in your backend
    async function authenticateFacebookUser(tokenData: any) {
    if (tokenData.accessToken) {
    // Handle access token - validate with Facebook Graph API
    const response = await fetch(`https://graph.facebook.com/me?access_token=${tokenData.accessToken}&fields=id,name,email`);
    const userInfo = await response.json();
    return {
    user: userInfo,
    tokenType: 'access_token',
    expiresIn: tokenData.expiresIn || 3600
    };
    } else if (tokenData.jwtToken) {
    // Handle JWT token - decode and validate
    // See: https://developers.facebook.com/docs/facebook-login/limited-login/token/validating/#standard-claims
    const decoded = jwt.verify(tokenData.jwtToken, getFacebookPublicKey());
    return {
    user: {
    id: decoded.sub,
    name: decoded.name,
    email: decoded.email
    },
    tokenType: 'jwt',
    expiresIn: decoded.exp - Math.floor(Date.now() / 1000)
    };
    } else {
    throw new Error('No valid token provided');
    }
    }

重要考虑因素

标题:重要考虑因素

Access Token (Standard Login):

  • Android: 总是可用(iOS-only 限制不适用)
  • iOS: 只有当用户明确允许应用跟踪时
  • ✅ 可以用于访问 Facebook Graph API
  • ✅ 更长的过期时间
  • ✅ 可以获取更多用户数据
  • 在 iOS 上变得越来越少见 因为用户越来越多地拒绝跟踪

JWT Token (iOS-Only Privacy Mode):

  • Android: 从未发生 (不受支持)
  • iOS: 当跟踪被拒绝或 limitedLogin: true
  • ✅ 遵守 iOS 用户隐私偏好
  • ❌ 只包含基本用户信息
  • ❌ 更短的过期时间
  • ❌ 无法访问 Facebook Graph API
  • ⚠️ 现在 iOS 用户最常见的场景

平台特定行为:

  • iOS 应用: 必须处理两种类型的令牌:访问令牌和 JWT 令牌
  • Android 应用: 只需要处理访问令牌
  • 跨平台应用: 必须实现两种令牌处理方法

Web安全上下文要求(Capacitor)

标题:Web安全上下文要求(Capacitor)

更新后的Facebook登录流程需要 Web加密API 用于生成随机数的__CAPGO_KEEP_0__ 仅在安全上下文中可用:

// This requires secure context (HTTPS or localhost)
async function sha256(message: string) {
const msgBuffer = new TextEncoder().encode(message);
const hashBuffer = await crypto.subtle.digest("SHA-256", msgBuffer); // ❌ Fails in insecure context
// ...
}

开发环境问题

开发环境问题

常见问题: ionic serve 使用 HTTP URL 的 Facebook 登录会出现问题

环境加密 API 可用Facebook 登录正常工作
http://localhost:3000✅ 是✅ 是
http://127.0.0.1:3000✅ 是✅ 是
http://192.168.1.100:3000❌ 否❌ 否
https://any-domain.com✅ 是✅ 是

解决方案Capacitor开发

标题:解决方案Capacitor开发
  1. 使用localhost进行web测试

    终端窗口
    # Instead of ionic serve --host=0.0.0.0
    ionic serve --host=localhost
  2. 在Ionic中启用HTTPS

    终端窗口
    ionic serve --ssl
  3. 在实际设备上进行测试

    终端窗口
    # Capacitor apps run in secure context on devices
    ionic cap run ios
    ionic cap run android
  4. 开发环境下替代的非对称密钥生成

    async function generateNonce() {
    if (typeof crypto !== 'undefined' && crypto.subtle) {
    // Secure context - use crypto.subtle
    return await sha256(Math.random().toString(36).substring(2, 10));
    } else {
    // Fallback for development (not secure for production)
    console.warn('Using fallback nonce - not secure for production');
    return btoa(Math.random().toString(36).substring(2, 10));
    }
    }

Firebase 集成注意事项

Firebase 集成注意事项

最近的 Firebase 文档要求使用 JWT 令牌和非对称密钥进行 Facebook 登录,哪怕是无论登录设置如何。这一方法适用于两种情况 limitedLogin: truelimitedLogin: false:

// Both modes can return JWT tokens depending on user choice
const loginResult = await SocialLogin.login({
provider: 'facebook',
options: {
permissions: ['email', 'public_profile'],
limitedLogin: false, // true = always JWT, false = depends on user tracking choice
nonce: nonce
}
});

开发限制: 如果您在 ionic serve on a network IP (not localhost), Facebook login will fail due to crypto API restrictions. Use localhost or HTTPS for web testing.

  1. 上下文:支持/高级支持页面或底部支持部分。角色:部分或页面标题。见于:页面 support-policy.astro。消息键 `support_policy_common_issues_title` (支持政策常见问题标题)。

    • 常见问题和解决方案
    • Android 上的密钥哈希错误
    • 请确认您已在 Facebook 控制台中添加了正确的密钥哈希
  2. 对于发布版本,请确保已添加了 debug 和 release 密钥哈希的哈希值

    • 验证所有清单条目是否正确
    • 检查您的Facebook App ID和Client Token是否正确
    • 确保您已正确初始化SDK
  3. 常见iOS问题

    • 确保所有Info.plist条目是否正确
    • 验证URL方案是否正确配置
    • 检查您的包ID是否与Facebook控制台中注册的ID匹配

测试

测试
  1. 在测试之前,在Facebook开发者控制台中添加测试用户

    • 转到角色>测试用户
    • 创建测试用户
    • 使用以下凭据进行测试
  2. 测试调试和发布版本

    • 使用调试密钥哈希的调试版本
    • 使用发布密钥哈希的发布版本
    • 在模拟器和物理设备上测试

请记住测试完整的登录流程,包括:

  • 成功登录
  • 登录取消
  • 错误处理
  • 注销功能

If you are using Facebook Login Setup to plan authentication and account flows, connect it with 使用 @capgo/capacitor-social-login for the native capability in 使用 @capgo/capacitor-social-login 使用 @capgo/capacitor-social-login for the implementation detail in 使用 @capgo/capacitor-social-login 使用 @capgo/capacitor-passkey for the implementation detail in 使用 @capgo/capacitor-passkey 使用 @capgo/capacitor-native-biometric for the implementation detail in 使用 @capgo/capacitor-native-biometric, and Two-factor authentication 用于两因素认证的实现细节。