Skip to main content

google_apple_sign_in 1.0.1 copy "google_apple_sign_in: ^1.0.1" to clipboard
google_apple_sign_in: ^1.0.1 copied to clipboard

Sign in with Google and Apple behind one interface. Returns the id token and nonce your backend or Firebase needs, and follows App Store guideline 4.8.

google_apple_sign_in #

Sign in with Google and Apple in Flutter behind one interface. You get back the id token (and, for Apple, the raw nonce) that Firebase or your own backend needs, and the buttons follow App Store guideline 4.8 for you.

final signIn = PlatformSocialSignIn(const SocialSignInConfig(
  googleClientId: 'IOS_CLIENT_ID.apps.googleusercontent.com',
  googleServerClientId: 'WEB_CLIENT_ID.apps.googleusercontent.com',
  appleSignIn: true,
));

for (final p in signIn.providers) { /* show a button per provider */ }

final credential = await signIn.signIn(SocialProvider.apple);
// credential.idToken, credential.rawNonce, credential.email, credential.displayName

It wraps google_sign_in 7 and sign_in_with_apple 8. It does not talk to any backend and does not depend on Firebase.

Why #

Getting both providers working on both platforms is mostly configuration, and the failures are quiet:

  • Google on Android returns no id token unless you pass the Web client id as serverClientId. You get SocialSignInFailure: Google returned no id token. Set googleServerClientId. instead of a null you find later.
  • Google on Android fails in release only when the SHA-1 of the Play app-signing key is not registered. You need one Android OAuth client per signing key (debug, upload, Play).
  • App Store guideline 4.8: an iOS app that offers a third-party login such as Google must also offer an equivalent privacy-focused login (data limited to name and email, email can be hidden, no tracking). Sign in with Apple is the standard way to meet it, so providers hides the Google button on iOS until Apple is configured, and a debug build tells you why.
  • Apple + Firebase needs a nonce: the SHA-256 goes to Apple, the raw value goes to Firebase. The package generates both and returns rawNonce.
  • Apple on Android works through a web flow with a Services ID and a server callback. The button is offered on Android only when appleServiceId is set.
  • Cancel is not an error: both SDKs' cancel codes become SocialSignInCancelled; everything else becomes SocialSignInFailure with the provider attached.

Install #

flutter pub add google_apple_sign_in

Supported: Android and iOS. Apple sign-in on the web works through sign_in_with_apple; Google on the web needs the button that google_sign_in renders, so signIn(SocialProvider.google) throws a SocialSignInFailure there.

The API #

SocialSignIn The interface: providers, signIn(provider), signOut(). Depend on this in your app.
PlatformSocialSignIn(config) The real implementation.
FakeSocialSignIn For tests and demo builds. Returns a made-up credential; cancel: true simulates the user backing out.
SocialSignInConfig Client ids and switches. Empty string = not set up.
SocialCredential provider, idToken, email, displayName; Apple adds authorizationCode and rawNonce.
SocialSignInCancelled / SocialSignInFailure The only two exceptions you need to catch.
try {
  final c = await signIn.signIn(SocialProvider.google);
  await backend.exchange(c.idToken);
} on SocialSignInCancelled {
  // user closed the sheet: do nothing
} on SocialSignInFailure catch (e) {
  showError('${e.provider?.name}: ${e.message}');
}

Setup: the four configurations #

You need a Google Cloud project (free) and, for Apple, a paid Apple Developer account.

1. Google on Android #

  1. Google Cloud console → APIs & Services → Credentials. Configure the OAuth consent screen first if asked.

  2. Create a Web application OAuth client. Its client id is googleServerClientId. Android needs it to return an id token.

  3. Create an Android OAuth client for each signing key, with your package name and that key's SHA-1:

    • debug: keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
    • upload key: the same command against your upload keystore, or cd android && ./gradlew signingReport
    • Play app signing: Play Console → your app → App integrity → App signing → "App signing key certificate".

    Miss the last one and sign-in works in your builds but fails for everyone who installs from Play.

  4. No google-services.json is needed for this package.

2. Google on iOS #

  1. Create an iOS OAuth client with your bundle id. Its client id is googleClientId.
  2. Add its reversed client id as a URL scheme in ios/Runner/Info.plist:
<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>com.googleusercontent.apps.YOUR_IOS_CLIENT_ID</string>
    </array>
  </dict>
</array>
  1. Also set googleServerClientId (the Web client from step 1.2) if your backend verifies the token, so the token's audience is the same on both platforms.
  2. Remember 4.8: the Google button appears on iOS only once Apple is set up as well.

