用于服务应用程序的 Google oAuth 2.0(JWT 令牌请求)

Posted

技术标签:

【中文标题】用于服务应用程序的 Google oAuth 2.0(JWT 令牌请求)【英文标题】:Google oAuth 2.0 (JWT token request) for Service Application 【发布时间】:2012-06-22 23:54:07 【问题描述】:

我正在尝试为此处描述的服务帐户实施 Google oAuth 2:https://developers.google.com/accounts/docs/OAuth2ServiceAccount on UnityScript(或 C# - 没关系,因为它们都使用相同的 Mono .NET 类)。

我在这里找到了类似的主题:Is there a JSON Web Token (JWT) example in C#? web-token-jwt-example-in-c 但我还是没有成功。

首先,我已经生成了标题和声明集(就像在谷歌文档中一样)

var header: String = GetJWTHeader();
var claimset: String = GetJWTClaimSet();

结果是(为清楚起见,用新行分隔):

"alg":"RS256","typ":"JWT"

"iss":"425466719070-1dg2rebp0a8fn9l02k9ntr6u5o4a8lp2.apps.googleusercontent.com",

"范围":"https://www.googleapis.com/auth/prediction",

"aud":"https://accounts.google.com/o/oauth2/token",

"exp":1340222315,

"iat":1340218715

Base-64 编码方式:

public static function Base64Encode(b: byte[]): String 
    var s: String = Convert.ToBase64String(b);
    s = s.Replace("+", "-");
    s = s.Replace("/", "_");
    s = s.Split("="[0])[0]; // Remove any trailing '='s
    return s;


public static function Base64Encode(s: String): String     
    return Base64Encode(Encoding.UTF8.GetBytes(s));

那我要签名了。

var to_sign: byte[] = 
     Encoding.UTF8.GetBytes(Base64Encode(header) + "." + Base64Encode(claimset));
var cert: X509Certificate2 = 
     new X509Certificate2(google_pvt_key.ToArray(), "notasecret");
var rsa: RSACryptoServiceProvider = cert.PrivateKey;
var sgn: String = Base64Encode(rsa.SignData(to_sign, "SHA256"));

var jwt: String = Base64Encode(header) + "." + Base64Encode(claimset) + 
                     "." + sgn;

然后形成请求:

var url: String = "https://accounts.google.com/o/oauth2/token";
var form: WWWForm = new WWWForm();
form.AddField("grant_type", "assertion");
form.AddField("assertion_type", "http://oauth.net/grant_type/jwt/1.0/bearer");
form.AddField("assertion", jwt);
var headers: Hashtable = form.headers;
headers["Content-Type"] = "application/x-www-form-urlencoded";

var www: WWW = new WWW(url, form.data, headers);

我得到的只是“错误 400:错误请求”。

编码后的数据看起来像(为清楚起见添加了换行符):

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.

eyJpc3MiOiI0MjU0NjY3MTkwNzAtMWRnMnJlYnAwYThmbjlsMDJrOW50cjZ1NW80YThscDIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTM0MDIyMjMxNSwiaWF0IjoxMzQwMjE4NzE1fQ。 P>

lIFg7-Og_BcC5qpICLt7USwGIHUOz-vV4ADNq0AWhuRtsvFrbZn5mxk4n9r5qU66q4reTVVAtuW06DeGsdcBMNgEdIMvN6VuYQybs64p9mqrfECBYxO1FWHbUG-2On1IpowybEsRRUQoXRapXan

我花了两天时间试图找出问题所在,但我看不到。

另外,我找不到任何合适的文档和示例。

我只是想收到一个令牌。

    我是否以正确的方式签署字节? 声明集中的“范围”参数应该是什么样的?我试过“https://www.googleapis.com/auth/devstorage.readonly”和“https://www.googleapis.com/auth/prediction”。 “iss”参数应该等于什么?客户 ID 或电子邮件地址? (都试过了) 有什么方法可以找出我的错误? 是否有任何用于服务应用程序的 C# 库(不适用于已安装的应用程序或客户端登录)?

我快疯了......它必须工作,但它没有......:-/

【问题讨论】:

我也很难在 C# 中实现服务帐户身份验证!您能否向我确认您成功使用了您的示例中显示的 grant_type 和 assertion_type 字段?谢谢 【参考方案1】:

解决方案是在请求代码中所有斜杠都必须反斜杠

错误:

"scope":"https://www.googleapis.com/auth/prediction",
"aud":"https://accounts.google.com/o/oauth2/token",

正确:

"scope":"https:\\/\\/www.googleapis.com\\/auth\\/prediction",
"aud":"https:\\/\\/accounts.google.com\\/o\\/oauth2\\/token",

【讨论】:

灵魂燃烧者你是我的英雄!非常感谢!我希望我能投票 10 次:D【参考方案2】:

尝试使用system.identitymodel.tokens.jwt .Net 库 您可以从 NuGet 安装它。 请参阅我的帖子中的示例(我用它来验证 websockets 服务器,但 JWT 处理是通用的)

http://mydevtricks.blogspot.co.il/2014/10/xsocketsnet-authentication-with-jwt.html

【讨论】:

以上是关于用于服务应用程序的 Google oAuth 2.0(JWT 令牌请求)的主要内容,如果未能解决你的问题,请参考以下文章

用于服务器端 Web 应用的 Google Oauth2 的 CORS 问题

服务帐户的 google OAuth 2.0 是 OAuth 2.0 标准的一部分吗?

将 OAuth 2.0 用于 Web 服务器应用程序流时无法选择正确的通道

Android 应用上的 Oauth 2

Android 应用上的 Oauth 2

OAuth 2.0 适用于 Google 表格,但不适用于 Google Calendar API