Tell HN: Google OAuth consent screen issue could be costing you signups
179 points| Aalk4308 | 1 year ago
What's the issue?
A few months ago we (Flat.app) noticed that a meaningful fraction of signups-via-Google to our SaaS product were failing. I recently found out why, so I'm sharing this PSA for anyone facing a similar problem.
If your app supports "Sign in with Google", it's likely that new signups will fail if, on Google's OAuth consent screen, a user clicks "Continue" more than once. The error will probably be inscrutable to the user, depending on your setup, so they may just give up instead of trying again. In our case, we were losing around 15% of signups!
I encountered this issue while investigating failed signups for our product, but I've also reproduced it with other popular products including ChatGPT, Doordash, Expedia, and Snyk, so I assume it's widespread.
Some of these products use Auth0, as do we, but others don't, and they still generate an error of one kind or another.
For Auth0 specifically, the error is "You may have pressed the back button, refreshed during login, opened too many login dialogs, or there is some issue with cookies, since we couldn't find your session. Try logging in again from the application and if the problem persists please contact the administrator." The error tries to be helpful by listing potential causes, but it fails to mention the actual cause. That's because Auth0 wasn't aware of this failure mode, based on my correspondence with them.
Why does this happen?
After a user clicks "Continue" the first time, Google will respond with a 302 to the callback URL, passing along the authorization code and replaying the OAuth 2.0 state param. If the user clicks "Continue" again, Google will respond again with a 302 to the callback URL. The browser will abort the first pending request and issue a new request to the callback URL. Importantly, the state param is, as it should be, the same in both requests, and it typically incorporates a nonce (see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#name-protecting-redirect-based-f). Since the nonce will already have been consumed by the first request, the second request will be rejected.
Why would a user click "Continue" twice?
Simple: poor UX in Google's consent screen. The "Continue" button provides almost no feedback that the click was registered, and the screen provides no feedback that any requests are pending. So, some users will naturally try again, especially if they're on a slow connection.
What can Google do?
Google could disable the "Continue" button with a loading indicator after the first click. That would ensure it's not possible to click it twice, and it would provide an improved UX by showing the user that something is happening.
Google's OAuth consent screen was redesigned at some point in the past few years. Allowing "Continue" to be clicked twice, with no visible feedback, may be an unintended regression.
What can I do?
Test this in your own application. Be sure to deauthorize your app before each test run so that you get the OAuth consent screen. You can do that in your Google account's Data & privacy section.
Also, check your logs for errors to see if you're losing signups. See if you can detect this scenario and, if so, provide a better experience to users, e.g., by acknowledging what caused the error and giving them a clearer path to continue.
mnw21cam|1 year ago
rollcat|1 year ago
- You interact with a bot in a mostly-idle, public chatroom (such as !commands on Twitch)
- Bot pastes a url-shortened link that redirects you to a Google doc
- Anyone who had that document already open can now link your Twitch identity to your Google identity (which may include real name+photo)
Granted this particular vector has been open for well over a decade, it may just catch you off guard sooner or later.
afandian|1 year ago
rrauenza|1 year ago
https://support.google.com/accounts/thread/219332922/how-to-...
WarOnPrivacy|1 year ago
pappeyrome|1 year ago
chrome://settings/content/federatedIdentityApi
enable: Block sign-in prompts from identity services
See: https://issues.chromium.org/issues/343584523
extraduder_ire|1 year ago
I've seen the gmail addresses of so many twitch streamers who were capturing their screen without knowing that would happen. Most of them with addresses they'd rather not be public.
Suppafly|1 year ago
So much this, it's 100% and antipattern. It often causes me to just close out of page unless the content is actually something I really want to see. I have several google accounts associated with my gmail, so the box is often kinda big and I'm afraid I'm going to accidentally subscribe one of them to something.
varispeed|1 year ago
At least that's me on Chrome.
shrink|1 year ago
Can you share a copy of your OAuth consent screen settings? Maybe there's an option influencing this behaviour.
edit: we do not use Auth0, our Google OAuth connection is built in house.
edit edit: comparing the URLs, our flow redirects from `https://accounts.google.com/signin/oauth/id` to `https://accounts.google.com/signin/oauth/consent` after clicking "continue" whereas yours remains on `https://accounts.google.com/signin/oauth/id` before redirecting to your app so there's definitely something different in the behaviour.
Aalk4308|1 year ago
I looked through the HAR files I've captured comparing my company's app to Termly. After clicking "Continue", in both cases there's a redirect to a URL of the form https://accounts.google.com/signin/oauth/consent?as=redacted.... For my company's app, hitting that URL results in another redirect to my Auth0 tenant, whereas for Termly, hitting that URL results in HTML showing the loading indicator (no immediate redirect).
Why the difference? As you said, maybe it's something in the OAuth consent screen configuration (though there are no options I see that could explain it). Maybe it has to do with the age of the account.
Aalk4308|1 year ago
Curiously, in all other apps I tested and mentioned, I don't see the screen changing to "loading" on them. Do you?
Meantime, I'm checking the OAuth consent screen settings to see if there's anything relevant.
mritchie712|1 year ago
xyst|1 year ago
“do not add google/apple/facebook(meta)/github sign on in the first place”
Not only are we centralizing identity to entities known to shutdown accounts for vague reasons. It can introduce painful debugging issues, increased support costs, and loss of sales.
Personally, dealt with an issue where a user signed up with “Sign in with Apple” but forgot whether they provided Apple associated email address or the “ @privaterelay.appleid.com”
Also, emails sent to the private relay address would occasionally bounce… Very frustrating and time I will never get back lol
kccqzy|1 year ago
ewoodrich|1 year ago
There is a psychological effect where I dread the image of whatever half broken bespoke registration flow or inane password requirements someone came up with when I only see a "Create Account" button.
That may not make a difference for signing up for an account at like a bank or something I truly need but for say a Show HN for Yet Another Thin Layer Over GPT #372 the odds are high I'll just click back and move on with my life.
muzani|1 year ago
But websites shouldn't copy the ideal UI for Android and so on.
kroolik|1 year ago
98codes|1 year ago
immibis|1 year ago
You are getting the same callback URL twice, and the second time the request is failing. Why not instead, if the user is already authorised, let them keep their authorisation and continue by redirecting the user to the same place they would go if it was a new authorisation? This solution works if you are using a session cookie.
If you need to set new cookies upon authorisation, that won't work because the browser won't receive the new cookie before the second request. Another possibility is to cache the whole request and response for a short time in case an identical request is received. Since the whole request is identical there will be no security issues from nonce reuse.
Alternatively, you could allow nonce reuse within a small time window. I'm not familiar with the web stack enough to evaluate the security implications of this.
Aalk4308|1 year ago
adaml_623|1 year ago
What if the nonce was still valid for the second response because your server detected that the connection was dropped for the first response?
Aalk4308|1 year ago
In Auth0's case, it appears the nonce is consumed early in the handling of the callback. In my correspondence with them, I confirmed that they do see that the first request is aborted (in the form of a log), but they take no action as a consequence.
immibis|1 year ago
layer8|1 year ago
klabb3|1 year ago
stephenr|1 year ago
The answer to "what can I do" is "stop depending on a third party service that's critical for your business and essentially trivial to replace".
xyst|1 year ago
dewey|1 year ago
uncletammy|1 year ago
throwaway984393|1 year ago
[deleted]
modeless|1 year ago
loa_in_|1 year ago
> If an attacker can get the nonce they can just as easily get the access tokens after authentication, can't they?
That's not the case. A js injection would usually lead to read access on the current page but not the next one.
GermanJablo|1 year ago
I created an issue with a repro, although the maintainers moved it to discussions. It seems that the problem is with Google, but in that case I don't understand why the next-auth example works fine[2].
There are other users affected. If anyone knows how to solve this problem, I would appreciate it if you could say so.
https://github.com/nextauthjs/next-auth/discussions/11160 https://next-auth-example.vercel.app/
previousjs|1 year ago
It is not bugs per-se as every framework has them.
It is that you are utterly stuck when they do and even 100s of thumbs up on issues don't get things fixed.
Case in point: can't defer chunk scripts anymore. Hard to get good performance scores as this is untenable.
Fetch cache limit is 2Mb or something like that and enforced by Verel. You need to fork NextJS and self host it to fix.
Probably 2 or 3 other such issues I forgot as well
Any over opinionated "batteries welded" frameworks will have this issue.
Use any of the usual MVC suspects like Rails for example and you avoid being stuck. You can find fixes or swap libraries. They tend to have battle tested out such issues anyway.
aitchnyu|1 year ago
https://firebase.google.com/docs/auth/web/redirect-best-prac...
Spiwux|1 year ago
yellow_lead|1 year ago
Aalk4308|1 year ago
ndriscoll|1 year ago
The attack the nonce is meant to prevent is tricking someone into logging into the wrong account, right? The attacker can't access or guess the user's cookie to put the right nonce into the URL, so I think that should be safe?
If auth0 were going to implement this in the middle for you, then there might be some subtleties to think about with the redirect on failure unless you always send the user to a landing page. More layers of redirects make this kind of thing hard to think through. What's the purpose of auth0 for what you're doing?
This might also not work if the authorization code is not re-usable (they're not supposed to be according to the spec) and your backend already used it. If it doesn't work, you could again kick the user back to a landing page, tell them the IdP had an error, and ask them to try again. Or I suppose if you're saving the login to a backend session, then it should just work and you can ignore the error.
dangoodmanUT|1 year ago