Search code examples
jwtlumenenvoyproxyjwklaravel-envoy

Jwt verification fails by Envoy


I have a Laravel(Lumen) Login API, which generates a JWT using HS256. Then I sent my bearer token to Envoy Gateway and get from Envoy

JWT verification fails

On official JWT decode site I could successfully decode and verify my bearer token. Here I generate my JWT:

{
    $payload = [
        'iss' => config('app.name'),                  // Issuer vom Token
        'sub' => strval($user->ID),                       // Subject vom Token
        'username' => $user->username,
        'iat' => time() - 500,                            // Time when JWT was issued.
        'exp' => time() + config('jwt.ttl'),         // Expiration time
        'alg' => 'HS256',
        'kid' => 'ek4Z9ouLmGnCoezntDXMxUwmjzNTBqptKNkfaqc6Ew8'
    ];
    $secretKey = 'helloworld'; //my base64url

    $jwtEnc = JWT::encode($payload, $secretKey, $payload['alg'], $payload['kid']);

    return $jwtEnc;
}

Here is my Envoy config:

static_resources:
  listeners:
    - name: listener_0
      address:
        socket_address:
          address: 0.0.0.0
          port_value: 10000
      filter_chains:
        - filters:
            - name: envoy.filters.network.http_connection_manager
              typed_config:
                '@type': 'type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager'
                stat_prefix: edge
                http_filters:
                  - name: envoy.filters.http.jwt_authn
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
                      providers:
                        provider1:
                          issuer: 'Lumen'
                          forward: true
                          local_jwks:
                            inline_string: '{"keys": [{"kty": "oct", "use": "sig", "kid": "ek4Z9ouLmGnCoezntDXMxUwmjzNTBqptKNkfaqc6Ew8", "k": "helloworld", "alg": "HS256"}]}' //'k' is here base64url
                      rules:
                        - match:
                            prefix: "/list"
                          requires:
                            provider_name: "provider1"
                  - name: envoy.filters.http.router
                route_config:
                  virtual_hosts:
                    - name: all_domains
                      domains: [ "*" ]
                      routes:
                        - match:
                            prefix: "/api"
                          route:
                            cluster: loginapi
  clusters:
    - name: loginapi
      connect_timeout: 5s
      load_assignment:
        cluster_name: loginapi
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: 0.0.0.0
                      port_value: 8080



Solution

  • The token is signed and verified with a symmetric algorithm (HS256).
    The key parameters of the symmetric key are provided in form of a JSON Web Key in the local_jwks parameter in the Envoy configuration. The key value itself in the parameter "k" is supposed to be stored in Base64Url format:

    The "k" (key value) parameter contains the value of the symmetric (or other single-valued) key. It is represented as the base64url encoding of the octet sequence containing the key value.

    (see RFC7518 Section 6.4.1)

    Base64Url encoding is used here in order to be able to use binary keys (i.e keys in which every byte can have any value in the full range from 0 to 255) for signing.

    When the key is used for signing and verification, it has to be decoded to it's (potentially) binary form.

    To stick with the simple example key "helloworld" (of course, just for illustration, not as a real key), this key would have to be stored as "k":"aGVsbG93b3JsZA" (the base64url form of "helloworld") in the inline jwk in the configuration and used in the not encoded form "helloworld" to sign the token. The receiving side also uses the base64url decoded value of k to verify the signature.

    Summary:

    • create a binary key and base64url encode it
    • store the encoded key in the "k" parameter of the local_jwks parameter in the Envoy configuration
    • decode the value of "k" to use it as a key to verify or sign the token