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

16

我正在尝试在UnityScript上(或C# - 无论哪个都可以,因为它们都使用相同的Mono .NET类)实现Google oAuth 2服务帐户,具体描述请参见此处:https://developers.google.com/accounts/docs/OAuth2ServiceAccount

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

首先,我已经生成了标题和声明集(与Google文档中的完全相同)。

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

结果如下(为了清晰起见,使用新行分隔):

{"alg":"RS256","typ":"JWT"}

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

"scope":"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);

我得到的全部内容是“Error 400:Bad request”。

编码后的数据如下(为了清晰起见添加了换行符):

  

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9。

     

eyJpc3MiOiI0MjU0NjY3MTkwNzAtMWRnMnJlYnAwYThmbjlsMDJrOW50cjZ1NW80YThscDIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTM0MDIyMjMxNSwiaWF0IjoxMzQwMjE4NzE1fQ。

     

lIFg7-Og_BcC5qpICLt7USwGIHUOz-vV4ADNq0AWhuRtsvFrbZn5mxk4n9r5qU66q4reTVVAtuW06DeGsdcBMNgEdIMvN6VuYQybs64p9mqrfECBYxO1FWHbUG-2On1IpowybEsRRUjZfp0jFuEY7SLE3XRaXan0k5zmejcvLQo

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

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

我只是尝试接收一个令牌。

  1. 我是否以正确的方式对字节进行签名?
  2. 声明集中的“范围”参数应该长什么样子? 我尝试了“https://www.googleapis.com/auth/devstorage.readonly”和“https://www.googleapis.com/auth/prediction”。
  3. “iss”参数应该等于什么?客户端ID还是电子邮件地址? (都试过)
  4. 有哪些方法可以发现我的错误?
  5. 是否有用于服务应用程序的C#库(而不是安装的应用程序或客户端登录)?

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


我在使用C#实现服务账户认证方面也遇到了一些困难。您能否确认一下,您是否成功地使用了示例中显示的grant_type和assertion_type字段?谢谢。 - Nick
2个回答

9
解决方案是,在请求代码中,所有斜杠必须转义为反斜杠。
"scope":"https://www.googleapis.com/auth/prediction",
"aud":"https://accounts.google.com/o/oauth2/token",

CORRECT:

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

soulburner你是我的英雄!非常感谢你!我希望我能点赞10次:D - Darjan Bogdan

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接