Expo Client Deep Link Security: Preventing Session Hijacking

I understand the typical sign-in flow when using the Expo Client looks like this: 1. A user visits /sign-in in their browser. 2. They are redirected to accounts.google.com. 3. After successful authentication, they are sent back to /callback. 4. The /callback endpoint uses a deep link to return to the mobile app and deliver the session cookie. My concern is that anyone can register the same deep link. For example, if I run example-service.com and register example-service:// in my own app, couldn’t my app hijack the callback and steal the session cookie from the legitimate app? * Am I misunderstanding something about how deep links work? * Is there a built-in mechanism to ensure only the genuine app can receive the cookie? * How do you prevent malicious or clone apps from intercepting the Expo Client’s authentication flow? Thanks in advance for any insights!
10 Replies
Ping
Ping5mo ago
Hey yes this is a valid concern. The alternative is to use Universal Links with expo, but after talking to Bekacru apparently it has it's own problems too. He says he remembers discussing this with Pilcrow from lucia auth about this. Even though app schemes are technically insecure, they’re still the most practical option for now.
kingitaj
kingitaj5mo ago
I believe Stytch (the auth provider we are migrating from) solves this with PKCE for OAuth and MagickLinks. - https://stytch.com/docs/guides/magic-links/email-magic-links/adding-pkce - https://stytch.com/docs/guides/oauth/adding-pkce
IETF Datatracker
RFC 7636: Proof Key for Code Exchange by OAuth Public Clients
OAuth 2.0 public clients utilizing the Authorization Code Grant are susceptible to the authorization code interception attack. This specification describes the attack as well as a technique to mitigate against the threat through the use of Proof Key for Code Exchange (PKCE, pronounced "pixy").
Adding PKCE to a Magic Link flow | Stytch Consumer authentication
Learn how to add Proof Key for Code Exchange (PKCE) to your email magic links to make your login flow more secure. Follow our step-by-step guide.
Adding PKCE to an OAuth flow | Stytch Consumer authentication
Learn how to add PKCE (Proof Key for Code Exchange) to your OAuth flow for enhanced security and protection against authorization code interception.
No description
kukuku
kukukuOP5mo ago
Thank you! Do you know how to implement PKCE in Better Auth’s authentication flow?
Ping
Ping5mo ago
We do support PKCE. It does require the OAuth provider to support PKCE though, since not all do. For example Google supports it.
kingitaj
kingitaj5mo ago
Ahh interesting. Might be worth adding this info to the docs.
Ping
Ping5mo ago
@kingitaj
No description
kukuku
kukukuOP5mo ago
I agree that Better Auth uses PKCE when redirecting to accounts.google.com. However, what I’m really concerned about is guaranteeing secure communication between the browser and the app. Currently, the flow is: 1. The app includes a code_challenge in the query parameters when sending the user to accounts.google.com. 2. After Google redirects back to /callback, the server uses the code_verifier to validate the request and improve security. But the Expo Client adds another step: a deep-link redirect from the browser back into the app. Instead of sending the session cookie in the deep-link URL, I think it would be safer to: * Include the code_challenge when the app first opens the browser, * Have Google return only the authorization code on redirect, * And then, once the app receives that code, use the code_verifier to exchange it for a token on the server side. Would that approach better protect against a malicious app intercepting the deep link?
Ping
Ping5mo ago
Developing your own expo plugin. From what I know, they considered the options between something like Deep links and Universal Links and came to the conclusion of Deep links for practical reasons. Our expo plugin is really small, you can copy it and just change the code out for Universal Links instead, but there is more work required such as setting up verification files on a webserver and potentially other things. This is as far as I know regarding Expo, but I recommend doing some research on how to setup Universal Links and then just replace our plugin
FalconiZzare
FalconiZzare5mo ago
Hey this might not be an universal solution to the problem here, however, using google credentials manager i somehow reduced the risk of deep linking. My app doesn't go into browser. Rather collects the id token from google and calls the api of BA However, this is only for google, discord and fb or other oauth providers still need deeplinking i guess.
kukuku
kukukuOP5mo ago
Thanks! I’ll try building the client myself. Could you explain in more detail why you chose Deep Links? Android’s documentation also highlights the advantages of Universal Links (App Links).

Did you find this page helpful?