1
votes

I'm writing an open-source stand-alone desktop app in Java that handles photos, and I'm adding a feature to let users upload pictures to their Google Photos account, but I'm faced with an authentication/security question.

I've registered my project to use the Google Photo API and have downloaded my credentials JSON file. I've been able to use it successfully with the samples from the java-photoslibrary Github project, so all is good.

However, the credentials file contains a "client_secret" key which, if I'm not mistaken, should not be disclosed (am I correct here ?). But those credentials have to somehow be distributed with the app and, as it is open-source, will be basically public. So my question is: How can I authenticate my app's user to his/her Google Photo account without disclosing my app's secret key ?

Note: I've integrated Dropbox upload, and their procedure for desktop apps clearly explains how to authenticate without embedding the secret key in the Desktop app using OAuth's token flow. Is there an equivalent for Google Photos ?

Thanks.

Edit: made some progress (see my own answer below), but after I finally got time to implement it, I realized that after user has authorized the app and a valid code has been returned (Yay!), step 5 (Exchanging the code for a token) again requires the client_secret ! :-(

I tried the call without it but I'm receiving a "client_secret is missing" error, so that's not a typo.

After more search (with the [google-oauth] keyword instead of [oauth-2.0], which says it all), it seems "secret" does not mean it is actually "secret" in Google world. In other terms, it's OK to embed it in your apps because, well, it's secret but it cannot be used in a malicious way (hopefully)...

See answers to these related questions:

One Google page even mentions that "In this context, the client secret is obviously not treated as a secret."

Come on Google, explain me how security works :-)

1
Is it a standalone client app or client server?Ralph
Stand-alone (just updated the question). Thanks.Vicne
Can you share the link for Dropbox documentation referred aboveRalph
Sure. My case was similar to this question - dropboxforum.com/t5/Dropbox-API-Support-Feedback/… . Starting from there, I implemented PKCE which basically creates a random number, encrypts it with the app's public key and send it to Dropbox, Dropbox prompts the user for approval and responds with a code that can be matched and converted by the app into a user token to be used in subsequent requests. The app's secret key is not involved at any pointVicne

1 Answers

0
votes

OK I think I found the answer.

Similar to Dropbox, Google can use OAuth 2 with PKCE, they just use the full spelling "Proof Key for Code Exchange", that's probably why I didn't find it at first :-). The details are here: https://developers.google.com/identity/protocols/oauth2/native-app#obtainingaccesstokens

I didn't find the equivalent process in the Google APIs, but those API are megabytes of classes so I may have missed it. Basically, all it takes is just sending a few requests and listening to the response, so I think I'll implement it from scratch (and will probably also get rid of Dropbox's client libs as the process is so similar).

Hope it helps...

Edit: that doesn't address the point because after the clean PKCE procedure, the app still has to send its private key to exchange the authorization code for a token. See edit in my question