Secure App-Engine Backend with GCP API-Gateway and Firebase Auth

Viewed 661

My purpose is to secure my backend, which is deployed as GCP App Engine, with an API-Gateway, provided by Google, to only let Firebase authenticated users have access to it.

I set everything up, as stated in the documents:

API-Gateway config:

{
  "swagger": "2.0",
  "info": {
    "title": "PROJECT_NAME",
    "version": "1.0"
  },
  "securityDefinitions": {
    "firebase": {
      "authorizationUrl": "",
      "flow": "implicit",
      "type": "oauth2",
      "x-google-issuer": "https://securetoken.google.com/PROJECT_ID",
      "x-google-jwks_uri": "https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken@system.gserviceaccount.com",
      "x-google-audiences": "PROJECT_ID"
    }
  },
  "security": [
    {
      "firebase": [ ]
    }
  ],
  "paths": {
    "/hello-spring": {
      "get": {
        "produces": [
          "application/json"
        ],
        "operationId": "helloSpring",
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "string"
            }
          }
        },
        "x-google-backend": {
          "address": "https://URI-TO-APP-ENGINE-SERVICE",
          "path_translation": "APPEND_PATH_TO_ADDRESS"
          "jwt_audience": "API_CREDENTIALS_FROM_IAP_APP_ENGINE_APP"
        }
      }
    }
  },
  "definitions": {
    "User": {
      "properties": {
        "creationTimestamp": {
          "format": "date-time",
          "type": "string"
        },
        "id": {
          "format": "int32",
          "type": "integer"
        },
        "name": {
          "type": "string"
        },
        "updateTimestamp": {
          "format": "date-time",
          "type": "string"
        },
        "uuid": {
          "type": "string"
        }
      },
      "type": "object"
    }
  },
  "x-components": {}
}

When I send a request - without a jwt token - to this api-gateways url, it correctly responds with

{
    "message": "Jwt is missing",
    "code": 401
}

Firebase jwt
"Default" firebase backend is used, no custom tokens are created. Firebase is used to create the JWT token. From the client following code snippet is used to receive a valid JWT:

final FirebaseAuth _auth = FirebaseAuth.instance;
....

final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication = await googleSignInAccount.authentication;

final AuthCredential credential = GoogleAuthProvider.credential(
    accessToken: googleSignInAuthentication.accessToken,
    idToken: googleSignInAuthentication.idToken,
  );

final UserCredential authResult = await _auth.signInWithCredential(credential);

final String token = await _auth.currentUser.getIdToken();

But as soon as I add the JWT (final String token in code above), which is created by a firebase client app and add it to the request header with

Authorization: Bearer TOKEN_CODE 

gateway responds with

{
    "code": 401,
    "message": "Jwt verification fails"
}

The most detailed LOG I can see in GCP is:

response_code_detail: jwt_authn_access_denied{Jwt_verification_fails}

I also created a service account linked to this API-Gateway with following roles:

  • roles/appengine.appViewer
  • roles/iam.serviceAccountUser
  • roles/run.invoker
  • roles/apigateway.viewer

But still, the same error: "401 - Jwt verification fails". What am I missing,how can I see more details about this issue in GCP and what could be a solution?

0 Answers
Related