How to use Apigee Standard + Identity Platform to expose and secure your APIs with OAuth in Google Cloud [Tutorial]

Dario Banfi
Google Cloud - Community
5 min readOct 26, 2023

In this tutorial we will use Apigee & Identity Platform to secure a Cloud Run API with OAuth.

This is what we’re going to build in a nutshell:

Apigee & Identity Platform to secure Cloud Run API

Apigee recently announced an update to the pay-as you go model which makes it possible to use a limited feature set of its very powerful api management capabilities for a reduced price.

With the new model, Developers can start using Apigee at a fraction of its cost to manage their APIs and provide powerful features like authentication, mediation and security.

What is Apigee? Apigee is a very powerful full-lifecycle API management solution which helps you build, deploy, monitor and productionize APIs. Some of its capabilities include also creating developers portals and user-management and monetization. But at its core, Apigee is an extensible API Gateway, which you can use to perform authentication, request routing & transformation and use it as a facade in front of your microservices.

Deploying Apigee Standard Proxy

Alright, first of all let’s deploy an Apigee instance, which will take some time to provision. The great thing about Apigee is that it’s fully integrated with the GCP networking stack, so that you have a lot of flexibility on what services you can have downstream of the proxy.

Let’s start by creating a project

Then we will deploy Apigee. Make sure to configure a Base Environment to have the low-cost Apigee functionalities, while still being able to use Identity Platform with it.

For brevity’s sake, we will skip those steps in the article and assume you deployed the instance through the console. Follow these instructions if you prefer to use the command line instead (but be aware that it’s a lot of steps!).

Deploying a Cloud Run Microservice

Now, we will deploy a microservice in Cloud Run which we will then put behind Apigee.

Open a Cloud Shell instance on the top-right and past the following command to deploy a simple Hello-World service in Go.

git clone https://github.com/GoogleCloudPlatform/golang-samples.git
cd golang-samples/run/helloworld
gcloud run deploy hello-world - port 8080 - source . - region europe-west1

Allow all necessary APIs when Cloud Run prompts you.

Setting up Identity-Platform

Identity Platform lets you add Google-grade identity and access management to your apps with our customer identity and access management (CIAM) platform.

Right now, it can be either configured through the console or via REST API / Terraform. We will set it up in the console.

Search for “Identity Platform” in the Google Cloud console and enable the API.

Click on “Add a Provider” and configure a “Email / Password” provider, enable it, and disable “Passwordless-Logins”

Click on “Users” in the Sidebar and add a test user e.g. “test@test.com”:”Test!!!”

Great, now let’s configure Apigee to act as a Proxy in front of our Microservices

Configuring Apigee with Identity Platform

Go to the Apigee UI, open the sidebar and select “Api Proxies” to create a new one.

Configure the Cloud Run service Endpoint you deployed earlier in the “Target” field.

Then, make sure to deploy the proxy on the Base Environment you created earlier:

Now, if everything works correctly, Apigee should proxy requests to your Cloud Run service.

Let’s test it out, by requesting the Apigee Endpoint:

curl https://34.36.80.112.nip.io/gcip-apigee-proxy
Hello World!

Cool, now let’s add the policies to secure the endpoint with OAuth2.

Click on the gcip-apigee-proxy proxy you just created and the click on the develop tab.

In the left sidebar, click the “Plus” button to create a new Policy, under the Policies folder.

Here you want to create a “Verify JWT” policy:

Once created, you can use this XML config to make sure that this policy uses Identity Platform JWKS to verify the token.

Make sure to replace apigee-identity-platform with the project id you created earlier.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<VerifyJWT continueOnError="false" enabled="true" name="validate_jwt">
<DisplayName>JWT-verify</DisplayName>
<Algorithm>RS256</Algorithm>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
<Type>signed</Type>
<PublicKey>
<JWKS uri="https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com"/>
</PublicKey>
<Issuer>https://securetoken.google.com/apigee-identity-platform</Issuer>
<Audience>apigee-identity-platform</Audience>
</VerifyJWT>

Now that you created a policy, set it in the PreFlow of the Proxy Request as displayed in this screenshot.

Let’s save this, deploy, and test again:

curl -I https://34.36.80.112.nip.io/gcip-apigee-proxy
HTTP/2 401
x-request-id: 75a88a0d-10a7–459f-9793–0951a790ea07
date: Tue, 24 Oct 2023 14:39:35 GMT
via: 1.1 google
alt-svc: h3=":443"; ma=2592000,h3–29=":443"; ma=2592000

The proxy is now blocking the endpoint because it’s missing a JWT token.

To create a sample JWT token let’s create a sample mock login page in Cloud Shell.

First, head to Identity Platform in the console and in the top right, click on “Application Setup Details”. Copy the content of apiKey and authDomain.

Go to Cloud Shell again and create a new folder with a index.html file:

mkdir gcip
cd gcip
touch index.html

Then copy in the index.html file the following content. Replace $API_KEY and $AUTH_DOMAIN with the ones you just copied, and make sure that the user & password reflect the one you created earlier.​​

<div>Identity Platform Demo</div>
<div id="message">Loading…</div>
<script src="https://www.gstatic.com/firebasejs/8.0/firebase.js"></script>
<script>
var config = {
apiKey: "$API_KEY",
authDomain: "$AUTH_DOMAIN",
};
firebase.initializeApp(config);

var email = "test@test.com";
var password = "Test!!!";

firebase.auth().onAuthStateChanged(function(user) {
if (user) {
document.getElementById("message").innerHTML = "Welcome, " + user.email + "<br/><br/><br/><br/><br/>" + JSON.stringify(user);
} else {
document.getElementById("message").innerHTML = "No user signed in.";
}
});

firebase.auth().signInWithEmailAndPassword(email, password).catch(function(error) {
document.getElementById("message").innerHTML = error.message;
});
</script>

Now we can just start a http server with

python -m http.server 8080

And preview the page on port 8080 through Cloud Shell:

The page will login with the provided credentials and display a JSON output. Grab the content of the field accessToken.

Now if you call the Proxy, this will work! 🎉

curl -H "Authorization: Bearer $ACCESS_TOKEN" https://34.36.80.112.nip.io/gcip-apigee-proxy
Hello World!

--

--