Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google oAuth 2.0 (JWT token request) for Service Application

I'm trying to implement Google oAuth 2 for service accounts described here: https://developers.google.com/accounts/docs/OAuth2ServiceAccount on UnityScript (or C# - that doesn't matter because they both use the same Mono .NET classes).

I've found similar topic here: Is there a JSON Web Token (JWT) example in C#? web-token-jwt-example-in-c but I still don't have a success.

Fist of all, I have generated header and claimset (that are just like in google documentation)

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

The result is (separated with new lines for clarity):

{"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 encoding methods:

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));
}

Then I'm making a signature.

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;

And then forming the request:

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);

And all I get is "Error 400: Bad request".

The encoded data looks like (line breaks added for clarity):

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.

eyJpc3MiOiI0MjU0NjY3MTkwNzAtMWRnMnJlYnAwYThmbjlsMDJrOW50cjZ1NW80YThscDIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTM0MDIyMjMxNSwiaWF0IjoxMzQwMjE4NzE1fQ.

lIFg7-Og_BcC5qpICLt7USwGIHUOz-vV4ADNq0AWhuRtsvFrbZn5mxk4n9r5qU66q4reTVVAtuW06DeGsdcBMNgEdIMvN6VuYQybs64p9mqrfECBYxO1FWHbUG-2On1IpowybEsRRUjZfp0jFuEY7SLE3XRaXan0k5zmejcvLQo

I've spent two days trying to figure out what is wrong but I can't see.

Also, I couldn't find any suitable documentation and examples.

I'm trying just to recieve a token.

  1. Am I signing the bytes the right way?
  2. What should "scope" parameter in claimset look like? I've tried "https://www.googleapis.com/auth/devstorage.readonly" and "https://www.googleapis.com/auth/prediction".
  3. What "iss" parameter should be equal to? Client-id or e-mail address? (tried both)
  4. What are the ways to find out my mistake?
  5. Are there any C# libraries for Service Application (not for installed apps or client login)?

I'm getting crazy... It has to work, but it doesn't... :-/

like image 758
soulburner Avatar asked Jun 20 '12 19:06

soulburner


People also ask

Does OAuth 2.0 Use JWT?

JWT and OAuth2 are entirely different and serve different purposes, but they are compatible and can be used together. The OAuth2 protocol does not specify the format of the tokens, therefore JWTs can be incorporated into the usage of OAuth2.


1 Answers

The solution was that in request code all slashes have to be backslashed

WRONG:

"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",
like image 93
soulburner Avatar answered Sep 21 '22 11:09

soulburner