Tyk and Firebase JWT tokens

Hello.
I’m evaluating Tyk as a gateway for our services.
We are also evaluating Firebase to use for our SSO scheme.

Currently I’ve setup a JWT policy in Tyk with the key which firebase provides, the custom key generated by firebase contains a claims element which is a object with custom claims - which is the only place to put in claims using the Firebase Server Side SDK.

The token roughly looks like this

{
  "alg": "RS256"
}.
{
  "aud": "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
  "claims": {
    "roles": [
      "s"
    ],
    "pol": "57bd61d728e3630001000008"
  },
  "exp": 1472148803,
  "iat": 1472145203,
  "iss": "[email protected]",
  "sub": "[email protected]",
  "uid": "[email protected]"
}.
(signature)

I’m getting such error

tyk_gateway_1    | time="Aug 28 06:17:09" level=error msg="Failed to deccode JWT to RSA type"
tyk_gateway_1    | time="Aug 28 06:17:09" level=info msg="Attempted JWT access with non-existent key." origin=192.168.99.1 path="/catalog/get-products"
tyk_gateway_1    | time="Aug 28 06:17:09" level=error msg="JWT validation error: asn1: structure error: tags don't match (16 vs {class:0 tag:2 length:1 isCompound:false}) {optional:false explicit:false application:false defaultValue:<nil> tag:<nil> stringType:0 timeType:0 set:false omitEmpty:false} tbsCertificate @2" origin=192.168.99.1 path="/catalog/get-products"

Maybe I’m misunderstanding the error, but I understand it as it was actually decoded, but the structure is not valid.
From obvious things are that typ in header is missing.

Also with the nested claims, I cannot have the policy on the root level of payload. Can I setup my policy to access nested properties like it this example claims.pol.

Thank you for your help.

1 Like

Ok, the issue with nested claims is solved. Firebase requires to the Client SDK to sign it and gives you a proper token.

{
  "alg": "RS256",
  "kid": "48576e464f516f804e16f8760066f58df7988f10"
}.
{
  "iss": "https://securetoken.google.com/next-test-c9c0b",
  "name": "my name",
  "roles": [
      "s"
    ],
  "pol": "57bd61d728e3630001000008",
  "aud": "my-app-c9c0b",
  "auth_time": 1472368680,
  "user_id": "9Lp2v00Yk0MrdfQSiwUFkCqkfIi2",
  "sub": "9Lp2v00Yk0MrdfQSiwUFkCqkfIi2",
  "iat": 1472368680,
  "exp": 1472372280,
  "email": "[email protected]",
  "email_verified": true,
  "firebase": {
    "identities": {
      "google.com": [
        "107374840125958991773"
      ],
      "email": [
        "[email protected]"
      ]
    },
    "sign_in_provider": "custom"
  }
}

I’ve added the key available on https://www.googleapis.com/robot/v1/metadata/x509/[email protected] as the secret of the endpoint - which I’m not sure if it is the proper key.

Now I get

tyk_gateway_1    | time="Aug 28 08:06:03" level=error msg="Failed to deccode JWT to RSA type"
tyk_gateway_1    | time="Aug 28 08:06:03" level=info msg="Attempted JWT access with non-existent key." origin=192.168.99.1 path="/catalog/get-products"
tyk_gateway_1    | time="Aug 28 08:06:03" level=error msg="JWT validation error: Invalid Key: Key must be PEM encoded PKCS1 or PKCS8 private key" origin=192.168.99.1 path="/catalog/get-products"

This second token looks more like an OpenID connect identity token, and looking at Firebase auth docs briefly seems to imply that this is what they use.

I would suggest to try use the OIDC middleware auth type instead of a custom JWT, then you:

  1. Don’t need to embed policy claims
  2. Just need to register issuers and oauth client ID’s with Tyk and match them to policies

Thanks for the advice @Martin.

Looking at OIDC right now.

So I understand that we would need to add all issuers and client ids to the endpoint definitions?

I’ve added accounts.google.com the client id from my app and gettings

tyk_gateway_1    | time="Aug 28 09:43:18" level=warning msg="JWT Invalid: Validation error. Validation error. No provider was registered with issuer: https://securetoken.google.com/next-test-c9c0b"
tyk_gateway_1    | time="Aug 28 09:43:18" level=warning msg="Attempted access with invalid key." key="[JWT]"
tyk_gateway_1    | time="Aug 28 09:43:18" level=error msg="request error: Key not authorised" api_id=4dbf44b731cc458f47a9919c4e91edfe org_id=57bd60fd28e3630001000001 path="/" server_name="http://httpbin.org/" user_id= user_ip=192.168.99.1

I’m not experienced with using OIDC, so the https://securetoken.google.com/next-test-c9c0b is a bit confusing right now.
Is this resolved from the client id?
Or maybe its some minor bug in Tyc, since I used that address as an issuer before, and now it is stuck with this one?
The client id is 190057808537-m972joqhtj01q4d1sjf5dkis4e7mnm5p.apps.googleusercontent.com, maybe its a wrong format or not the client Id I should be using?

Edit. the ``https://securetoken.google.com/next-test-c9c0b` is coming from the token I’m sending as I understand. How do I tie this token to a specific client id or a provider?

Google would be the issuer, the client I’d is your Firebase app (or google app or whatever you’ve registered (aka the OAuth Client ID).

So Google issues the tokens, for the client id and then Tyk will contact the issuer, get the relevant key set, validate it agains t the key if in the claims and ensure that your client id is authorised for this app.

Id suggest reading up on OIDC to get the gist.

FWIW this data is all in your JWT:

  • iss: issuer
  • aud: your client ID
  • kid: the cryptographic key id used to sign this request (this id will rotate, Google’s OIDC provider has a discovery endpoint that provides a list, called a JWK, of keys that Tyk caches and uses for validation)
  • sub: your logged in identity’s user ID

So you should be able to populate Tyk based on the claims in the JWT, though yu may need to experiment with be issuer URL

Thanks @Martin.

I’ve tried to apply accounts.google.com as an issuer and got:

tyk_gateway_1    | time="Aug 28 12:01:45" level=warning msg="JWT Invalid: Validation error. Validation error. No provider was registered with issuer: https://securetoken.google.com/next-test-c9c0b"

Which makes sense since the token has the issuer set to this issuer.

I’ve changed the issuer to https://securetoken.google.com/next-test-c9c0b and the client ID to next-test-c9c0b and actually it went pass the verification, but failed on:

tyk_gateway_1    | time="Aug 28 12:05:26" level=warning msg="JWT Invalid: Validation error. Validation error. Failure while decoding the configuration retrived from endpoint https://securetoken.google.com/next-test-c9c0b/.well-known/openid-configuration."

This makes me suspicious that firebase doesn’t entirely follow the OIDC spec.

Hmmm, there might be something up with the token claim, because the issuer is kind of weird, this endpoint works:

https://securetoken.google.com/.well-known/openid-configuration

For some reason in your token there is an additional section: test-xxxx/ before the well known endpoint.

I’d go back to Firebase to see why the token is being generated this way.

M.

So it isn’t yet supported
https://groups.google.com/forum/#!msg/firebase-talk/C5g1H_8tmEA/WaImWzH1DQAJ

So what has been the approach at the end?

I’m evaluating a solution with Firebase as the backend and Tyk as the API manager.

What are your thoughts about this?

Thanks

Carlos

Might be a question to ask the guys at Firebase :-/