66 "crypto/ecdsa"
77 "crypto/ed25519"
88 "crypto/rsa"
9+ "encoding/json"
910 "errors"
1011 "fmt"
1112 "io"
@@ -235,6 +236,55 @@ func (r *RemoteKeySet) keysFromRemote(ctx context.Context) ([]jose.JSONWebKey, e
235236 }
236237}
237238
239+ // jwkJSON implements custom logic for unmarshaling JSON Web Key Sets.
240+ type jwkJSON struct {
241+ Keys []jose.JSONWebKey
242+ }
243+
244+ func (j * jwkJSON ) UnmarshalJSON (data []byte ) error {
245+ var raw struct {
246+ Keys []json.RawMessage `json:"keys"`
247+ }
248+ if err := json .Unmarshal (data , & raw ); err != nil {
249+ return err
250+ }
251+ // For each key, attempt to determine if the algorithm is supported before
252+ // unmarshaling the key. This allows us to ignore keys with unsupported
253+ // algorithms, rather than failing to load the entire set.
254+ for _ , key := range raw .Keys {
255+ var metadata struct {
256+ Alg string `json:"alg"`
257+ }
258+ if err := json .Unmarshal (key , & metadata ); err != nil {
259+ return err
260+ }
261+ if metadata .Alg != "" {
262+ // Algorithms are technically optional, but if the key advertises an
263+ // algorithm we don't support, ignore it rather than failing to load
264+ // the entire key set.
265+ //
266+ // https://datatracker.ietf.org/doc/html/rfc7517#section-4.4
267+ //
268+ // This skip is currently implemented due to secp256k1, which some
269+ // providers use for signing with "ES256K". While we could also
270+ // ignore the curve, this seems like a more general check in case
271+ // providers start throwing in post-quantum algorithims or something
272+ // like that.
273+ //
274+ // https://github.com/coreos/go-oidc/issues/490
275+ if ! supportedJOSEAlgs [metadata .Alg ] {
276+ continue
277+ }
278+ }
279+ var jwk jose.JSONWebKey
280+ if err := json .Unmarshal (key , & jwk ); err != nil {
281+ return err
282+ }
283+ j .Keys = append (j .Keys , jwk )
284+ }
285+ return nil
286+ }
287+
238288func (r * RemoteKeySet ) updateKeys () ([]jose.JSONWebKey , error ) {
239289 req , err := http .NewRequest ("GET" , r .jwksURL , nil )
240290 if err != nil {
@@ -257,7 +307,7 @@ func (r *RemoteKeySet) updateKeys() ([]jose.JSONWebKey, error) {
257307 return nil , fmt .Errorf ("oidc: get keys failed: %s %s" , resp .Status , body )
258308 }
259309
260- var keySet jose. JSONWebKeySet
310+ var keySet jwkJSON
261311 err = unmarshalResp (resp , body , & keySet )
262312 if err != nil {
263313 return nil , fmt .Errorf ("oidc: failed to decode keys: %v %s" , err , body )
0 commit comments