Awesome
jcp
This is a JWK Set client proxy, JCP for short. It is used to validate JWTs that were signed by a key that lives in a remote JWK Set. JCP caches the JWK Set in memory and automatically refreshes the JWK Set as configured.
This project serves a few primary use cases:
- The language or shell a program is written in does not have an adequate JWK Set client. Validate JWTs with
curl
? Why not? - Restrictive networking policies prevent a program from accessing the remote JWK Set directly.
- Many co-located services need to validate JWTs that were signed by a key that lives in a remote JWK Set.
It is recommended that JCP is hosted in the same environment (data center) as the program verifying JWTs to reduce latency.
flowchart LR
subgraph Public Internet
J[Remote JWK Set]
end
subgraph Your Datacenter
Y[Your code]
JCP
end
Y-->JCP
JCP-->Y
JCP-->J
J-->JCP
API Specifications
This proxy server implements a Swagger 2.0 and OpenAPI 3 specification. Please see swagger.yml
for the Swagger 2.0
specification and openapi.yml
for the OpenAPI 3 specification.
These specification files can be used to generate client code for your favorite language. However, there is only one small endpoint for JWT validation so hand-coding a client is reasonable.
Installation
This project can be installed via a Docker or using the Go toolchain.
Docker
Pull the image:
docker pull micahparks/jcp
See docker-compose.yml
for a working Docker Compose example.
Go
Confirm you have Go installed. The minimum required version can be found in go.mod
.
go install github.com/MicahParks/jcp/cmd/proxy@latest
Or you can compile the by downloading this repository, making it your current working directory and running the below commands:
cd cmd/proxy/
go build
After these commands have been run, the proxy
executable will be in the cmd/proxy/
directory.
Validation features
Below is a table of JWT registered claims and the validation behavior of JCP.
JWT Validation Type | Behavior |
---|---|
Cryptographic signature | automatic |
alg header | automatic |
exp claim | automatic |
iat claim | automatic |
nbf claim | automatic |
aud claim | per request |
iss claim | per request |
sub claim | per request |
Configuration
This project is configured via JSON. This program will check three places for this configuration JSON on startup in this order:
- The
CONFIG_JSON
environment variable's raw contents. - The
CONFIG_PATH
environment variable will be read. If non-empty, it will attempt to parse the file at that path. - The
config.json
file in the current working directory.
Configuration JSON structure
{
"jwks": {
"https://example.com/jwks.json": {
"refreshInterval": "1h",
"refreshTimeout": "10s"
}
},
"listenAddress": ":8080",
"logFormat": "json",
"requestMaxBytes": 1048576
}
JSON Attribute | Description | Example | Default Value | Required |
---|---|---|---|---|
jwks | An object mapping remote JWK Set URLs to their options. | see above | none | required |
refreshInterval | The amount of time to wait before automatically refreshing the remote JWK Set resource. It uses Go syntax for time.ParseDuration . | 1h30m5s | 1h | optional |
refreshTimeout | The amount of time to wait failing a remote JWK Set refresh due to a timeout. It uses Go syntax for time.ParseDuration . | 5s | 10s | optional |
listenAddress | The address to listen on. It uses Go syntax for net.Listen . | :3000 | :8080 | optional |
logFormat | The format to log in. This determines which zap output logging is used. Valid values are human and json . | human | json | optional |
requestMaxBytes | The maximum number of bytes to read from the request body. | 10000 | 1048576 | optional |
For most use cases, ensure all JWK Set URLs are HTTPS to prevent MITM attacks.
Test coverage
This project currently has greater than 90%
test coverage:
$ go test -cover -race
PASS
coverage: 91.1% of statements
ok github.com/MicahParks/jcp 0.043s
Local debug setup
Run these commands in the listed order in separate terminals.
Start a local JWK Set server:
go run cmd/local_jwkset/main.go
Start the JCP server (debugger instructions not shown):
CONFIG_PATH=config.local.json go run cmd/proxy/main.go
References
This project was built on the following JSON Object Signing and Encryption (JOSE) related libraries: