我正在寻找一些关于如何设计和创建我自己的桌面应用程序(或)的最佳实践示例代码。安装的应用程序)在Python中要求OAuth 2.0授权流向Google,并找到了Google提供的这个资源库。https:/github.comgooglesamplesoauth-apps-for-windows)。 (用C#编码,但无论如何设计应该是一样的)。
当深入研究代码时,我惊讶地看到 client_secret
被直接嵌入到源代码中,清晰地显示出来(请看这里。https:/github.comgooglesamplesoauth-apps-for-windowsblobe79f1575b5858c5f617d29f2435a93996e4248c5OAuthConsoleAppOAuthConsoleAppProgram.cs#L47。).
我发现在 谷歌开发者文档中关于 "已安装的应用程序" :
当您通过Google API控制台创建客户端ID时,请指定这是一个安装的应用程序,然后选择Android、Chrome、iOS或 "其他 "作为应用程序类型。这个过程会产生一个客户端ID,在某些情况下。客户端秘密,您将其嵌入到您的应用程序的源代码中。(在这种情况下,客户端的秘密显然不被视为秘密)。
另外,我不知道为什么Android或iOS应用程序不包括这个。client_secret
在从控制台生成的OAuth客户端ID中,其他原生应用(桌面)也应该如此。
我还在许多网站上发现,客户端的秘密应该保持......秘密,正如它的名字所暗示的那样。
我已经阅读了不同的RFCs的本地应用程序(最可靠的来源,我相信),并发现这是有用的。
https:/tools.ietf.orghtmldraft-ietf-oauth-native-apps-12#附录-A :
- 不要以为原生应用客户端可以保守秘密。如果秘密被分发给同一本地应用程序的多个安装,则不应将其视为机密。参见第8.5节。
但我想确定我的理解是正确的。
那么,在从Google API Console生成 "其他 "应用类型的OAuth客户端Id后,是否可以直接在我的应用中嵌入客户端秘密?这样做真的没有安全问题吗?这篇SO贴 。What the attacker could do if he obtains application's client_secret? 谈到了安全问题,所以我有点迷茫。
使用 google-auth-oauthlib 为了避免从头开始实现OAuth协议,我可以安全地发布以下代码吗?****
值显然不会被混淆)。
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
如果一个恶意用户发现了 client_secret
,他能用这个做什么?
客户端secret并没有附加任何特殊的用户数据,因为任何使用client_id和client_secret的人都需要通过OAuth屏幕来验证自己的Google账户。
但实际的问题似乎是,你正在使用生成的凭证访问谷歌API,而这些API调用不是免费的。最后,你的应用要为通过你的应用进行认证的用户所进行的API调用付费。
当公共客户端(例如,本地和单页应用程序)请求访问令牌时,会带来一些额外的安全问题,而这些问题并不能仅仅通过授权代码流来缓解。这是因为
原生应用程序无法安全地存储客户端秘密。反编译应用程序将揭示客户机秘籍,该秘籍与应用程序绑定,对所有用户和设备都是一样的。 可能会利用自定义 URL 方案来捕获重定向(例如,MyApp:/),有可能允许恶意应用程序从您的授权服务器接收授权代码。
单页应用程序无法安全地存储客户机秘密,因为它们的整个源头对浏览器是可用的。
为了缓解这一问题,OAuth 2.0提供了一个授权代码流的版本,它使用了代码交换的证明密钥(PKCE)(在OAuth 2.0 RFC 7636中定义)。
PKCE增强的授权代码流引入了一个由调用应用程序创建的秘密,该秘密可以被授权服务器验证;该秘密被称为代码验证器。此外,调用应用程序还创建了一个称为代码验证器的转换值,并通过HTTPS发送这个值来检索授权代码。这样一来,恶意攻击者只能拦截授权码,他们无法在没有Code Verifier的情况下将其换成令牌。