{"id":24171307,"url":"https://github.com/micahparks/jcp","last_synced_at":"2025-03-02T12:27:49.922Z","repository":{"id":65071826,"uuid":"581376419","full_name":"MicahParks/jcp","owner":"MicahParks","description":"A JWK Set client proxy.","archived":false,"fork":false,"pushed_at":"2024-09-07T13:27:28.000Z","size":19,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-13T00:37:11.328Z","etag":null,"topics":["jwk","jwks","jwkset","jwt","proxy","proxy-server"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MicahParks.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":"MicahParks"}},"created_at":"2022-12-23T02:25:27.000Z","updated_at":"2024-05-28T19:13:20.000Z","dependencies_parsed_at":"2022-12-29T21:46:41.908Z","dependency_job_id":null,"html_url":"https://github.com/MicahParks/jcp","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MicahParks%2Fjcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MicahParks%2Fjcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MicahParks%2Fjcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MicahParks%2Fjcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MicahParks","download_url":"https://codeload.github.com/MicahParks/jcp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241505722,"owners_count":19973465,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["jwk","jwks","jwkset","jwt","proxy","proxy-server"],"created_at":"2025-01-13T00:37:14.677Z","updated_at":"2025-03-02T12:27:49.916Z","avatar_url":"https://github.com/MicahParks.png","language":"Go","funding_links":["https://github.com/sponsors/MicahParks"],"categories":[],"sub_categories":[],"readme":"# jcp\n\nThis is a [JWK Set](https://www.rfc-editor.org/rfc/rfc7517) client proxy, JCP for short. It is used to validate JWTs\nthat were signed by a key that lives in a remote JWK Set. JCP caches the JWK Set in memory and automatically refreshes\nthe JWK Set as configured.\n\nThis project serves a few primary use cases:\n\n1. The language or shell a program is written in does not have an adequate JWK Set client. Validate JWTs with `curl`?\n   Why not?\n2. Restrictive networking policies prevent a program from accessing the remote JWK Set directly.\n3. Many co-located services need to validate JWTs that were signed by a key that lives in a remote JWK Set.\n\nIt is recommended that JCP is hosted in the same environment (data center) as the program verifying JWTs to reduce\nlatency.\n\n```mermaid\nflowchart LR\n    subgraph Public Internet\n    J[Remote JWK Set]\n    end\n    subgraph Your Datacenter\n    Y[Your code]\n    JCP\n    end\n    Y--\u003eJCP\n    JCP--\u003eY\n    JCP--\u003eJ\n    J--\u003eJCP\n```\n\n# API Specifications\n\nThis proxy server implements a Swagger 2.0 and OpenAPI 3 specification. Please see `swagger.yml` for the Swagger 2.0\nspecification and `openapi.yml` for the OpenAPI 3 specification.\n\nThese specification files can be used to generate client code for your favorite language. However, there is only one\nsmall endpoint for JWT validation so hand-coding a client is reasonable.\n\n# Installation\n\nThis project can be installed via a Docker or using the Go toolchain.\n\n## Docker\n\nPull the image:\n\n```bash\ndocker pull micahparks/jcp\n```\n\nSee `docker-compose.yml` for a working Docker Compose example.\n\n## Go\n\nConfirm you have [Go installed](https://go.dev/). The minimum required version can be found in `go.mod`.\n\n```bash\ngo install github.com/MicahParks/jcp/cmd/proxy@latest\n```\n\nOr you can compile the by downloading this repository, making it your current working directory and running the below\ncommands:\n\n```bash\ncd cmd/proxy/\ngo build\n```\n\nAfter these commands have been run, the `proxy` executable will be in the `cmd/proxy/` directory.\n\n# Validation features\n\nBelow is a table of [JWT registered claims](https://www.rfc-editor.org/rfc/rfc7519#section-4.1) and the validation\nbehavior of JCP.\n\n| JWT Validation Type     | Behavior    |\n|-------------------------|-------------|\n| Cryptographic signature | automatic   |\n| `alg` header            | automatic   |\n| `exp` claim             | automatic   |\n| `iat` claim             | automatic   |\n| `nbf` claim             | automatic   |\n| `aud` claim             | per request |\n| `iss` claim             | per request |\n| `sub` claim             | per request |\n\n# Configuration\n\nThis project is configured via JSON. This program will check three places for this configuration JSON on startup in this\norder:\n\n1. The `CONFIG_JSON` environment variable's raw contents.\n2. The `CONFIG_PATH` environment variable will be read. If non-empty, it will attempt to parse the file at that path.\n3. The `config.json` file in the current working directory.\n\n## Configuration JSON structure\n\n```json\n{\n  \"jwks\": {\n    \"https://example.com/jwks.json\": {\n      \"refreshInterval\": \"1h\",\n      \"refreshTimeout\": \"10s\"\n    }\n  },\n  \"listenAddress\": \":8080\",\n  \"logFormat\": \"json\",\n  \"requestMaxBytes\": 1048576\n}\n```\n\n| JSON Attribute    | Description                                                                                                                                                                  | Example   | Default Value | Required |\n|-------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------|---------------|----------|\n| `jwks`            | An object mapping remote JWK Set URLs to their options.                                                                                                                      | see above | none          | required |\n| `refreshInterval` | The amount of time to wait before automatically refreshing the remote JWK Set resource. It uses [Go syntax for `time.ParseDuration`](https://pkg.go.dev/time#ParseDuration). | `1h30m5s` | `1h`          | optional |\n| `refreshTimeout`  | The amount of time to wait failing a remote JWK Set refresh due to a timeout. It uses [Go syntax for `time.ParseDuration`](https://pkg.go.dev/time#ParseDuration).           | `5s`      | `10s`         | optional |\n| `listenAddress`   | The address to listen on. It uses [Go syntax for `net.Listen`](https://pkg.go.dev/net#Listen).                                                                               | `:3000`   | `:8080`       | optional |\n| `logFormat`       | The format to log in. This determines which [zap](https://github.com/uber-go/zap) output logging is used. Valid values are `human` and `json`.                               | `human`   | `json`        | optional |\n| `requestMaxBytes` | The maximum number of bytes to read from the request body.                                                                                                                   | `10000`   | `1048576`     | optional |\n\nFor most use cases, ensure all JWK Set URLs are HTTPS to\nprevent [MITM attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack).\n\n# Test coverage\n\nThis project currently has greater than `90%` test coverage:\n\n```\n$ go test -cover -race\nPASS\ncoverage: 91.1% of statements\nok      github.com/MicahParks/jcp   0.043s\n```\n\n# Local debug setup\n\nRun these commands in the listed order in separate terminals.\n\nStart a local JWK Set server:\n\n```bash\ngo run cmd/local_jwkset/main.go\n```\n\nStart the JCP server (debugger instructions not shown):\n\n```bash\nCONFIG_PATH=config.local.json go run cmd/proxy/main.go\n```\n\n# References\n\nThis project was built on the following JSON Object Signing and Encryption (JOSE) related libraries:\n\n* [`github.com/golang-jwt/jwt/v4`](https://github.com/golang-jwt/jwt)\n* [`github.com/MicahParks/jwkset`](https://github.com/MicahParks/jwkset) (testing only)\n* [`github.com/MicahParks/keyfunc`](https://github.com/MicahParks/keyfunc)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmicahparks%2Fjcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmicahparks%2Fjcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmicahparks%2Fjcp/lists"}