1
votes

I'm using Google App Engine to host a couple of services (a NextJS SSR service and a backend API built on Express). I've setup my dispatch.yaml file to route /api/* requests to my API service and all other requests get routed to the default (NextJS) service.

dispatch:
  - url: '*/api/*'
    service: api

The problem: I've also turned on Identity-Aware Proxy for App Engine. When I try to make a GET request from my NextJS service to my API (server-side, via getServerSideProps) it triggers the IAP sign-in page again instead of hitting my API. I've tried out a few ideas to resolve this:

  1. Forwarding all cookies in the API request
  2. Setting the X-Requested-With header as mentioned here
  3. Giving IAP-secured Web App User permissions to my App Engine default service account

But nothing seems to work. I've confirmed that turning off IAP for App Engine allows everything to function as expected. Any requests to the API from the frontend also work as expected. Is there a solution I'm missing or a workaround for this?

1
How do you perform your request in your code? Do you add a bearer id token in the Authorization header?guillaume blaquiere
@guillaumeblaquiere No, I use Axios to make a GET request and pass the cookies from the frontend along in the cookie headerMatt Bise
Ok, you have a frontend service behind IAP that call a backend service behind IAP? Or is it a backend service that call another backend service?guillaume blaquiere
How about turning off IAP on the Backend Service and instead add a bearer token verification? You include that token when you make the call internally. Public users won't have that token which means a call to the backend service by them will fail. Note: According to the documentation - cloud.google.com/iap/docs/managing-access - you should be able to separately turn on/off IAP for Backend Services versus other web servicesNoCommandLine
@guillaumeblaquiere it's a backend service that calls another backend service. Both deployed via App Engine which is behind IAPMatt Bise

1 Answers

1
votes

You need to perform a service to service call. That's no so simple and you have not really example for that. Anyway I tested (in Go) and it worked.

Firstly, based your development on the Cloud Run Service to Service documentation page.

You will have this piece of code in NodeJS sorry, I'm not a NodeJS developer and far least a NexJS developer, you will have to adapt

// Make sure to `npm install --save request-promise` or add the dependency to your package.json
const request = require('request-promise');

const receivingServiceURL = ...

// Set up metadata server request
// See https://cloud.google.com/compute/docs/instances/verifying-instance-identity#request_signature
const metadataServerTokenURL = 'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=';
const tokenRequestOptions = {
    uri: metadataServerTokenURL + receivingServiceURL,
    headers: {
        'Metadata-Flavor': 'Google'
    }
};

// Fetch the token, then provide the token in the request to the receiving service
request(tokenRequestOptions)
  .then((token) => {
    return request(receivingServiceURL).auth(null, null, true, token)
  })
  .then((response) => {
    res.status(200).send(response);
  })
  .catch((error) => {
    res.status(400).send(error);
  });    

This example won't work because you need the correct audience. Here, the variable is receivingServiceURL. It's correct for Cloud Run (and Cloud Functions) but not for App Engine behind IAP. You need to use the Client ID of the OAuth2 credential named IAP-App-Engine-app

Ok, hard to understand what I'm talking about. So, go to the console, API & Services -> Creentials. From there, you have a OAuth2 Client ID section. copy the Client ID column of the line IAP-App-Engine-app, like that

enter image description here

Final point, be sure that your App Engine default service account has the authorization to access to IAP. And add it as IAP-secured Web App User. The service account has this format <PROJECT_ID>@appspot.gserviceaccount.com

Not really clear also. So, go to the IAP page (Security -> Identity Aware Proxy), click on the check box in front of App Engine and go the right side of the page, in the permission panel

enter image description here


In the same time, I can explain how to deactivate IAP on a specific service (as proposed by NoCommandLine). Just a remark: deactivate security when you have trouble with it is never a good idea!!

Technically, you can't deactive IAP on a service. But you can grant allUsers as IAP-secured Web App User on a specific service (instead of clicking on the checkbox of App Engine, click on the checkbox of a specific service). And like that, even with IAP you authorized all users to access to your service. it's an activation without checks in fact.