Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Safely distribute OAuth 2.0 client_secret in desktop applications in Python

I was looking for some best practices sample code about how to design and create my own desktop app (or installed app) in Python requiring OAuth 2.0 Authorization flow to Google, and found this repository provided by Google : https://github.com/googlesamples/oauth-apps-for-windows (coded in C#, but anyway the design should be the same).

When diving into the code, I was surprised to see that the client_secret was directly embedded, in clear, into the source code (take a look here : https://github.com/googlesamples/oauth-apps-for-windows/blob/e79f1575b5858c5f617d29f2435a93996e4248c5/OAuthConsoleApp/OAuthConsoleApp/Program.cs#L47).

I have found this on Google Developers documentation about "Installed applications" :

When you create a client ID through the Google API Console, specify that this is an Installed application, then select Android, Chrome, iOS, or "Other" as the application type. 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.)

Also, I don't know why Android or iOS applications does not include this client_secret in the OAuth Client ID generated from the console, and other native applications (desktop) should.

And I have also found in many websites that the client secret should be kept ... secret, as its name implies.

I have read the different RFCs for native apps (most reliable source I believe) and found this useful :

https://datatracker.ietf.org/doc/html/draft-ietf-oauth-native-apps-12#appendix-A :

  1. Not assume native app clients can keep a secret. If secrets are distributed to multiple installs of the same native app, they should not be treated as confidential. See Section 8.5.

But I'd like to be sure I understand correctly.

So, after generating the OAuth Client Id for "other" application type from the Google API Console, is it ok to embed the client secret directly in my app? Is there really no security issues by doing this? This SO post : What the attacker could do if he obtains application's client_secret? talks about security issues, so I'm a little bit lost.

Using google-auth-oauthlib to avoid implementing OAuth protocol from scratch, can I distribute safely the following code (**** values will not be obfuscated obviously) :

from google_auth_oauthlib import flow

# generated from Google API Console ("other" application)
client_config = {
  "installed": {
    "client_id": "****.apps.googleusercontent.com",
    "client_secret": "****", # is it safe?
    "project_id": "****",
    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "token_uri": "https://oauth2.googleapis.com/token",
    "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
    "redirect_uris": [
      "urn:ietf:wg:oauth:2.0:oob"
    ]
  }
}

scopes = ['https://www.googleapis.com/auth/books'] # example
appflow = flow.InstalledAppFlow.from_client_config(client_config, scopes=scopes)
appflow.run_console()
credentials = appflow.credentials

# some code requesting Google APIs for the required scopes

If a malicious user found the client_secret, what can he do with this?

like image 465
norbjd Avatar asked Dec 19 '19 20:12

norbjd


2 Answers

I have the same issue with Google requiring client_secret for desktop apps. While an attacker obviously cannot get confidential information with a client_secret, could he not launch a denial-of-service attack by generating a large number of spurious requests with that client_secret and causing Google to block it? That would require the developer to create a new client secret and redistribute to all users??

like image 57
yegodz Avatar answered Sep 18 '22 05:09

yegodz


When public clients (e.g., native and single-page applications) request Access Tokens, some additional security concerns are posed that are not mitigated by the Authorization Code Flow alone. This is because:

Native apps
Cannot securely store a Client Secret. Decompiling the app will reveal the Client Secret, which is bound to the app and is the same for all users and devices. May make use of a custom URL scheme to capture redirects (e.g., MyApp://) potentially allowing malicious applications to receive an Authorization Code from your Authorization Server.

Single-page apps
Cannot securely store a Client Secret because their entire source is available to the browser.

To mitigate this, OAuth 2.0 provides a version of the Authorization Code Flow which makes use of a Proof Key for Code Exchange (PKCE) (defined in OAuth 2.0 RFC 7636).

The PKCE-enhanced Authorization Code Flow introduces a secret created by the calling application that can be verified by the authorization server; this secret is called the Code Verifier. Additionally, the calling app creates a transform value of the Code Verifier called the Code Challenge and sends this value over HTTPS to retrieve an Authorization Code. This way, a malicious attacker can only intercept the Authorization Code, and they cannot exchange it for a token without the Code Verifier.

Further reading : https://auth0.com/docs/flows/concepts/auth-code-pkce

like image 37
Akashdeep S Avatar answered Sep 20 '22 05:09

Akashdeep S