1. Rejections are logged. chassis v0.2.0 refused without a log line, so since #149 an unknown REST caller got silent 401s. v0.7.1 writes `mcp auth rejected` (reason, remote, token fingerprint, path) and `mcp auth accepted` per authenticated request. Tested through buildMux. 2. Fallout: since chassis v0.7 (mcp-chassis#4) NewJWTValidator no longer fails on OIDC discovery; the issuer resolves lazily and a JWT gets 503-and-retry until it does. #83's boot retry loop therefore never retried, and its tests failed. buildJWTValidator now builds once and logs an issuer still unresolved at boot. Behaviour change: a misconfigured issuer no longer exits the process; JWTs get 503, the static bearer keeps working. internal/startupretry is now unused. 3. Metrics: authenticated REST requests were already labelled by route (the REST mux sets Pattern on the same *http.Request the middleware reads). Requests refused by auth never reached the REST mux and were labelled path="/". labelRESTPattern now sets the REST route's pattern before auth; unmatched paths keep "/", so the label set stays bounded. Closes #155 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
27 lines
1003 B
Go
27 lines
1003 B
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log/slog"
|
|
|
|
chassisauth "git.d-ma.be/mathias/mcp-chassis/auth"
|
|
)
|
|
|
|
// buildJWTValidator builds the JWT validator for issuer (nil when issuer is
|
|
// empty: JWT auth disabled). Since mcp-chassis v0.7 construction no longer
|
|
// fails when OIDC discovery does (mcp-chassis#4): the issuer resolves lazily,
|
|
// and until it does a JWT is answered 503-and-retry, not 401. That replaces
|
|
// #83's boot-time retry loop (hyperguild#155). An issuer still unresolved at
|
|
// boot is logged, so a misconfigured issuer is visible rather than silent.
|
|
func buildJWTValidator(ctx context.Context, logger *slog.Logger, issuer, audience string) (*chassisauth.JWTValidator, error) {
|
|
v, err := chassisauth.NewJWTValidator(ctx, issuer, audience)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("build jwt validator: %w", err)
|
|
}
|
|
if ok, rerr := v.Ready(ctx); !ok {
|
|
logger.Warn("jwt issuer not resolved at boot; JWTs answer 503 until it is", "issuer", issuer, "err", rerr)
|
|
}
|
|
return v, nil
|
|
}
|