To this day I have no idea how one should handle client secrets in (F)OSS applications, and I'm often wondering if I'm the only one. I guess what this text says in 4.13 is "just don't put it somewhere for anyone to see", which means that the only solution is to make the id and secret configurable and let the user register the application with its OAuth provider, which of course most users wouldn't know how to do. As a result, applications like Thunderbird simply put the secret in the code with a comment above it "please don't copy these values for your own application". I really don't mean to shame Mozilla, what else are they supposed to do?
It's not just an open source problem. It's fairly trivial to scrape the keys out of a lot of closed source applications. When Twitter first mandated OAuth, I was able to grep a key right out of the apk of their native Android client.
OAuth with client secrets is fundamentally unsuitable for desktop and mobile applications, but that hasn't stopped virtually every major implementor from using it that way. The people who wrote the spec were too busy congratulating each other and downplaying concerns to seriously engage with this issue until it was much too late to do anything about it.
It remains a deeply broken standard, and the people who were responsible for it at an early stage are entirely to blame. Several of them have removed their names from the spec, but I'll not forget the role they played in shouting down critics who raised concerns about this very issue.
Much of the deployment of OAuth2 was a shitshow, because early on, there was a huge debate about OAuth1 vs OAuth2, and the concepts and terminology used in the OAuth2 spec exceeded the mental load of people who were simply looking for a quickstart to some API. Docs by various providers either adopted the OAuth2 terminology wholesale without sufficiently explaining the new concepts and the best practices, or they simplified the client registration to just a few fields and offered no guidance as to make use of them in your app.
The spec has been clear from the start that there are clients that can protect their secrets, and ones that can't [1]. Here's a choice quote: "A native application is a public client installed and executed on the device used by the resource owner. Protocol data and credentials are accessible to the resource owner. It is assumed that any client authentication credentials included in the application can be extracted." Unfortunately, much of the rest of the spec is a bit like a playing puzzle, where reading it in one sitting doesn't actually build your understanding, and you have to constantly cross-reference various sections to construct a complete picture of the process the spec is trying to set.
It look a long time for people's familiarity with the spec to grow, and for providers and clients to improve in quality and adherence to the ideas and text of the spec.
If it's a FOSS clientside application, like a mobile or desktop app, it's a public application and the client secret doesn't really apply. If it's a serverside application, a web app, then every instance of the app will be registered independently with auth servers, and will manage their own client secrets.
From my understanding the best practice for applications that run on clients' machines (Javascript SPA, mobile app, email client) is to not use a client secret at all. Just use a client id and assume that anyone can reuse it.
Of course that is if the OAuth provider allows it.
"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")."
At the end of the day, no matter what the grant, if you store the access tokens (or refresh tokens) in the browser running an SPA, it is vulnerable to an XSS attack, right?
Thanks. I am not wholly convinced of the benefits of releases for a project of this scale, I suspect most will just reimplement the moving parts in their own code for a variety of (usually NIH) reasons.
With PKCE you can use the authorzation_code grant flow. The whole issue with SPAs and the authorization_code grant flow isn't the presence or absence of middleware; rather, it's the lack of a confidential client. PKCE gets around the requirement for a client to securely store it's secret.
> Of course that is if the OAuth provider allows it.
That's the catch. Last time I checked, at least Google didn't. So how can you write a (F)OSS email application for accessing GMail via OAuth2, without putting the secrets into the code (which Google also forbids)?
In this situation, their guidance says to embed the secret, because in this context it's obviously not a secret. Here's the current page [1]; here's the earliest Archive.org snapshot of its one-earlier predecessor page from 2015 [2] -- the advice has been consistent.
No, Google is not consistent in the slightest, because their terms of service directly contradict this statement:
"Developer credentials (such as passwords, keys, and client IDs) are intended to be used by you and identify your API Client. You will keep your credentials confidential and make reasonable efforts to prevent and discourage other API Clients from using your credentials. Developer credentials may not be embedded in open source projects."
"The process results in a client ID and, in some cases, a client secret, which you embed in the source code of your application. (In this context, the client secret is obviously not treated as a secret.)"[0]
You would not embed the client secret to any application unless you are open for public to see and use the secret (most likely not for applications you distribute to public domain).