Twitter LogoFacebook Logo
Generating the JWT and Retrieving the OAuth 2.0 Token
In this tutorial, I’ll show you how to generate the JSON Web Token for OAuth so you can use the Google Play Developer API in server-to-server apps.
By: King

Creating the Service Account

To begin, you will need a Service Account to access the API on behalf of the user. 


Go to the API Access page on the Google Play Console.

Image from Codeible.com

Select "Create new project" and click on the "Link project" button at the bottom.

Image from Codeible.com

Once the project is created, you'll see a new screen with the linked project.

Image from Codeible.com

Under the Service accounts section, click on the "Create new service account" button to begin creating the account.

Image from Codeible.com

Click on the "Google Cloud Platform" link in the dialog.

Image from Codeible.com

Make sure that the project is selected.

Image from Codeible.com

Then click on "CREATE SERVICE ACCOUNT."

Image from Codeible.com

Give the account a name and continue to the next step.

Image from Codeible.com

For the role, select "Service Account User," then click on "Done" to complete the process.

Image from Codeible.com

Go back to the API Access page and click "Done" to close the dialog.

Image from Codeible.com

The page should refresh and your account will appear in the Service accounts section.

Image from Codeible.com

Granting Permissions

The next thing we need to do is to give access to the account to perform actions with the Google Play Developer API.


Click on the "Grant access" button.

Image from Codeible.com

If you want to allow all access, check the Admin permission. For Google Play Billing, check the financial data and Manager orders option.

View financial data, orders, and cancellation survey responses

View financial reports, sales reports, and orders; view buyer metrics on the User acquisition page; access the Purchases API; view revenue information for any associated Play Games Services projects; and download written responses to the cancellation survey

Manage orders and subscriptions

View orders, refund orders, and cancel subscriptions. Users also need the ‘View financial data’ permission to view aggregate financial reports.

Then click on "Invite user" to complete the process.

Image from Codeible.com

Retrieving the Service Account Information

After you grant the necessary permissions, go back to the API access page and click on the "Google Cloud" button next the account.

Image from Codeible.com

Click on the account.

Image from Codeible.com

Select the "Keys" tab.

Image from Codeible.com

Click on "ADD KEY" and then "Create new key."

Image from Codeible.com

Select JSON and then click on "CREATE" to create the file.

Image from Codeible.com

A file should be downloaded automatically. It contains information about the account that we'll need to generate the JSON Web Token.


Keep it safe somewhere and try not to lose it. If you did lose it, you will need to repeat this step and create a new Key file.

Sample JSON Key file

{
  "type": "...",
  "project_id": "...",
  "private_key_id": "...",
  "private_key": "...",
  "client_email": "...",
  "client_id": "...",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "...",
  "client_x509_cert_url": "..."
}

Generating the JSON Web Token

After you obtain the private key for the service account, you’ll need to create a JSON Web Token to request an access token to communicate with the Google Play Developer API.


A JSON Web Token is divided into 3 parts:

1. Header
2. Claim Set
3. Signature

Each part is encoded using the Base64url encoding format and separated by a period.

{ Base64Url Header } . { Base64Url Claim Set } . { Base64Url Signature }

The header and claim set are JSON objects that contains information about the token. 


And the signature is used validate the information when it is received by the server.

Let's see how this is done in code.

To begin, create a new JavaScript file call jwt.js. Then create a JSON object call header. 

const header = {

}

The header consists of 2 fields that indicate the signing algorithm and format of the information.

Use “alg” to represent the algorithm field and then set it to “RS256.” It is the only algorithm supported by the Google OAuth Authorization Server. 

Add another field call “typ” to represent the format and set it to “JWT.”

Now for the claim set, create another JSON object call claimSet. 

const claimSet = {

}

We use the claim set to provide some information about the token such as when it’ll expire, the time it was issued, what permission we want, and the service account we are using to access the information.

Use “iss” to represent the service account and set it to the account you have created earlier. 

const claimSet = {
    iss: "....iam.gserviceaccount.com",
}

Then add 2 more fields call iat and exp.

iat represents the time the token is issued. 

Create a new date object call now, call the getTime() function to get the time into milliseconds and then divide it by 1000 to convert it to seconds. 

Then pass it inside the claimSet.

const now = new Date().getTime() / 1000;


const claimSet = {
    iss: "....iam.gserviceaccount.com",
    iat: now
}

For exp, it represents the time the token will expire. The maximum time it can last is 1 hour. 

Create a new variable call oneHour.

To get one hour in seconds, we do 60 to represent 1 minute. Then we need to multiply it by 60 to get 1 hour.

Create a new variable call expireTime and add now and hourOne together. This’ll get us the amount one hour after the token was issued.

Now pass it inside the claimSet for exp.

const now = new Date().getTime() / 1000;
const oneHour = 60 * 60;
const expireTime = now + oneHour;

const claimSet = {
    iss: "....iam.gserviceaccount.com",
    iat: now,
    exp: expireTime,
}

For the last 2 fields, use “scope” and” aud”.

“scope” represents the permissions we want. 

If we look at the documentation for the Google Play Developer API and scroll to the bottom of the method page. It’ll tell use what scope we need to use to call a particular method.

Copy it and set it into the claimSet.

const claimSet = {
    iss: "....iam.gserviceaccount.com",
    iat: now,
    exp: expireTime,
    scope: "https://www.googleapis.com/auth/androidpublisher"
}

