A Cloud Run service that exchanges API keys for signed JWTs for M-Lab services.
| Method | Path | Description |
|---|---|---|
POST |
/v0/token/autojoin |
Exchange autojoin API key for JWT token |
POST |
/v0/token/integration |
Exchange client integration API key for JWT token |
GET |
/.well-known/jwks.json |
Serve JSON Web Key Set for token verification |
GET |
/health |
Health check endpoint |
# Build all packages
go build -v ./...
# Run all tests with race detection
go test -race -v ./...
# Run tests with coverage
go test -coverprofile=coverage.out -coverpkg=./... ./...# Build Docker image
docker build -t token-exchange .gcloud builds submit --config cloudbuild.yamlConfiguration is via command-line flags. All flags can also be set via environment variables (e.g., -port becomes PORT, -platform-ns becomes PLATFORM_NS).
| Flag | Default | Description |
|---|---|---|
-port |
8080 |
Port to listen on |
-private-key-path |
/secrets/jwk-priv.json |
Path to JWK private key file |
-platform-ns |
platform-credentials |
Datastore namespace for autojoin credentials |
-client-integration-ns |
client-integration |
Datastore namespace for client integration credentials |
-project-id |
mlab-sandbox |
Google Cloud project ID |
Creates a new client integration and API key in Datastore.
go run ./cmd/create-integration -project=mlab-sandbox -integration-id=my-integration| Flag | Default | Description |
|---|---|---|
-project |
(required) | Google Cloud project ID |
-integration-id |
(required) | Integration ID |
-namespace |
client-integration |
Datastore namespace |
-key-id |
(auto-generated) | Key ID |
-integration-description |
Human-readable description for the integration | |
-key-description |
Human-readable description for the API key | |
-key-tier |
0 |
Service tier for the API key |
Exchange an API key for a short-lived JWT token.
Request:
curl -X POST https://your-service-url/v0/token/integration \
-H "Content-Type: application/json" \
-d '{"api_key": "your-api-key"}'Response:
{
"token": "eyJhbGciOiJSUzI1NiIsImtpZCI6Ii..."
}JWT Claims:
| Claim | Description |
|---|---|
int_id |
Integration ID |
key_id |
API Key ID |
tier |
Service tier |
aud |
Audience (integration) |
exp |
Expiration time (20 seconds from issue) |
iat |
Issued at time |
iss |
Issuer |
jti |
Unique token ID |
nbf |
Not valid before time |
Error Responses:
| Status | Description |
|---|---|
400 Bad Request |
Invalid request body |
401 Unauthorized |
Invalid API key |
405 Method Not Allowed |
Request method is not POST |
500 Internal Server Error |
Failed to generate token |
The service validates API keys stored in Google Cloud Datastore and returns signed JWT tokens. Tokens are signed using RS256 with keys loaded from a JWK file.
sequenceDiagram
participant Client
participant TokenExchange
participant Datastore
Client->>TokenExchange: POST /v0/token/integration (API key)
TokenExchange->>Datastore: Validate API key
Datastore-->>TokenExchange: Integration info
TokenExchange->>TokenExchange: Generate JWT (20-second expiry)
TokenExchange-->>Client: Signed JWT token