# JWT Security

On incoming requests, the `gm-jwt-security` filter creates a [jwt token](http://jwt.io/) from the [gm-jwt-security service](https://greymatter.gitbook.io/grey-matter-documentation/1.7-beta/usage/security/jwt) "/policies" endpoint using the incoming `USER_DN`. It passes the token along with the request in a `jwt` header.

## Gotchas

### Ordering

When using TLS and, in most instances, this filter should be applied *after* inheaders and impersonation. This is because the `userpolicyid` sent to the gm-jwt-security is taken from the `USER_DN` header. If the gm-jwt-security filter is applied *before* those headers, it could retrieve a token for the wrong `USER_DN` associated with the request, or you will receive a 407 response and see the error

```bash
gm-proxy_1_3c03fda44591 | {"level":"error","filter":"gm-jwt-security","error":"USER_DN must be present to retrieve jwt token from gm-jwt-security","time":"2020-01-30T17:58:37Z","message":"DecodeHeaders() - retrieving USER_DN header"}
```

### Header Length

Something to be careful of is the maximum size of headers allowed, as this can differ substantially between deployments. By default, the maximum header size for incoming requests is `60kb`.\* In production, we suggest a header size of no more than `30kb`, as gm-proxy dynamically adds, updates, and removes header values while processing filters. If a request header is too large for the proxy to handle, it will return the request with a [431 response code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/431).

`30kb` should support most `jwt` token sizes since the average jwt token from gm-jwt-security is about 500 bytes. If this is still too small for your header, you can consider:

* Set the parameter `max_request_headers_kb` to `96` in the `envoy.http_connection_manager` section of the proxy.\*\*
* Using an alternative approach to jwt authentication such as [cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) or [access tokens](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/identity).
* Process access control information within the sidecar.

Note that for outgoing requests from the gm-proxy, the maximum request header size is about `1mb`. This means that in some scenarios it's possible for a large `jwt` token to be added to outgoing headers but fail as an upstream request to another sidecar. Alternatively, the request could also succeed as an upstream request to external service, depending on the implementation.

* The maximum header size is the size of all headers added together. This was tested and verified locally. see [Envoy docs for more info](https://www.envoyproxy.io/docs/envoy/v1.15.0/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto).

*\** In testing, http/1.1 requests increase nicely to 96 KB (98,100 chars in header) but gRPC and http/2 requests start failing after a max of 74 KB. This could be because different protocols use different header [compression algorithms](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding)\*

## Filter Configuration Options

| Name                 | Type   | Default                    | Example                        | Description                                                                                                                                                                                                                       |
| -------------------- | ------ | -------------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `apiKey`             | string | \[empty]                   | MTIzCg==                       | Api key used in request to gm-jwt-security                                                                                                                                                                                        |
| `endpoint`           | string | \[empty]                   | <https://gm-jwt-security:9443> | Endpoint of gm-jwt-security                                                                                                                                                                                                       |
| `jwtHeaderName`      | string | "jwt"                      | "custom-header-name"           | Header in which the jwt token is put                                                                                                                                                                                              |
| `useTls`             | bool   | false                      | --                             | Should the filter use certs in connecting to gm-jwt-security?                                                                                                                                                                     |
| `certPath`           | string | "./certs/server.crt"       | --                             | Certificate path                                                                                                                                                                                                                  |
| `keyPath`            | string | "./certs/server.key"       | --                             | Keyfile path                                                                                                                                                                                                                      |
| `caPath`             | string | "./certs/intermediate.crt" | --                             | Certificate authority or intermediate certificate path                                                                                                                                                                            |
| `insecureSkipVerify` | bool   | false                      | --                             | Should calls to gm-jwt-security require hostname verification in certs? Should be used only for testing. See [go docs](https://golang.org/pkg/crypto/tls/) for more information.                                                  |
| `timeoutMs`          | int    | 1000ms                     | --                             | Timeout in milliseconds for the connection between gm-proxy and gm-jwt-security service. Set to a negative number to disable timeouts completely, though **this is not advised** as it can cause an infinite hang in the sidecar. |
| `maxRetries`         | int    | 0                          | --                             | Number of retries after failed connection between gm-proxy and gm-jwt-security service                                                                                                                                            |
| `retryDelayMs`       | int    | 0                          | --                             | Amount of time in milliseconds between each unsuccessful retry                                                                                                                                                                    |
| `cacheLimit`         | int    | 100                        | --                             | Maximum number of tokens held in cache. If negative, caching is disabled, **must be > 0 to enable caching**                                                                                                                       |
| `cachedTokenExp`     | int    | 10m                        | --                             | Time in minutes to hold tokens in the cache. If negative, caching is disabled, **must be > 0 to enable caching**                                                                                                                  |

## Flow Chart

![](https://lucid.app/publicSegments/view/4abfa28a-71eb-4d3d-93d5-5462710da5b8/image.jpeg)