aud” represents the url we are using to get the token from. It is always going to https://oauth2.googleapis.com/token.

Encoding the header and claim set

Now that we have the header and claim set, we need to turn them into a byte array and then encode them using Base64url encoding.

To do this, create a function call toBase64URL with a parameter call json. 

Inside the function, turn the json into a string to serialize it and store it inside a variable call jsonString. 

Then turn it into a Byte array using the Buffer class and store it inside a variable call byteArray.

To encode the array into Base64url, grab the array, call toString() using “base64”, and replace all the +’s with hyphens, all the forward slashes with underlines, and all the equal symbols with an empty string.

Lastly return the encoded string.

Now create a variable call encodedHeader and call the toBase64URL() function to encode the header.

We’ll do the same for the claim set.

const encodedHeader = toBase64URL(header);
const encodedClaimSet = toBase64URL(claimSet);

Generating the signature

To create the signature, import the crypto module from NodeJS.
Then use the createSign() function to create the signer object.

const crypto = require("crypto");
const signer = crypto.createSign("RSA-SHA256");

The first part to getting the signature is to pass in the data to the signer to get it sign.

Grab the signer, call write(), and pass in the header and claim set. Use the period symbol to separate them.

Then, call end() to complete the writing process.

signer.write(encodedHeader + "." + encodedClaimSet);
signer.end;

The second part to get the signature is to get the private key that is unique for the account. It is located inside the JSON file that you downloaded earlier when you created the service account.

Copy the private_key and store it inside a variable of the project.

const privateKey = "-----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY-----\n";

Then grab the signer, call sign, pass in the private key for the first parameter, use “base64” for the second, and store the signature.

const signature = signer.sign(privateKey, "base64");

The third and final part to getting the signature is to encode it using Base64url. 

Create a variable call encodedSignature and replace all the +’s, forward slashes, and equal symbols like how we did it earlier.

const encodedSignature = signature.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");

Obtaining the JWT

Once we have the encoded header, claim set, and signature, we have the JSON Web Token.

Create a variable call jwt and set it to the sum of the header, claimSet, and signature. Then use the period symbol to separate it.

const jwt = `${encodedHeader}.${encodedClaimSet}.${encodedSignature}`;

If we print it out, we’ll get some long-encoded string which is what we want.

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJiaWxsaW5nc2VydmljZWFjY291bnRAYXBpLTQ2NDE1NTM5ODcyMzczOTQyMDUtNTUxMzU5LmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiaWF0IjoxNjQyNDc0Nzg3LjAyOCwiZXhwIjoxNjQyNDc4Mzg3LjAyOCwic2NvcGUiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2FuZHJvaWRwdWJsaXNoZXIiLCJhdWQiOiJodHRwczovL29hdXRoMi5nb29nbGVhcGlzLmNvbS90b2tlbiJ9.vagBHLgdfzyaDO0mutpVZWqzXcrK4K0M7o6s6jQNFB5m50mcvJyLTI9E6RcoHv14ujGodP-NvKSdsg4-mASBV6Ay65bjsQta4GNrpVRAp8Xse8Rsl3Z8j7EtDOtFvdEs9TjHvj_LPThtr0FlFE3yr-513cJmyeAd53kxDOdKeHguuTOrvtp58IrYoAKyuJURY20ijg7ibZD07r-lcDK2cx9yejHs-TYGcvEjAxL7PECEP4JbXaA2NmTKoiNClXfm533Qq-8JqOHUPINx6iKtIkkLmZmzHDvArWZ5WyuvnJuQz83Eyk-iwgY7H_4_6zuv1IU-VG69vaitipCPfMh53g

OAuth and Access Token

Now let’s see how we can get the OAuth token using the JSON Web Token.

Import the https module from Node.  

const https = require("https");

Define a function call getOAuthToken() with one parameter for the JSON Web Token.

This function will return a Promise(). Inside the Promise, create a JSON object call option. We’ll use this to provide information for the request we’ll make to get the OAuth token.

Set the hostname to oauth2.googleapis.com. 

For the path, use forward slash, token, followed by a question mark to start the query string.

Set the grant_type to urn:ietf:params:oauth:grant-type.jwt-bearer and then set the assertion using the JSON Web Token.

For the method, we’ll use POST and for the headers, we’ll set the Content-Type to application/x-www-form-urlencoded.

Once we have the option, make the request by taking the https module and calling the request() function.

var req = https.request();

For the first parameter, pass in the option, and for the second parameter, pass in a callback to handle the response.

var req = https.request(option, function (res) {
                
});

Inside the callback add a callback for the data and when it ends. 

Then store the data inside a string. 

Call the resolve() function from the promise to stop the promise when it ends and pass in the result so we can get it.

var req = https.request(option, function (res) {
     var result = '';
     res.on('data', function (chunk) {
            result += chunk;
     });
     res.on('end', function () {
            resolve(result);
     });           
});

After, add a callback to handle any errors and then end the request.

req.on('error', function (err) {
                reject(err);
});

req.end();

Full function

Testing

To test this, create an async function call test() and call the getOAuthToken() function inside. 


Convert it into a JSON and print it out to the console.

Call the test() function and run the app.

You should see an response with the access token.

{
  access_token: '...',
  expires_in: 3599,
  token_type: 'Bearer'
}


Sign In