signInWithCredential method

Future<UserCredential> signInWithCredential(
  1. AuthCredential credential
)

Asynchronously signs in to Firebase with the given 3rd-party credentials (e.g. a Facebook login Access Token, a Google ID Token/Access Token pair, etc.) and returns additional identity provider data.

If successful, it also signs the user in into the app and updates any authStateChanges, or idTokenChanges stream listeners.

If the user doesn't have an account already, one will be created automatically.

Important: You must enable the relevant accounts in the Auth section of the Firebase console before being able to use them.

A FirebaseAuthException maybe thrown with the following error code:

  • account-exists-with-different-credential
    • Thrown if there already exists an account with the email address asserted by the credential. Resolve this by calling fetchSignInMethodsForEmail and then asking the user to sign in using one of the returned providers. Once the user is signed in, the original credential can be linked to the user with linkWithCredential.
  • invalid-credential
    • Thrown if the credential is malformed or has expired.
  • operation-not-allowed
    • Thrown if the type of account corresponding to the credential is not enabled. Enable the account type in the Firebase Console, under the Auth tab.
  • user-disabled
    • Thrown if the user corresponding to the given credential has been disabled.
  • user-not-found
  • wrong-password
    • Thrown if signing in with a credential from EmailAuthProvider.credential and the password is invalid for the given email, or if the account corresponding to the email does not have a password set.
  • invalid-code
    • Thrown if the credential is a PhoneAuthProvider.credential and the verification code of the credential is not valid.
  • invalid-verification-id
    • Thrown if the credential is a PhoneAuthProvider.credential and the verification ID of the credential is not valid.

Implementation

Future<UserCredential> signInWithCredential(
  AuthCredential credential,
) async {
  try {
    Map<String, dynamic> response;

    if (credential is EmailAuthCredential) {
      if (credential.providerId ==
          EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD) {
        throw UnsupportedError('Email link sign in is not supported.');
      }

      return await signInWithEmailAndPassword(
        credential.email,
        credential.password!,
      );
    } else if (credential is GoogleAuthCredential) {
      assert(app.options.authDomain != null,
          'You should provide authDomain when trying to add Google as auth provider.');

      response = (await _api.idpAuth.signInWithOAuthCredential(
        requestUri: app.options.authDomain,
        providerId: credential.providerId,
        providerIdToken: credential.idToken,
        providerAccessToken: credential.accessToken,
      ))
          .toJson();
    } else if (credential is TwitterAuthCredential) {
      response = (await _api.idpAuth.signInWithOAuthCredential(
        requestUri: app.options.authDomain,
        providerId: credential.providerId,
        providerAccessToken: credential.accessToken,
        providerSecret: credential.secret,
      ))
          .toJson();
    } else if (credential is FacebookAuthCredential) {
      response = (await _api.idpAuth.signInWithOAuthCredential(
        requestUri: app.options.authDomain,
        providerId: credential.providerId,
        providerAccessToken: credential.accessToken,
      ))
          .toJson();
    } else if (credential is OAuthCredential) {
      response = (await _api.idpAuth.signInWithOAuthCredential(
        requestUri: app.options.authDomain,
        providerId: credential.providerId,
        providerAccessToken: credential.accessToken,
        providerIdToken: credential.idToken,
        nonce: credential.rawNonce,
      ))
          .toJson();
    } else {
      throw UnsupportedError('This credential is not supported yet.');
    }

    final userData =
        await _api.userAccount.getAccountInfo(response['idToken']);

    // Map the json response to an actual user.
    final user = User(userData..addAll(response), this);

    _updateCurrentUserAndEvents(user, true);

    return UserCredential._(
      auth: this,
      credential: credential,
      additionalUserInfo: AdditionalUserInfo(
        isNewUser: response['isNewUser'] ?? false,
        providerId: credential.providerId,
        username: userData['screenName'],
        profile: {
          'displayName': userData['displayName'],
          'photoUrl': userData['photoUrl']
        },
      ),
    );
  } catch (e) {
    rethrow;
  }
}