From Extreme Confusion... to Clarity
With so many moving parts — Google Cloud, Clerk, iOS configuration, and my own app — it’s incredibly easy to get lost when trying to understand how OAuth actually works.
After several days of questioning, experimenting, breaking things, and staying persistent, I finally got everything working — a fully functioning demo 😃
Even after years of being a developer, this wasn’t something that came naturally or instantly. And that’s exactly why I’m writing this.
1) Client ID + Client Secret: the introductory business card (and proof of identity)
Think of Google and Clerk like two companies.
- Client ID is your app’s “business card” (public identity).
- Client Secret is your app’s “sealed letter / private stamp” (private proof).
When you paste these from Google to into Clerk, you’re basically saying:
“Clerk, when my app says ‘I’m the Google app you’re expecting’, here’s the official identity card and the private proof so you can trust it’s really me.”
Why it matters: without this “formal introduction,” Clerk can’t confidently talk to Google as your app, and Google won’t know which OAuth app configuration rules to apply.
2) Redirect URL must match: the relay race baton handoff
OAuth is a relay race:
- Your app sends the runner to Google (login screen).
- Google finishes their segment (user authenticates).
- Then Google must hand the baton back to the correct next runner.
That “handoff point” is the Redirect URL.
So the rule is:
The redirect URL Google is allowed to hand the baton to must match what your app/Clerk expects.
That’s why you check both dashboards:
- In Google Cloud Console: “These are the allowed handoff addresses.”
- In Clerk: “This is the handoff address I’m expecting.”
If they don’t match, Google refuses the handoff (because it could be a security risk).
3) iOS must understand the redirect URL: Google → iOS → Your App
On mobile, the baton doesn’t go straight back into your app automatically.
The flow is really:
Google → iOS (system) → Your App
So iOS needs to know:
- “When I see a URL that looks like this, which installed app should receive it?”
That’s what these do:
-
app.jsonscheme: registers the “special address format” your app owns (like claiming a mailbox). - Expo Linking: helps your app listen for and parse the incoming redirect so it can resume the login flow.
In human terms:
app.json tells iOS which app owns that URL, and Linking helps your app open the envelope and read what Google sent back.
4) Secure Store: where the baton gets locked up after the race
After OAuth succeeds, you end up with something sensitive stored on the phone (commonly session tokens / refresh tokens, depending on the setup).
Here’s the key idea:
- A mobile app is not a safe place to keep secrets in plain storage.
- Tokens act like “proof you’re logged in.”
- If stolen, they can be reused like a copied keycard.
So you use Secure Store as the phone’s built-in safe:
- iOS Keychain / Android Keystore under the hood.
- Encrypted + protected by the OS.
Why it usually needs a rebuild:
- Secure Store is a native capability.
- If your project isn’t already including it in the native build (or you change native config), you need a new native build for it to be available properly.
In story form:
Once your app receives the baton (tokens), you don’t leave it on the table. You put it in the hotel safe (Secure Store), so nobody can copy it while you’re not looking.
One-line summary
Client ID/Secret = who you are (formal introduction)
Redirect URL = where the baton goes (handoff point)
Scheme/Linking = how iOS routes it (Google → iOS → app)
Secure Store = where you lock the result (tokens in a safe)
Code to follow…
Next I will paste the React Native code here… please watch this space!
Top comments (0)