Home > Software design >  Ambassador Edge Stack JWT filter with Firebase token not working
Ambassador Edge Stack JWT filter with Firebase token not working

Time:11-08

I'm trying to verify a Firebase generated JWT token with an Ambassador Edge Stack (datawire/edge-stack version 3.3.0) Filter.

The Firebase token is generated using a login/password authent mechanism on firebase, something like (in Python):

    email=input("Enter email: ")
    password=input("Enter password: ")
    user = authentication.sign_in_with_email_and_password(email, password)
    custom_token = auth.create_custom_token(user["localId"], additional_claims)
    print("JWT Token :")
    print(custom_token)

After the token is generated, I use it with a curl command such as:

curl -H "Authorization: Bearer $TOKEN" https://ambassador-ip.nip.io/hello-world/

and the curl command returns the following error:

        },
        "message": "Token validation error: token is invalid: errorFlags=0x00000002=(ValidationErrorUnverifiable) wrappedError=(KeyID=\"50***redacted***1\": JWK not found)",
        "status_code": 401
}

Here is the ambassador Filter I've declared:

apiVersion: getambassador.io/v2
kind: Filter
metadata:
  name: "firebase-filter"
  namespace: ${kubernetes_namespace.hello_world.metadata[0].name}
spec:
  JWT:
    jwksURI:  "https://www.googleapis.com/service_accounts/v1/metadata/x509/[email protected]"
    audience: "${local.project_id}"
    issuer:   "https://securetoken.google.com/${local.project_id}"

And the policy filter applied to my backend:

apiVersion: getambassador.io/v3alpha1
kind: FilterPolicy
metadata:
  name: "firebase-filter-policy"
  namespace: ${kubernetes_namespace.hello_world.metadata[0].name}
spec:
  rules:
  - host: "*"
    path: "/hello-world/"
    filters:                    
    - name: "firebase-filter"
      namespace: "${kubernetes_namespace.hello_world.metadata[0].name}"

For the record, the curl command with the same token works on a deployed hello-world Cloud Run with a GCP API gateway configured as follow:

swagger: '2.0'
info:
  title: Example Firebase auth Gateway
  description: API Gateway with firebase auth
  version: 1.0.0
schemes:
  - https
produces:
  - application/json
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/[email protected]"
    x-google-audiences: "${project_id}"
paths:
  /v1/hello:
    get:
      security:
        - firebase: []
      description: Hello
      operationId: hello
      responses:
        '200':
          description: Success
      x-google-backend:
        address: 'https://hello-redacted-ew.a.run.app'

Any idea why the Ambassador filter is misconfigured ?

CodePudding user response:

The JWT Filter requires you to provide the url for the .well-known/openid-configuration so that it can verify the signature of the token. I'm not familiar with Firebase but looking on their docs it appears you can find this here: https://firebase.google.com/docs/auth/web/openid-connect

For example your Filter should be configured something like the following (i'm guessing on the jwksURI):

apiVersion: getambassador.io/v2
kind: Filter
metadata:
  name: "firebase-filter"
  namespace: ${kubernetes_namespace.hello_world.metadata[0].name}
spec:
  JWT:
    jwksURI:  "https://securetoken.google.com/${local.project_id}/.well-known/openid-configuration"
    audience: "${local.project_id}"
    issuer:   "https://securetoken.google.com/${local.project_id}"

CodePudding user response:

Ambassador JWT Filter needs the jwksURI to point to the Firebase secure token service account public keys and not the X509 certificates, therefore the Filter should be:

apiVersion: getambassador.io/v2
kind: Filter
metadata:
  name: "firebase-filter"
  namespace: ${kubernetes_namespace.hello_world.metadata[0].name}
spec:
  JWT:
    jwksURI:  "https://www.googleapis.com/service_accounts/v1/jwk/[email protected]"
    audience: "${local.project_id}"
    issuer:   "https://securetoken.google.com/${local.project_id}"

This is working for Firebase tokens only. If you want to make this works with Custom tokens using some dedicated service account for example, you might need the jwksURI to point to your service account public keys, something like:

apiVersion: getambassador.io/v2
kind: Filter
metadata:
  name: "firebase-custom-filter"
  namespace: ${kubernetes_namespace.hello_world.metadata[0].name}
spec:
  JWT:
    jwksURI:  "https://www.googleapis.com/service_accounts/v1/jwk/${service_account}@${local.project_id}.iam.gserviceaccount.com"
    audience: "${local.project_id}"
    issuer:   "https://securetoken.google.com/${local.project_id}"
  • Related