3. Apple on iOS #

  1. Apple Developer → Certificates, Identifiers & Profiles → Identifiers → your App ID → enable Sign in with Apple.
  2. Xcode → Runner target → Signing & Capabilities → + Capability → Sign in with Apple.
  3. Set appleSignIn: true. Leave it false until both steps are done: a button on an App ID without the capability fails on every tap.

Apple sends the user's name and email only on the first sign-in for that Apple ID. Save them then; later sign-ins return displayName == null.

4. Apple on Android #

Android has no native Apple sign-in, so sign_in_with_apple opens a web flow:

  1. Apple Developer → Identifiers → Services IDs → create one (for example com.example.app.signin). This is appleServiceId.
  2. Configure it for Sign in with Apple: primary App ID, your domain, and a Return URL on your server (for example https://api.example.com/auth/apple/callback). This is appleRedirectUri.
  3. That endpoint receives Apple's form POST and must redirect back into the app: intent://callback?<the posted fields as a query string>#Intent;package=YOUR.PACKAGE.NAME;scheme=signinwithapple;end
  4. Add the callback activity to android/app/src/main/AndroidManifest.xml, inside <application>:
<activity
    android:name="com.aboutyou.dart_packages.sign_in_with_apple.SignInWithAppleCallback"
    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="signinwithapple" android:path="/callback" />
  </intent-filter>
</activity>
  1. Set appleSignIn: true and appleServiceId / appleRedirectUri.

Using the credential #

With Firebase Auth #

final c = await signIn.signIn(provider);
final AuthCredential cred = switch (c.provider) {
  SocialProvider.google => GoogleAuthProvider.credential(idToken: c.idToken),
  SocialProvider.apple => OAuthProvider('apple.com').credential(
      idToken: c.idToken,
      rawNonce: c.rawNonce,
      accessToken: c.authorizationCode,
    ),
};
await FirebaseAuth.instance.signInWithCredential(cred);

Enable Google and Apple under Firebase console → Authentication → Sign-in method. For Apple, rawNonce is required.

With your own backend #

Send idToken (and for Apple rawNonce) and verify the JWT on the server. Do not trust email / displayName from the client.

  • Signature: Google's keys at https://www.googleapis.com/oauth2/v3/certs, Apple's at https://appleid.apple.com/auth/keys.
  • iss: https://accounts.google.com (or accounts.google.com) / https://appleid.apple.com.
  • aud: your Web client id for Google; your bundle id (iOS) or Services ID (Android) for Apple.
  • exp in the future; for Apple, the nonce claim equals SHA-256 of rawNonce.
  • Key users on sub, not email. Apple may give a private relay address.

Testing #

Depend on SocialSignIn, not on PlatformSocialSignIn, and pass FakeSocialSignIn in tests:

final fake = FakeSocialSignIn();
await myLoginController(fake).tapGoogle();
expect(fake.calls, 1);

fake.cancel = true; // the next signIn throws SocialSignInCancelled

SocialSignInConfig.offered(applePlatform: true) lets you test which buttons iOS would show without a device.

FAQ #

Do I need Firebase? No. The package returns tokens; Firebase is one way to use them.

Why is the Google button missing on my iPhone? App Store guideline 4.8 asks for an equivalent privacy-focused login next to Google, and this package uses Sign in with Apple for that. Configure it and set appleSignIn: true; a debug build prints this in the console.

Google works in debug but not from the Play Store. Register the SHA-1 of the Play app-signing key as another Android OAuth client (setup step 1.3).

Google returns no id token on Android. Set googleServerClientId to the Web client id, not the Android one.

Apple returns no name on the second sign-in. That is Apple's behavior. Store the name the first time. To test the first-time flow again, remove the app under Settings → Apple ID → Sign-In & Security → Sign in with Apple.

About #

Extracted from the coderqh Flutter app templates, where it backs the Google and Apple buttons in every app. Issues and pull requests are welcome.

MIT licensed.

1
likes
160
points
0
downloads

Documentation

API reference

Publisher

verified publishercoderqh.com

Weekly Downloads

Sign in with Google and Apple behind one interface. Returns the id token and nonce your backend or Firebase needs, and follows App Store guideline 4.8.

Homepage
Repository (GitHub)
View/report issues

Topics

#authentication #google-sign-in #apple-sign-in #login #firebase

License

MIT (license)

Dependencies

crypto, flutter, google_sign_in, sign_in_with_apple

More

Packages that depend on google_apple_sign_in