How to get Bearer token for Management APIs in Apigee X using API Call?

I couldn't get clear documentation around how to get a bearer token for making management API calls using an API. 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.

Any help related to this would be great.

Thanks

Solved Solved
2 15 4,139
1 ACCEPTED SOLUTION

I was more referring to populating KVMs with required entries.

You can do that with this repo. https://github.com/apigee/devrel/tree/main/references/kvm-admin-api

Since Apigee X is inside of Google Cloud we don't need the Service Account Keys?

Well I wouldn't say "don't need." It depends on what you're doing. But, it's possible to specify a service account to use, when you deploy an API Proxy. And then subsequently outbound calls via ServiceCallout or HTTPTargetConnection can use that service account. (You don't need to bother, inside the proxy logic, about getting and caching a JWT, bearer token, and etc). Here is the documentation for this feature.

Here is what it looks like in the Apigee X UI: https://youtu.be/uylH5qZ_WJY

View solution in original post

15 REPLIES 15

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:

sign-in-with-google.png

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

Hi Dino,

Thanks. I am going to try this and update you

I will be interested to hear your feedback!

HI Dino,

We were able to create a shared flow with service callouts to get the bearer token needed for Apigee Management API calls and successfully call the management APIs in Apigee X. We are using service account keys for the token request 

 

Appreciate your help and follow up

ok I see!  Good.  I'm glad to hear that works for you.  I wasn't clear that you wanted to create thhis Bearer token within the scope of an API Proxy request. I had an example flow that I could have shared with you.  It uses GenerateJWT and ServiceCallout...

https://github.com/DinoChiesa/Apigee-GCP-Logging-Example

Former Community Member
Not applicable
  1. Apigee has a native mechanism to obtain ID and Access tokens to *.googleapis.com. Here are the docs for it. You should not have to programmatically obtain tokens. This system automatically caches token too. This method is also more secure since there is no need to download private keys.
  2. It is a bad practice to invoke control plane APIs from the data plane (because control plane APIs do not have an SLA and are rate limited). What is your use case for invoking the control plane APIs? 

Hi Nandan,

Thanks for this info, this helps. We are not calling control plane APIs for every call but rather KVM setup, Product attributes etc as one time setup for pre deployment config thru CICD. So rate SLA/Rate Limit etc. is non issue.

We have helper proxies created to perform these one time functions.

From what understand if CICD process has to deploy these helper proxies then CICD process would need a Service Account with actAs permission.

I had one additional question. If we are to rotate the Keys for these Service Accounts would the proxies make these Service Callouts using Google Auth need to redeployed?

 

Thanks,

Julian

 

 

Former Community Member
Not applicable

KVMs are automatically created when a proxy is deployed. There is no need to create them. 

For the other items consider calling the apis directly from the CI/CD system instead of an API proxy. 

In general, the CI/CD system does require actAs permission on the SA it uses to deploy the proxy. Key rotation does not apply since keys are not created. 

Thanks. I was more referring to populating KVMs with required entries. Since we don't have management APIs to manage KVM entries in Apigee X this seemed to be the only option.

 

If we are to do it thru CICD process we would still need API Proxies to manage these KVM entries.

Since Apigee X is inside of Google Cloud we don't need the Service Account Keys? 

 

I was more referring to populating KVMs with required entries.

You can do that with this repo. https://github.com/apigee/devrel/tree/main/references/kvm-admin-api

Since Apigee X is inside of Google Cloud we don't need the Service Account Keys?

Well I wouldn't say "don't need." It depends on what you're doing. But, it's possible to specify a service account to use, when you deploy an API Proxy. And then subsequently outbound calls via ServiceCallout or HTTPTargetConnection can use that service account. (You don't need to bother, inside the proxy logic, about getting and caching a JWT, bearer token, and etc). Here is the documentation for this feature.

Here is what it looks like in the Apigee X UI: https://youtu.be/uylH5qZ_WJY

Hi @Former Community Member Will this work for Apigee Edge? I am trying to create an API Proxy in Apigee Edge that will be able to call Apigee Hybrid Management API. Thanks in advance.

Hi @Former Community Member @dchiesa1 Will this work with Apigee Hybrid? TIA


Will this work with Apigee Hybrid? TIA


Can you be specific ? what specifically are you asking about?

@dchiesa1 Thanks for noticing. I am trying to make an Apigee Edge API Proxy call to Apigee Hybrid Management. Use case for this is to try Developer Portal (Drupal plugin) to connect to both Edge and Hybrid and read API apps/products via management endpoint. The most feasible way I can think of is an API proxy in Edge that will target both Edge and at the same time make call to Hybrid Management plane as the Dev Portal plugin doesn't allow more than one apigee instance. Connecting to Hybrid requires authentication and authorization via OAuth2 hence my question.

Ah, I understand. 

Here is a repo containing an example of an API proxy that connects into the Apigee hybrid/X management API. You could start with this, then generalize it to build a proxy that calls the apigee.googleapis.com endpoint to read apps and products etc. 

The repo I referred above attempts to implement a facade  on the KeyValueMaps. But you could modify that to act as a facade on the apps and products, etc.  You may want to handle authn differently - for example store a service account JSON in a keyvaluemap and get the token that is usable against apigee.googleapis.com, "manually".  Here is an example SharedFlow that shows how to do that.