connect icon indicating copy to clipboard operation
connect copied to clipboard

Bloblang interpolation in http jwt claims

Open webfrank opened this issue 3 years ago • 4 comments

Hi, I was trying to use http processor with jwt enabled and I need to set the "iat" claim with current timestamp using this code:

jwt:
                  enabled: true
                  private_key_file: private.pem
                  signing_method: RS256
                  claims:
                    iss: iotbuilder
                    sub: benthos
                    iat: ${! timestamp_unix() * 1000 }

but on the server the decoded JWT is:

{
  iat: '${! timestamp_unix() * 1000 }',
  iss: 'iotbuilder',
  sub: 'benthos'
}

The iat claim is not interpolated.

webfrank avatar Jul 29 '22 09:07 webfrank

Hey @webfrank unfortunately these fields don't support interpolation functions, fields that support interpolation functions state explicitly in their document, like here for example: https://www.benthos.dev/docs/components/outputs/nats#subject.

If this is a common pattern we could consider adding them but it'll be quite restrictive in which functions are available.

Jeffail avatar Jul 30 '22 15:07 Jeffail

Hi, it would be useful to have them with interpolation as multiple claims could be inferred from message fields. Probably iat and exp are the more relevant.

webfrank avatar Jul 30 '22 16:07 webfrank

I actually ran into the issue recently as well, in addition to the lack of support for symmetric key algorithms.

Although the interpolation features (in addition to symmetric key algos) would be nice to have, I managed to implement JWT authentication in bloblang. We only needed HS256 support but it shouldn't be hard to adapt.

# Input: an object with fields:
#   * claims - optional map of kv's to include in the payload
#       * 'iat' and 'exp' included by default, but can be overridden if provided
#   * secret - raw signing secret (not PEM encoded)
#   * ttl - time to live, in seconds (exp = now + ttl)
# Output: signed JWT token
map jwt_gen {
    let header = {
        "typ": "JWT",
        "alg": "HS256",
    }.string().encode("base64url").trim("=")
    let now = timestamp_unix()
    let claims = {
        "iat": $now,
        "exp": $now + this.ttl,
    }.assign(this.claims | {}).string().encode("base64url").trim("=")
    let signature = [$header, $claims].join(".").hash("hmac_sha256",this.secret).encode("base64url").trim("=")
    root = [$header, $claims, $signature].join(".")
}

In high throughput scenarios, it's also usually a good idea to also utilize a cached processor to save from recalculating the JWT signature on every message.

EDIT: engrish

DeusFacticius avatar Jul 31 '22 20:07 DeusFacticius

Just dropping in to say I just hit this issue trying to use the github api with the http processor. Thanks for the workaround!

greysond avatar Nov 11 '22 16:11 greysond

For people looking to use something like this for GitHub Apps, here's an example: https://github.com/mihaitodor/benthos-playground/blob/main/benthos/github_app_graphql_query.yaml. It should work once #1970 is merged.

mihaitodor avatar Jun 20 '23 23:06 mihaitodor