Google Sign-In Works in Debug but Fails in Production on Android? Check This Hidden SHA-1
DEV Community

Google Sign-In Works in Debug but Fails in Production on Android? Check This Hidden SHA-1

Google Sign-In worked on my development build. It worked on my preview build. On the version Google Play delivered to real testers, tapping "Sign in with Google" did absolutely nothing - no account picker, no error message, no crash. Just a button that did nothing. It took me several days to find. The answer turned out to be a fingerprint that Play Console doesn't show you anymore. If you're here from a search, the short version is below. TL;DR - the fix If your app uses Play App Signing and you've opted into Quantum-ready app signing (beta), the SHA-1 fingerprint buttons on Play Console's App signing page are not the certificate that signs your app. - Go to Play Console โ†’ Protect with Play โ†’ Play Store protection โ†’ Manage Play app signing - Click Download certificates (not the SHA-1 fingerprint buttons) - You'll get three files. The one you need is deployment_cert.der - Get its SHA-1 fingerprint (commands below) - Put that fingerprint in your Android OAuth client in Google Cloud Console No rebuild needed. Mine started working within minutes. What "Google Sign-In is broken" actually looked like Nothing. That's the hard part. On modern Android, Sign in with Google runs through a system component called Credential Manager. When it can't complete a sign-in, it hands your app back a result that means "cancelled." Here's the code in the library I use: } catch (e: GetCredentialCancellationException) { OneTapResponse.cancelled() } catch (e: NoCredentialException) { OneTapResponse.noSavedCredential() } The problem: "cancelled" is also what you get when a user swipes the dialog away. Android uses one bucket for all of these: - the user genuinely dismissed the dialog - your app isn't registered properly with Google - your app's security certificate doesn't match what Google expects - your OAuth consent screen is still in "Testing" mode and this person isn't on the tester list No error code. No message. Nothing to look up. And it only happens in the version you can't easily debug - the one Google Play installed on someone else's phone. Plain English: what a "signing certificate" is and why it matters Skip this if you already know. It's the core of the bug, so it's worth being clear. Every Android app is digitally signed - think of it as a tamper-proof wax seal stamped onto the app file. The seal proves the app came from you and hasn't been modified. A SHA-1 fingerprint is just a short, unique ID for that seal. It looks like this: 88:93:67:BB:FA:76:AC:40:3E:1D:AC:E2:9B:7D:2A:C0:45:7E:D1:BF When your app asks Google "please sign this person in," Google checks two things: - Is this app's package name registered with me? (e.g. com.example.myapp ) - Does the app's seal match the fingerprint I have on file? If either answer is no, Google refuses - and on Android, that refusal comes back as "cancelled." So a wrong fingerprint looks exactly like a user changing their mind. The twist: Google Play re-seals your app Here's what trips up most people, and it's worth understanding even if your bug turns out to be something else. When you upload your app to Google Play, you sign it with your upload key. Play then removes your seal and applies its own before sending the app to users. This is a feature called Play App Signing, and it exists so that losing your own key doesn't lock you out of updating your app forever. The consequence: the app on a user's phone has a different fingerprint than the file you uploaded. So you need to register both fingerprints with Google: - your upload key fingerprint (for builds you install directly, e.g. from a CI service) - Play's app signing key fingerprint (for everything from the Play Store) Register only the first, and every Play Store install fails while every local install works perfectly. That is the classic version of this bug. I checked the obvious thing. It looked correct. So naturally, that's where I looked first. I opened Google Cloud Console. The Android OAuth client had the right package name. It had a SHA-1 fingerprint copied straight from Play Console's app signing page. The consent screen was published to production. No unusual permissions requested. Everything matched. I concluded the fingerprint theory was dead and started investigating the user's Google account on the device instead. That was wrong, and it cost me another day. My mistake was simple: I was comparing a field in one console against a field in another console and trusting both. Neither of them described the app sitting on the phone. The breakthrough: stop reading the console, read the phone The console tells you what you configured. The phone tells you what's true. Google checks the certificate of the app that's actually installed, so that's the thing to measure. So I plugged in the test phone, pulled the installed app off it, and read its fingerprint directly. (Full step-by-step is further down - it's optional, and you probably won't need it.) Out came: 88:93:67:BB:FA:76:AC:40:3E:1D:AC:E2:9B:7D:2A:C0:45:7E:D1:BF That matched neither the fingerprint registered in Google Cloud nor my upload key. A third fingerprint I had never seen before. The real cause: Quantum-ready app signing (beta) Back in Play Console, there was a small badge on the app signing page I'd never paid attention to: Quantum-ready (beta). Quantum-ready app signing is Google preparing for a future where today's encryption can be broken by quantum computers. If you opt in, your app gets a hybrid key - a traditional ("classical") half and a new post-quantum half. It also quietly changes the page. Where Play Console used to show plain text rows - MD5, SHA-1, SHA-256 of your app signing certificate - it now shows two buttons instead: Classical key and Post-quantum cryptography key. Neither button gives you the certificate that signs your app. Click Download certificates and you get three files: | File | What it actually is | |---|---| deployment_cert.der | The certificate Play uses to seal your app. This is the one to register. | hybrid_classical_cert.der | Classical half of the quantum-ready pair - what the SHA-1 button copies | hybrid_pqc_cert.der | Post-quantum half - also not it | The deployment certificate - the ordinary Play App Signing key that has been there all along - has no fingerprint button on that page at all. I had dutifully copied the only SHA-1 the page offered me. It was never going to work. Fixing it, step by step - Play Console โ†’ Protect with Play โ†’ Play Store protection โ†’ Manage Play app signing - Click Download certificates and unzip. Find deployment_cert.der - Read its SHA-1 fingerprint (see the next section) - Google Cloud Console โ†’ APIs & Services โ†’ Credentials - Open your Android OAuth client, or create one (type Android, package name = your app's package) - Paste the fingerprint into SHA-1 certificate fingerprint. Save - Wait a few minutes, then test on a Play Store build While you're there, create a second Android OAuth client with your upload key fingerprint, so builds you install directly also work. Each client holds exactly one fingerprint, so you need one per certificate. Three ways to read a .der fingerprint A certificate's SHA-1 fingerprint is simply a SHA-1 hash of the certificate file itself. So you don't need any Android tooling at all. Windows PowerShell - nothing to install, and it formats the result with colons exactly the way Google Cloud wants: $c = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("deployment_cert.der") $c.Thumbprint -replace '(..)(?!$)','$1:' Windows, even shorter - certutil ships with Windows (output has no colons; Google Cloud accepts it either way): certutil -hashfile deployment_cert.der SHA1 macOS / Linux / anywhere with a JDK or OpenSSL: keytool -printcert -file deployment_cert.der # or openssl x509 -inform DER -in deployment_cert.der -noout -fingerprint -sha1 A genuine Play App Signing certificate shows CN=Android, O=Google Inc. as its owner. That's a good sanity check that you grabbed the right file. Optional: prove it by reading the app on the phone You probably don't need this section. If registering deployment_cert.der 's fingerprint fixed your sign-in, you're done - close the tab. Do this when the fix didn't work, or when you want hard proof of which certificate is on a device before you change anything. It's the step that ended a week of guessing for me, and it works on any Android phone with any app. Step 1 - Get adb adb (Android Debug Bridge) is the tool that talks to a connected phone. You do not need Android Studio. - Download SDK Platform-Tools for your OS: developer.android.com/tools/releases/platform-tools - Unzip it anywhere - a platform-tools folder withadb inside - Either add that folder to your PATH , or just runadb with its full path Quick check that it runs: adb version # Android Debug Bridge version 1.0.41 macOS users can alternatively brew install --cask android-platform-tools . Step 2 - Turn on USB debugging on the phone - Settings โ†’ About phone โ†’ tap Build number seven times. You'll see "You are now a developer" - Settings โ†’ System โ†’ Developer options โ†’ turn on USB debugging - Plug the phone into your computer with a USB cable - Change the USB mode to File transfer / MTP (not "Charging only") - on some phones the debugging prompt won't appear otherwise - A dialog appears on the phone: "Allow USB debugging?" โ†’ tick Always allow from this computer โ†’ Allow Confirm the computer can see it: adb devices -l # List of devices attached # 95QW4TIFNRIBCAR8 device product:... model:... If it says unauthorized , you missed the prompt on the phone. If the list is empty, try a different cable - plenty of USB cables are charge-only. Step 3 - Confirm you're testing the Play Store build This matters. A sideloaded build carries a different certificate, and testing the wrong one sends you down the wrong path. adb shell pm list packages -i | grep com.example.myapp Look at the installer= value: - installer=com.android.vending โ†’ installed by the Play Store โœ… this is wha

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.