How to properly store client secret for Google Drive API on Electron app?

Viewed 838

I have an Electron app that requires access to the users Google Drive and I want to implement the api functionality without having to expose the client secret. From my understanding, this is impossible to do in certain scenarios like mobile applications, but what is the proper way of going about this on a local app?

When trying to follow the web-app OAuth instructions from Google, it looks like you can't use this method on a local application. When trying to setup the OAuth process this way it doesn't even let you whitelist localhost as a domain to authenticate users on (which breaks the process since this is a local app running on Electron). Add on to that this paper that Google released and it also seems like you can't trick the auth process to think it's not running on localhost, and you also can't run Node.js in the browser (I'm using Electron so this is impossible to do).

I then tried following their Mobile and Desktop app workflow which seemed promising. The issue arises when you need to Exchange authorization code for refresh and access tokens. This again requires that you show your client secret in your main app. I then though of splitting this up and doing some of it locally and then having an auth server that held the client secret and exchanged the authorization code from the client and returned a refresh and access token. Looking at the diagram that Google provides for visualizing this process, it clearly shows that your app needs to do both parts of the authorization process so that idea was also out.

One application that I personally use and looked at was rclone and from the looks of it they just list their client ID and secret directly in their code. The client secret is encrypted, but if you follow the workflow it gets revealed with a key that is also just stored locally on the app. So it's plain text is obscured, but there is nothing preventing anyone from getting hold of the client secret by slightly modifying the code.

I should also mention this app is in a public repo on GitHub and will stay that way.

This is my first time using OAuth so I may be misunderstanding something, but I tried following the documentation as closely as I could and can't shake the feeling that I'm overlooking a piece of this process.

And if the only way to solve this problem is to expose both the client id and secret, is there any way this could lead to users data being compromised? Since the Google Drive API is free to use I don't really mind if others use some of my quota. I'm more worried about security.

1 Answers

For public clients like Desktop apps you're developing, you'll need to use the PKCE flow. You're right that Google's documentation seems off here - you shouldn't need to pass the client_secret as part of the authorization code exchange.

That's supported by the documentation here: https://www.oauth.com/oauth2-servers/pkce/authorization-code-exchange/

It's possible that Google requires the client_secret but it doesn't treat the parameter as a real "secret" for public clients, but rather an additional identifier that is not sensitive, and not sufficient on its own to do anything on behalf of your application. Section 8.5 of the specification reads:

Secrets that are statically included as part of an app distributed to multiple users should not be treated as confidential secrets, as one user may inspect their copy and learn the shared secret. For this reason, and those stated in Section 5.3.1 of [RFC6819], it is NOT RECOMMENDED for authorization servers to require client authentication of public native apps clients using a shared secret, as this serves little value beyond client identification which is already provided by the "client_id" request parameter.

Authorization servers that still require a statically included shared secret for native app clients MUST treat the client as a public client (as defined by Section 2.1 of OAuth 2.0 [RFC6749]), and not accept the secret as proof of the client's identity. Without additional measures, such clients are subject to client impersonation (see Section 8.6).

You might also look into standalone OAuth service providers, like Xkit where I work. That would let you keep the secret confidential while still going through an OAuth flow.

Related