Flutter中Facebook授权提示错误的签名

最近在项目中集成Facebook登录,按照之前的流程接入,登录时提示下面的错误

Unhandled Exception: [firebase_auth/invalid-credential] {"code":190,"message":"Bad signature"}

这里是我的项目依赖

firebase_core: ^3.8.0
firebase_auth: ^5.3.3
flutter_facebook_auth: ^7.1.1

我之前的授权代码如下,登录的时候提示错误

Future<UserCredential> signInWithFacebook() async {
    // throw SimpleException('Facebook Login Fail.');
    // Trigger the sign-in flow
    final LoginResult loginResult = await FacebookAuth.instance.login();
    if (loginResult.accessToken?.token == null) {
        throw SimpleException('Facebook Login Fail.');
    }
    // Create a credential from the access token
    final OAuthCredential facebookAuthCredential =
            FacebookAuthProvider.credential(loginResult.accessToken!.token);
    // Once signed in, return the UserCredential
    return FirebaseAuth.instance.signInWithCredential(facebookAuthCredential);
}

经过查阅资料,发现最近Facebook SDK发生了一些修改,具体可以参考下面的链接:

https://github.com/facebook/facebook-ios-sdk/issues/2365

在stackoverflow也找到了一些解决方案,基本就是下面的两种方案

  • 强制App进行跟踪(这个在审核会有问题)
  • 本地自己生成nonce字符串

我选择了第2种方式来实现,代码修改如下

import 'package:crypto/crypto.dart';
import 'dart:math';

class AuthService extends GetxController {
    /// 这里应该还有一些业务代码
    /// .....
    
    /// facebook登录
    Future<UserCredential> signInWithFacebook() async {
        final rawNonce = generateNonce();
        final nonce = sha256ofString(rawNonce);
        final LoginResult loginResult = await FacebookAuth.instance.login(
            loginTracking: LoginTracking.enabled,
            nonce: nonce,
        );
    
        OAuthCredential facebookAuthCredential;
    
        // Create a credential from the access token
        switch (loginResult.accessToken!.type) {
            case AccessTokenType.classic:
                final token = loginResult.accessToken as ClassicToken;
                facebookAuthCredential = FacebookAuthProvider.credential(
                    token.authenticationToken!,
                );
                break;
            case AccessTokenType.limited:
                final token = loginResult.accessToken as LimitedToken;
                facebookAuthCredential = OAuthCredential(
                    providerId: 'facebook.com',
                    signInMethod: 'oauth',
                    idToken: token.tokenString,
                    rawNonce: rawNonce,
                );
                break;
        }
    
        if (facebookAuthCredential == null) {
            throw SimpleException('Facebook Login Fail.');
        }
    
        // Once signed in, return the UserCredential
        return FirebaseAuth.instance.signInWithCredential(facebookAuthCredential);
    }
    
    String generateNonce([int length = 32]) {
        const charset =
                '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._';
        final random = Random.secure();
        return List.generate(length, (_) => charset[random.nextInt(charset.length)])
                .join();
    }
    
    /// Returns the sha256 hash of [input] in hex notation.
    String sha256ofString(String input) {
        final bytes = utf8.encode(input);
        final digest = sha256.convert(bytes);
        return digest.toString();
    }
}

上述的解决方案参考链接

留下回复