Reputation: 675
I trying to make authorized API call (HTTP/REST) to service account in Google Analytics. using this doc: https://developers.google.com/identity/protocols/OAuth2ServiceAccount
I just use HTTP/REST request to test.
So I have service account's private key file:
{
"type": "service_account",
"project_id": "test-x",
"private_key_id": "some_private_key_id",
"private_key": "-----BEGIN PRIVATE KEY----- some_private_key -----END PRIVATE KEY-----",
"client_email": "[email protected]",
"client_id": "some_client_id",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/test-01%40test-x.iam.gserviceaccount.com"
}
I create JWT based on client_email: [email protected]
Header:
{"alg":"RS256","typ":"JWT"}
Claim set:
{
"iss": "[email protected]",
"scope": "https://www.googleapis.com/auth/analytics.readonly",
"aud": "https://www.googleapis.com/oauth2/v4/token",
"exp": 1488820112,
"iat": 1488816522
}
iat - I just set current
exp - current + 1 hour,
I use this service to create signature: https://jwt.io/#debugger
It generates encoded value which I try to use for access token request
When I try to use generated result from "Encoded" field:
curl -d 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=JWT_that_has_been_signed' https://www.googleapis.com/oauth2/v4/token
result:
{
"error": "invalid_grant",
"error_description": "Invalid JWT Signature."
}
But I not use my private key. Accordingly to documentation for computing the signature I have to use my private key. I not completely understand how to use key in right way to compute the signature correctly.
jwt.io already generates PUBLIC and PRIVATE key...
Probably I'm using jwt.io incorrectly..
Please advise me the correct way of creating JWT or may be another service to create it.
Thanks!
Upvotes: 10
Views: 34171
Reputation: 1
In my case I had a wrong time zone on my system.
I reinstalled my system and did not spot that the time was not set correctly.
Upvotes: 0
Reputation: 130
In my case I used wrong service account ID
.
You are able to find correct on under: Google console -> Service Account -> Detail -> Unique ID
I must be a long number like: 113334445551115554321
Upvotes: 1
Reputation: 577
For anyone exploring this issue, I have a set of code in PHP to get the token with the JSON service account file. This PHP snippet will get you a token to use to get GA data.
// assume $config is your json service account file converted to array
$config = "YOUR JSON FILE CONVERTED TO ARRAY";
$jwt_header = '{"alg":"RS256","typ":"JWT"}';
$jwt_header_cryph = urlencode(base64_encode($jwt_header));
$jwt_claim = '{
"iss": "'.$config['client_email'].'",
"scope":"https://www.googleapis.com/auth/analytics.readonly",
"aud":"https://www.googleapis.com/oauth2/v4/token",
"exp":'.(time()+3600).',
"iat":'.time().'
}';
$jwt_claim_cryph = urlencode(base64_encode($jwt_claim));
$data = $jwt_header_cryph.".".$jwt_claim_cryph;
$binary_signature = "";
$algo = "SHA256";
openssl_sign($data, $binary_signature, $config['private_key'], $algo);
$jws_signature_cryph = urlencode(base64_encode($binary_signature));
//concatenating the jwt request to complete it
$complete_request = $jwt_header_cryph.".".$jwt_claim_cryph.".".$jws_signature_cryph;
//build CURL request with post method
$url = 'https://www.googleapis.com/oauth2/v4/token';
//set POST variables
$fields = array(
'grant_type' => urlencode('urn:ietf:params:oauth:grant-type:jwt-bearer'),
'assertion' => $complete_request
);
$fields_string = "";
//url-ify the data for the POST
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string, '&');
//open connection
$ch = curl_init();
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true );
//execute post
$result = curl_exec($ch);
//close connection
curl_close($ch);
$token = json_decode($result, true);
The variable $token
will have the following content
[
"access_token" => "your-access-token-string"
"expires_in" => 3599
"token_type" => "Bearer"
]
Use the access_token
string to ping GA for analytics data.
Hopefully this helps someone along as this is not well explained much anywhere and it took some digging to figure out the encryption properly.
Upvotes: 3
Reputation: 774
I got this error when the secrets key was no longer valid. I generated a new service account key and it started working.
Upvotes: 7
Reputation: 2437
I had a same issue ,
I just create a new private key from google cloud platform
IAM & admin -> Service accounts
Service accounts for project
"Project_Name"
already created your Service account,click on the actions-> Create Key
and update the private key on your project. Hope it will help you.
Upvotes: 1