Flutter Google Login: No Firebase Needed!
Flutter Google Login: No Firebase Needed!
Hey there, Flutter developers! Ever wanted to integrate Google Sign-In into your awesome app without the hassle of setting up Firebase? Well, you’ve come to the right place, guys! It’s totally possible, and honestly, it’s not as scary as it might sound. We’re going to dive deep into how you can achieve seamless Google authentication right within your Flutter project, keeping things lean and mean.
Table of Contents
Why Go Firebase-Free for Google Sign-In?
Now, you might be wondering, “Why would I skip Firebase?” Firebase is fantastic, no doubt. It simplifies a ton of backend tasks. However, sometimes you might have specific reasons to avoid it. Maybe your project is super lightweight and you don’t need all the bells and whistles Firebase offers. Perhaps you’re already using a different backend solution and want to keep your tech stack consistent. Or, maybe you just want to understand the nitty-gritty of authentication without an abstraction layer. Whatever your reason, going Firebase-free for Google Sign-In is a perfectly valid and achievable goal. It gives you more control and can sometimes lead to a smaller app size. Plus, learning how to do it manually builds a stronger foundation for understanding authentication flows in general.
Setting Up Your Google Cloud Project
Before we write a single line of Flutter code, the first crucial step is to get your Google Cloud project squared away. This is where you’ll register your application with Google and obtain the necessary credentials. Think of it as getting your app an official ID from Google. You’ll need to navigate to the
Google Cloud Console
. If you don’t have a project yet, create one. Once you’re in your project, you’ll need to enable the
Google Sign-In API
. Look for “APIs & Services” in the menu, then “Library”, and search for “Google Sign-In API” or “Identity Platform API” (the terminology can sometimes shift, but you’re looking for the service that handles user authentication with Google accounts). After enabling it, head over to “Credentials”. Here’s where the magic happens. You’ll need to create an
OAuth 2.0 Client ID
.
Crucially
, you’ll need to specify the application type. For Flutter, this will typically be an
Android app
and an
iOS app
. For Android, you’ll need to provide your app’s package name and the SHA-1 signing certificate fingerprint. For iOS, you’ll need your app’s bundle ID. Getting these details right is
super
important for the authentication to work smoothly. Don’t forget to also configure the
Authorized redirect URIs
. This is the URL that Google will redirect your user back to after they’ve successfully authenticated. For local development, you’ll often use a placeholder like
com.googleusercontent.apps.<YOUR_CLIENT_ID>://oauth2redirect
or similar, but you’ll need to configure this correctly for production environments, especially if you’re using web-based authentication flows. This initial setup might seem a bit daunting, but taking it step-by-step ensures you have the correct keys and configurations needed for your Flutter app to communicate securely with Google’s authentication servers. It’s the bedrock of our
Flutter Google login without Firebase
journey.
Leveraging the
google_sign_in
Package
Okay, so we’ve got our Google Cloud project all set up. Now, let’s talk about the hero of our story in the Flutter world: the
google_sign_in
package. This fantastic plugin is your gateway to integrating Google Sign-In into your Flutter app without relying on Firebase’s authentication services. It handles a lot of the platform-specific boilerplate code for you, making the process much smoother. First things first, you’ll need to add it to your
pubspec.yaml
file. Just pop this line under
dependencies
:
google_sign_in:
^6.0.0 # Or the latest version
After adding it, run
flutter pub get
to fetch the package. Now, the real fun begins with the configuration. For Android, you need to add your
Google Sign-In configuration
to your
android/app/src/main/res/values/strings.xml
file. This involves adding a
client_id
tag with the value you obtained from the Google Cloud Console. It should look something like this:
<resources>
<string name="app_name">YourAppName</string>
<string name="google_client_id">YOUR_WEB_CLIENT_ID.apps.googleusercontent.com</string>
</resources>
Important Note: For Android, you’ll use the Web application client ID you created in the Google Cloud Console, even though it’s for a mobile app. This is a common point of confusion, but it’s how Google’s SDK is designed to work for mobile clients when not using Firebase.
For iOS, the setup involves a few more steps. You need to add your
iOS bundle ID
to the Google Cloud Console configuration. Then, in your Flutter project, you’ll need to configure your
Info.plist
file (located at
ios/Runner/Info.plist
). You’ll add a
CFBundleURLTypes
array, and within that, a
URL Schemes
item that corresponds to your Google client ID. It typically looks like this:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>com.googleusercontent.apps.YOUR_WEB_CLIENT_ID</string>
<key>CFBundleURLSchemes</key>
<array>
<string>com.googleusercontent.apps.YOUR_WEB_CLIENT_ID</string>
</array>
</dict>
</array>
This
CFBundleURLName
and
CFBundleURLSchemes
should match the
com.googleusercontent.apps.<YOUR_CLIENT_ID>
format. You also need to add the
GoogleService-Info.plist
file to your iOS project, but since we are not using Firebase, we will skip this step. Instead, the
google_sign_in
package uses the client ID directly, which we’ve configured in the
Info.plist
.
This configuration might seem a bit fiddly, but it’s essential for the
google_sign_in
package to correctly identify your app and initiate the Google Sign-In flow. Getting these details spot-on ensures that when you try to sign in, Google knows exactly which application is requesting the authentication.
Implementing the Sign-In Flow in Flutter
With the package added and configurations in place, let’s get to the fun part: writing the code to handle the actual
Google Sign-In flow
in your Flutter app! This involves a few key steps. First, you need to instantiate the
GoogleSignIn
object. It’s a good practice to define the scopes you want to request from the user. Scopes determine what information your app can access from the user’s Google account. For basic sign-in, requesting
email
and
profile
is usually sufficient. You can also request
openid
and
https://www.googleapis.com/auth/userinfo.email
, and
https://www.googleapis.com/auth/userinfo.profile
. Here’s how you might set up the
GoogleSignIn
instance:
final GoogleSignIn _googleSignIn = GoogleSignIn(
scopes: <String>[
'email',
'profile',
],
);
Next, you’ll need a function to trigger the sign-in process. This function will call the
signIn()
method on your
_googleSignIn
instance. This method will prompt the user with the Google Sign-In dialog. If the user successfully signs in, it returns a
GoogleSignInAccount
object, which contains information about the authenticated user, like their email, display name, and photo URL. If there’s an error or the user cancels, it might return
null
or throw an exception, so error handling is key!
Future<void> _handleGoogleSignIn() async {
try {
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
if (googleUser != null) {
// User signed in successfully!
// You can access user details like:
// googleUser.email
// googleUser.displayName
// googleUser.photoUrl
print('Signed in as ${googleUser.displayName}');
// Now you can proceed to authenticate with your backend or manage the user session.
} else {
// User canceled the sign-in
print('Google sign-in cancelled');
}
} catch (error) {
print('Error signing in with Google: $error');
// Handle the error appropriately, e.g., show a message to the user.
}
}
You’ll also want to consider handling the sign-out process. This is straightforward using the
signOut()
method:
Future<void> _handleGoogleSignOut() async {
await _googleSignIn.signOut();
print('User signed out');
// Update your app's UI to reflect the signed-out state.
}
And what about checking if a user is
already
signed in when the app starts? The
isSignedIn()
method is your friend here:
Future<void> checkSignInStatus() async {
bool isSignedIn = await _googleSignIn.isSignedIn();
if (isSignedIn) {
final GoogleSignInAccount? currentUser = await _googleSignIn.signInSilently();
if (currentUser != null) {
print('User already signed in: ${currentUser.displayName}');
// Automatically log them in or show their profile.
}
}
}
Remember to call
checkSignInStatus()
when your app initializes to provide a seamless experience for returning users. This direct interaction with the
google_sign_in
package allows you to manage the authentication state entirely within your Flutter app, giving you full control over the user experience without needing any Firebase backend infrastructure for the sign-in process itself. This is the core of implementing
Flutter Google login without Firebase
.
Handling User Data and Tokens
Once a user successfully signs in with Google using the
google_sign_in
package, you receive a
GoogleSignInAccount
object. This object contains valuable information like the user’s email, display name, and profile picture URL. But what do you do with this information, especially if you’re not using Firebase Authentication to manage user sessions?
This is where you need to bridge the gap between Google’s authentication and your own backend or app-state management. You have a couple of primary options:
-
Directly use Google User Info: For simpler apps, you might just store the basic profile information locally (e.g., using
shared_preferencesor a local database) to display the user’s name and avatar. However, this doesn’t provide a secure way to identify the user across sessions or on your backend. -
Exchange Google Token for Your Own Token: This is the most common and recommended approach for secure applications. When a user signs in via Google, you can obtain an ID token or an access token from the
GoogleSignInAccount. The ID token is a JWT (JSON Web Token) that contains verified information about the user. You can send this ID token to your own backend server. Your backend can then verify the token’s authenticity and signature using Google’s public keys. If valid, your backend can issue its own session token (like a JWT) to your Flutter app. Your app then uses this custom token for subsequent requests to your backend, ensuring that only authenticated users can access protected resources. This decouples your authentication from Google after the initial sign-in and gives you full control over your application’s security.
Here’s a simplified look at how you might get the ID token:
Future<void> _handleGoogleSignIn() async {
try {
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
if (googleUser != null) {
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
final String? idToken = googleAuth.idToken;
// final String? accessToken = googleAuth.accessToken; // You might need this too
print('User signed in: ${googleUser.displayName}');
print('ID Token: $idToken');
// TODO: Send the idToken to your backend for verification and session creation.
// Example: await sendTokenToMyBackend(idToken!)
} else {
print('Google sign-in cancelled');
}
} catch (error) {
print('Error signing in with Google: $error');
}
}
On your backend, you’ll need a library to verify the Google ID token. Libraries like
google-auth-library
(Node.js),
google-auth
(Python), or similar for other languages can help with this. The process typically involves fetching Google’s public keys, decoding the JWT, and verifying its signature and claims (like
iss
for issuer and
aud
for audience, which should match your client ID).
By handling the token exchange, you effectively implement secure user authentication in your Flutter app without relying on Firebase. You gain the benefits of Google’s robust authentication infrastructure while maintaining complete control over your application’s user management and security policies. This approach is robust, scalable, and gives you the flexibility to integrate with any backend system.
Troubleshooting Common Issues
Even with the best intentions, you might run into a few snags when setting up
Flutter Google login without Firebase
. Don’t sweat it, guys! These are common hurdles, and we can usually iron them out. One of the most frequent problems is related to configuration errors in the Google Cloud Console or within your app’s native files (
strings.xml
for Android,
Info.plist
for iOS).
-
Incorrect Client ID:
Double-check that the client ID you’ve entered in your
strings.xml(for Android) orInfo.plist(for iOS) exactly matches the one generated in the Google Cloud Console. For Android, remember to use the Web application client ID. Ensure there are no typos or extra spaces. - SHA-1 Fingerprint Mismatch (Android): If your Android sign-in isn’t working, the SHA-1 fingerprint is often the culprit. Make sure you’re using the correct one for your debug keystore (if testing locally) or your release keystore (for production builds). You can get your debug SHA-1 by running `keytool -list -v -keystore