I am able to get bearer token using gcloud commands and do an export but would like to get it programmatically using an API Call.
To “manually” perform the equivalent of gcloud auth login or gcloud auth application-default login you can just invoke the Google oauthv2 token dispensing endpoints. There is a REST API.
There are two approaches you can take:
In either case, to get a token, you will need to send an HTTP POST to the /token endpoint, like this:
POST https://oauth2.googleapis.com/token
…but there are some details regarding the payload and what you need to send.
The first case, using service account keys to authenticate, is easier. But that alone is not a good reason to use SA keys. The two methods are intended for different purposes, and you should take care to decide which one to use, carefully. If in doubt review your use case with your security architect. In a typical case, a CI/CD pipeline might use a service account. But if you’re just automating Google things (including apigee.googleapis.com) for your own purposes you probably want to use the human authentication to get the token. Regardless which case you use, the result is an OAuth token, which looks and works the same after you acquire it.
The oauth2.googleapis.com endpoint supports authorization code grants for human authentication, or an RFC7523-style grant , using grant_type = urn:ietf:params:oauth:grant-type:jwt-bearer. I’ll describe those here.
urn:ietf:params:oauth:grant-type:jwt-bearer
This process is documented in various places in the docs for Google cloud. Here is one. Just search for the grant_type string and you’ll find other pages. They’re all similar. I’ll summarize here. You need to pass in a signed JWT as an assertion. That JWT should be “self-signed” using RS256, and the private key of the service account. The payload of the JWT must be like this:
{
"iss" : "ServiceAccount client_email",
"scope" : "https://www.googleapis.com/auth/cloud-platform",
"aud": "https://oauth2.googleapis.com/token",
"iat": nowInSeconds,
"exp": nowInSeconds + (3 * 60)
}
That scope string is valid, but it’s just an example. Of course you should use the minimal scope necessary there. The iss claim you should get from the downloaded .JSON file for the service account. The iat and exp must be present and reasonable. The expiry can be no longer than 300 seconds after issuance or now (whichever is less).
The POST request then looks like this:
curl -i -H content-type:application/x/www-form-urlencoded \
-X POST \
https://oauth2.googleapis.com/token \
-d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=$JWT"
The result is a JSON payload like this:
{
"access_token": "ya29.c.b0AXv0zTPIXDh-FGN_hM4e....jN8H3fp50U............",
"expires_in": 3599,
"token_type": "Bearer"
}
and you can use THAT access_token value as a Bearer token in other API calls to *.googleapis.com , including apigee.googleapis.com . Note: the service account must have the right roles in order for the token to be honored for the various requests you make.
User Authentication
You need to create an OAuth client ID within google cloud console, then use the id in a request to kick off authorization. The authz request looks like this:
GET https://accounts.google.com/o/oauth2/v2/auth?
scope=email%20profile&
response_type=code&
state=security_token%3D138r5719ru3e1%26url%3Dhttps%3A%2F%2Foauth2.example.com%2Ftoken&
redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&
client_id=client_id
When you open that in a browser, you should get redirected to a sign-in-with-google screen that looks like this:
After you sign in, you will see a consent screen, the content of which varies depending on the scopes you requested in the kickoff. If you consent, then you get a one-time code, which you can then exchange for a token, with the post call I mentioned earlier. IT looks like this:
POST https://oauth2.googleapis.com/token
Accept: application/json
Content-Type: application/x-www-form-urlencoded
code=ONE_TIME_CODE_HERE&
client_id=CLIENT_ID_HERE&
client_secret=CLIENT_SECRET_HERE&
redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&
grant_type=authorization_code
That payload should be all-on-one-line.
The response will be a JSON payload containing an access_token. It will grant the permissions - on Apigee things or any GCP resource - that the user has in the project.
Here is a github repo with working code that shows both of these methods: https://github.com/DinoChiesa/get-gcp-access-token