Skip to content

Commit 419dd46

Browse files
committed
feat: publish only public key to JWKS
1 parent 2ed57b5 commit 419dd46

File tree

2 files changed

+49
-3
lines changed

2 files changed

+49
-3
lines changed

pkg/config/auth.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,44 @@ type JWK struct {
108108
Y string `json:"y,omitempty"`
109109
}
110110

111+
// ToPublicJWK converts a JWK to a public-only version by removing private key components
112+
func (j JWK) ToPublicJWK() JWK {
113+
publicJWK := JWK{
114+
KeyType: j.KeyType,
115+
KeyID: j.KeyID,
116+
Use: j.Use,
117+
Algorithm: j.Algorithm,
118+
Extractable: j.Extractable,
119+
}
120+
121+
// Only include key_ops for verification (not signing) for public keys
122+
if len(j.KeyOps) > 0 {
123+
var publicOps []string
124+
for _, op := range j.KeyOps {
125+
if op == "verify" {
126+
publicOps = append(publicOps, op)
127+
}
128+
}
129+
if len(publicOps) > 0 {
130+
publicJWK.KeyOps = publicOps
131+
}
132+
}
133+
134+
switch j.KeyType {
135+
case "RSA":
136+
// Include only public key components for RSA
137+
publicJWK.Modulus = j.Modulus
138+
publicJWK.Exponent = j.Exponent
139+
case "EC":
140+
// Include only public key components for ECDSA
141+
publicJWK.Curve = j.Curve
142+
publicJWK.X = j.X
143+
publicJWK.Y = j.Y
144+
}
145+
146+
return publicJWK
147+
}
148+
111149
type (
112150
auth struct {
113151
Enabled bool `toml:"enabled"`

pkg/config/config.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,17 +1441,25 @@ func (a *auth) ResolveJWKS(ctx context.Context, fsys afero.Fs) (string, error) {
14411441
jwks.Keys = append(jwks.Keys, rJWKS.Keys...)
14421442
}
14431443

1444-
// If SIGNING_KEYS_PATH is provided, read from file
1444+
// If SIGNING_KEYS_PATH is provided, read from file and convert to public keys
14451445
if len(a.SigningKeysPath) > 0 {
14461446
f, err := fsys.Open(a.SigningKeysPath)
14471447
if err != nil {
14481448
return "", errors.Errorf("failed to read signing key: %w", err)
14491449
}
1450-
jwtKeysArray, err := fetcher.ParseJSON[[]json.RawMessage](f)
1450+
jwtKeysArray, err := fetcher.ParseJSON[[]JWK](f)
14511451
if err != nil {
14521452
return "", err
14531453
}
1454-
jwks.Keys = append(jwks.Keys, jwtKeysArray...)
1454+
// Convert each signing key to public-only version
1455+
for _, key := range jwtKeysArray {
1456+
publicKey := key.ToPublicJWK()
1457+
publicKeyEncoded, err := json.Marshal(publicKey)
1458+
if err != nil {
1459+
return "", errors.Errorf("failed to marshal public key: %w", err)
1460+
}
1461+
jwks.Keys = append(jwks.Keys, json.RawMessage(publicKeyEncoded))
1462+
}
14551463
} else {
14561464
// Fallback to JWT_SECRET for backward compatibility
14571465
jwtSecret := secretJWK{

0 commit comments

Comments
 (0)