node.jsoauth-2.0google-oauthgoogle-contacts-api

Is a Client Secret Required for Google OAuth 2.0 using the PKCE Authorization Flow? Should I Expose the Client Secret Publicly?


I run an open-source app that runs in a macOS environment. What I want to do is implement Google Contacts syncing to it, so I've implemented the OAuth 2.0 "token" (implicit) authorization flow so users can consent to the app accessing their contacts. The problem with that flow is that it doesn't allow me to get a refresh token to use for incremental/scheduled syncing without the user's consent.

After researching it some more, I found that in order to get the refresh token, I need to implement the authorization "code" flow, which will return a code in the consent callback and then I can use that code to get the refresh token and access token. Albeit, providing a client secret. The problem with this flow is that I need to provide a client secret. Since this is an open-source app, I'm hesitant to add my client secret directly to the codebase. Especially since the credentials give access to a consent app that also has both read and edit permissions to the Google Cloud Platform.

After some more research, I found that there is a PKCE flow that can be added to the authorization "code" flow, and I was under the impression that I would not be required to provide a client secret using this flow. Instead, I should be able to provide a code_challenge when generating the initial OAuth URL, and then it can be used later to verify the request. However, even after implementing the code challenge (PKCE) into the flow, I still receive the following error when trying to get the access token & refresh token using the returned "code" from the callback after the consent flow.

The error I'm receiving is, "client_secret" is missing. But I was under the impression that the PKCE flow did not require a client secret... So I have a few questions that I was not able to get a definite answer to when searching SO:

  1. Is it safe to expose the client secret publicly?
    • I've always assumed not, but I can't seem to get this flow working otherwise.
    • I've seen other open-source projects expose the client secret, but their consent was for less sensitive scopes
  2. Am I understanding correctly that I shouldn't need the client secret when using the Authorization Code flow w/ PKCE?
    • Or do I still need the client secret, and the PKCE (code challenge) stuff is just an additional layer of security?
  3. Is there a different flow/process I should be using where I do not need to expose my client secret, but still allows me to get a refresh token?

I know that Google allows credentials to be created for UWP, iOS, or Android, and I think that those allow the authorization code flow without a client secret, but only because they are linked to a specific app/store ID on the respective platforms.

I've also already seen this SO article as well as this SO article, but I didn't feel that it answered my question or provided a good solution to the issue I'm facing.

Is the only route to store the client secret in the public source code? Is that even safe? Any help is greatly appreciated!

Thanks in advance!


Solution

  • Is it safe to expose the client secret publicly?

    Generally not a great idea. Depending on the scope of the secret

    Am I understanding correctly that I shouldn't need the client secret when using the Authorization Code flow w/ PKCE?

    No, you are incorrect. PCKE solves a different security problem.

    Is there a different flow/process I should be using where I do not need to expose my client secret, but still allows me to get a refresh token?

    You could handle part of the authentication on a server you control.

    Is the only route to store the client secret in the public source code? Is that even safe? Any help is greatly appreciated!

    You could also require that your users sign up for a developer account and provide their own secret.