diff --git a/example_jwks.json b/example_jwks.json index 5fcd256..22084e0 100644 --- a/example_jwks.json +++ b/example_jwks.json @@ -118,19 +118,6 @@ "use": "sig", "kid": "hmac", "k": "V_8Ob8dVs6JuZx6expyjShoUgFgxoaovGjmGhesL2jA" - }, - { - "kty": "RSA", - "use": "enc", - "kid": "WW91IGdldCBhIGdvbGQgc3RhciDwn4yfCg", - "alg": "RSA-OAEP", - "n": "ja99ybDrLvw11Z4CvNlDI-kkqJEBpSnvDf0pZF2DvBlvYmeVYL_ChqIe8E9GyHUmLMdtO_jifSgOqE5b8vILwi1kZnJR7N857uEnbWM9YTeevi_RZ-E_hr4frW2NKJ78YGvCzwLKG2GgtSjj0zuTLnSaK8fCGzqXgy6paXNhgHUSZgGwvO0YItpMlyJeqEj1wGTWz1IyA1sguF1cC7K0fojPbPoBwrhvaAeoGRPLraE0rrBsQv8iiLwnRBIez9B1j0NiUG8Iad953Y7UzaKOAw8crIEK45NIK_yxHUpxqcHLjPIcRyIyJGioRyGK7cp-_7iPLOCutQc-u46mom1_ZQ", - "e": "AQAB", - "x5c": [ - "MIICmzCCAYMCBgF4BJRpbzANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjEwMzA1MjI0NzE4WhcNMzEwMzA1MjI0ODU4WjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCNr33JsOsu/DXVngK82UMj6SSokQGlKe8N/SlkXYO8GW9iZ5Vgv8KGoh7wT0bIdSYsx207+OJ9KA6oTlvy8gvCLWRmclHs3znu4SdtYz1hN56+L9Fn4T+Gvh+tbY0onvxga8LPAsobYaC1KOPTO5MudJorx8IbOpeDLqlpc2GAdRJmAbC87Rgi2kyXIl6oSPXAZNbPUjIDWyC4XVwLsrR+iM9s+gHCuG9oB6gZE8utoTSusGxC/yKIvCdEEh7P0HWPQ2JQbwhp33ndjtTNoo4DDxysgQrjk0gr/LEdSnGpwcuM8hxHIjIkaKhHIYrtyn7/uI8s4K61Bz67jqaibX9lAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAHrGJFhVNiQupIwkn2jiW/jBobm9CHUxOwQL5E7WdRz5uaOJ0v62PrynOQE9xim9Qk8bT3q7DThZs66U9bpIk3msKVRgXRfn5FZy1H5RKOlEEFZhGakPqSlC1yPbhUNhHXMs3GTzdGMLtYaGvSy6XM/8/zqVqVwgh6BpbAR9RfiSdyaiNTSBriu+n/tHW934G9J8UIzdfpVcb0Yt9y4o0UgIXt64NtGFq7zmNJijH88AxBZFB6eUUmQQCczebzoAjyYbVOes5gGFzboVWcyLe3iyD0vvsAVHJViXeiGoxhpKnc8ryISpRUBzsKngf5uZo3bnrD9PHLYBoGOHgzII1xw=" - ], - "x5t": "5GNr3LeRXHWI4YR8-QTSsF98oTI", - "x5t#S256": "Dgd0_wZZqvRuf4GEISPNHREX-1ixTMIsrPeGzk0bCxs" } ] } \ No newline at end of file diff --git a/get.go b/get.go index f1446e8..3b45917 100644 --- a/get.go +++ b/get.go @@ -35,9 +35,6 @@ func Get(jwksURL string, options Options) (jwks *JWKS, err error) { if jwks.refreshTimeout == 0 { jwks.refreshTimeout = defaultRefreshTimeout } - if len(jwks.allowedJWKUses) == 0 { - jwks.allowedJWKUses = []JWKUse{UseSignature, UseOmitted} - } err = jwks.refresh() if err != nil { @@ -184,7 +181,7 @@ func (j *JWKS) refresh() (err error) { } } - j.keys[kid] = parsedKey{public: key.inter} + j.keys[kid] = key.inter } } diff --git a/given.go b/given.go index 18141c5..f7bf6ad 100644 --- a/given.go +++ b/given.go @@ -13,10 +13,10 @@ type GivenKey struct { // NewGiven creates a JWKS from a map of given keys. func NewGiven(givenKeys map[string]GivenKey) (jwks *JWKS) { - keys := make(map[string]parsedKey) + keys := make(map[string]interface{}) for kid, given := range givenKeys { - keys[kid] = parsedKey{public: given.inter} + keys[kid] = given.inter } return &JWKS{ diff --git a/jwks.go b/jwks.go index 55b8b23..2f5104b 100644 --- a/jwks.go +++ b/jwks.go @@ -15,23 +15,11 @@ var ( // ErrMissingAssets indicates there are required assets are missing to create a public key. ErrMissingAssets = errors.New("required assets are missing to create a public key") - - // ErrJWKUse indicates that the given key was found in the JWKS, but that the use was not allowed. - ErrJWKUse = errors.New("the given key ID was found but the key use is not allowed") ) // ErrorHandler is a function signature that consumes an error. type ErrorHandler func(err error) -// JWKUse specifies a `use` for a JWK -type JWKUse string - -const ( - UseEncryption JWKUse = "enc" - UseOmitted JWKUse = "" - UseSignature JWKUse = "sig" -) - // jsonWebKey represents a raw key inside a JWKS. type jsonWebKey struct { Curve string `json:"crv"` @@ -40,20 +28,12 @@ type jsonWebKey struct { ID string `json:"kid"` Modulus string `json:"n"` Type string `json:"kty"` - Use string `json:"use"` X string `json:"x"` Y string `json:"y"` } -// parsedKey represents a parsed JWK with assoicated metadata -type parsedKey struct { - use JWKUse - public interface{} -} - // JWKS represents a JSON Web Key Set (JWK Set). type JWKS struct { - allowedJWKUses []JWKUse cancel context.CancelFunc client *http.Client ctx context.Context @@ -61,7 +41,7 @@ type JWKS struct { givenKeys map[string]GivenKey givenKIDOverride bool jwksURL string - keys map[string]parsedKey + keys map[string]interface{} mux sync.RWMutex refreshErrorHandler ErrorHandler refreshInterval time.Duration @@ -88,7 +68,7 @@ func NewJSON(jwksBytes json.RawMessage) (jwks *JWKS, err error) { // Iterate through the keys in the raw JWKS. Add them to the JWKS. jwks = &JWKS{ - keys: make(map[string]parsedKey, len(rawKS.Keys)), + keys: make(map[string]interface{}, len(rawKS.Keys)), } for _, key := range rawKS.Keys { var keyInter interface{} @@ -118,10 +98,7 @@ func NewJSON(jwksBytes json.RawMessage) (jwks *JWKS, err error) { continue } - jwks.keys[key.ID] = parsedKey{ - use: JWKUse(key.Use), - public: keyInter, - } + jwks.keys[key.ID] = keyInter } return jwks, nil @@ -169,7 +146,7 @@ func (j *JWKS) ReadOnlyKeys() map[string]interface{} { keys := make(map[string]interface{}) j.mux.Lock() for kid, cryptoKey := range j.keys { - keys[kid] = cryptoKey.public + keys[kid] = cryptoKey } j.mux.Unlock() return keys @@ -178,50 +155,35 @@ func (j *JWKS) ReadOnlyKeys() map[string]interface{} { // getKey gets the jsonWebKey from the given KID from the JWKS. It may refresh the JWKS if configured to. func (j *JWKS) getKey(kid string) (jsonKey interface{}, err error) { j.mux.RLock() - parsedKey, ok := j.keys[kid] + jsonKey, ok := j.keys[kid] j.mux.RUnlock() if !ok { - if !j.refreshUnknownKID { - return nil, ErrKIDNotFound - } - - ctx, cancel := context.WithCancel(j.ctx) - - // Refresh the JWKS. - select { - case <-j.ctx.Done(): - return - case j.refreshRequests <- cancel: - default: - // If the j.refreshRequests channel is full, return the error early. - return nil, ErrKIDNotFound - } - - // Wait for the JWKS refresh to finish. - <-ctx.Done() + if j.refreshUnknownKID { + ctx, cancel := context.WithCancel(j.ctx) + + // Refresh the JWKS. + select { + case <-j.ctx.Done(): + return + case j.refreshRequests <- cancel: + default: + // If the j.refreshRequests channel is full, return the error early. + return nil, ErrKIDNotFound + } - j.mux.RLock() - defer j.mux.RUnlock() - if parsedKey, ok = j.keys[kid]; !ok { - return nil, ErrKIDNotFound - } - } + // Wait for the JWKS refresh to finish. + <-ctx.Done() - // allowedJWKUses might be empty if the jwks was from keyfunc.NewJSON() - if len(j.allowedJWKUses) > 0 { - found := false - for _, use := range j.allowedJWKUses { - if parsedKey.use == use { - found = true - break + j.mux.RLock() + defer j.mux.RUnlock() + if jsonKey, ok = j.keys[kid]; ok { + return jsonKey, nil } } - if !found { - return nil, ErrJWKUse - } + return nil, ErrKIDNotFound } - return parsedKey.public, nil + return jsonKey, nil } diff --git a/jwks_test.go b/jwks_test.go index 052314f..d19ff34 100644 --- a/jwks_test.go +++ b/jwks_test.go @@ -3,10 +3,6 @@ package keyfunc_test import ( "bytes" "context" - "crypto/ecdsa" - "crypto/ed25519" - "crypto/rsa" - _ "embed" "errors" "fmt" "net/http" @@ -32,12 +28,9 @@ const ( // jwksFilePath is the full path of th JWKS file on the test HTTP server. jwksFilePath = "/example_jwks.json" -) -var ( - // jwksJSON is a embedded JWKS in JSON format. - //go:embed example_jwks.json - jwksJSON string + // jwksJSON is a hard-coded JWKS in JSON format. + jwksJSON = `{"keys":[{"kid":"zXew0UJ1h6Q4CCcd_9wxMzvcp5cEBifH0KWrCz2Kyxc","kty":"RSA","alg":"PS256","use":"sig","n":"wqS81x6fItPUdh1OWCT8p3AuLYgFlpmg61WXp6sp1pVijoyF29GOSaD9xE-vLtegX-5h0BnP7va0bwsOAPdh6SdeVslEifNGHCtID0xNFqHNWcXSt4eLfQKAPFUq0TsEO-8P1QHRq6yeG8JAFaxakkaagLFuV8Vd_21PGJFWhvJodJLhX_-Ym9L8XUpIPps_mQriMUOWDe-5DWjHnDtfV7mgaOxbBvVo3wj8V2Lmo5Li4HabT4MEzeJ6e9IdFo2kj_44Yy9osX-PMPtu8BQz_onPgf0wjrVWt349Rj6OkS8RxlNGYeuIxYZr0TOhP5F-yEPhSXDsKdVTwPf7zAAaKQ","e":"AQAB","x5c":["MIICmzCCAYMCBgF4HR7HNDANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjEwMzEwMTcwOTE5WhcNMzEwMzEwMTcxMDU5WjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCpLzXHp8i09R2HU5YJPyncC4tiAWWmaDrVZenqynWlWKOjIXb0Y5JoP3ET68u16Bf7mHQGc/u9rRvCw4A92HpJ15WyUSJ80YcK0gPTE0Woc1ZxdK3h4t9AoA8VSrROwQ77w/VAdGrrJ4bwkAVrFqSRpqAsW5XxV3/bU8YkVaG8mh0kuFf/5ib0vxdSkg+mz+ZCuIxQ5YN77kNaMecO19XuaBo7FsG9WjfCPxXYuajkuLgdptPgwTN4np70h0WjaSP/jhjL2ixf48w+27wFDP+ic+B/TCOtVa3fj1GPo6RLxHGU0Zh64jFhmvRM6E/kX7IQ+FJcOwp1VPA9/vMABopAgMBAAEwDQYJKoZIhvcNAQELBQADggEBALILq1Z4oQNJZEUt24VZcvknsWtQtvPxl3JNcBQgDR5/IMgl5VndRZ9OT56KUqrR5xRsWiCvh5Lgv4fUEzAAo9ToiPLub1SKP063zWrvfgi3YZ19bty0iXFm7l2cpQ3ejFV7WpcdLJE0lapFdPLo6QaRdgNu/1p4vbYg7zSK1fQ0OY5b3ajhAx/bhWlrN685owRbO5/r4rUOa6oo9l4Qn7jUxKUx4rcoe7zUM7qrpOPqKvn0DBp3n1/+9pOZXCjIfZGvYwP5NhzBDCkRzaXcJHlOqWzMBzyovVrzVmUilBcj+EsTYJs0gVXKzduX5zO6YWhFs23lu7AijdkxTY65YM0="],"x5t":"IYIeevIT57t8ppUejM42Bqx6f3I","x5t#S256":"TuOrBy2NcTlFSWuZ8Kh8W8AjQagb4fnfP1SlKMO8-So"},{"kid":"ebJxnm9B3QDBljB5XJWEu72qx6BawDaMAhwz4aKPkQ0","kty":"EC","alg":"ES512","use":"sig","crv":"P-521","x":"YQ95Xj8MTzcHytbU1h8YkCN2kdEQA7ThuZ1ctB9Ekiw6tlM9RwL62eQvzEt4Rz8qN69uRqgU9RzxQOkSU5xVvyo","y":"SMMuP3QnAPHtx7Go2ARsG3NBaySWBLmVvS8s2Ss7Vm_ISWenNbdjKOsY1XvtiQz5scGzWDCEUoZzgV8Ve1mLOV0"},{"kid":"TVAAet63O3xy_KK6_bxVIu7Ra3_z1wlB543Fbwi5VaU","kty":"EC","alg":"ES384","use":"sig","crv":"P-384","x":"Pik2o5as-evijFABH5p6YLXHnWw8iQ_N1ummPY1c_UgG6NO0za-gNOhTz2-tsd_w","y":"e98VSff71k19SY_mHgp3707lgQVrhfVpiGa-sGaKxOWVpxd2jWMhB0Q4RpSRuCp5"},{"kid":"arlUxX4hh56rNO-XdIPhDT7bqBMqcBwNQuP_TnZJNGs","kty":"RSA","alg":"RS512","use":"sig","n":"hhtifu8LL3ICE3BAX5l1KZv6Lni0lhlhBusSfepnpxcb4C_z2U71cQTnLY27kt8WB4bNG6e5_KMx9K3xUdd3euj9MCq8vytwEPieeHE1KXQuhJfLv017lhpK_dRMOHyc-9-50YNdgs_8KWRkrzjjuYrCiO9Iu76n5319e-SC8OPvNUglqxp2N0Sp2ltne2ZrpN8T3OEEXT62TSGmLAVopRGw5gllNVrJfmEyZJCRrBM6s5CQcz8un0FjkAAC4DI6QD-eBL0qG3_NR0hQvR1he2o4BLwjOKH45Pk_jj-eArp-DD6Xq6ABQVb5SNOSdaxl5lnmuotRoY3G5d9YSl-K3w","e":"AQAB","x5c":["MIICmzCCAYMCBgF4HSCcDzANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjEwMzEwMTcxMTE5WhcNMzEwMzEwMTcxMjU5WjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCGG2J+7wsvcgITcEBfmXUpm/oueLSWGWEG6xJ96menFxvgL/PZTvVxBOctjbuS3xYHhs0bp7n8ozH0rfFR13d66P0wKry/K3AQ+J54cTUpdC6El8u/TXuWGkr91Ew4fJz737nRg12Cz/wpZGSvOOO5isKI70i7vqfnfX175ILw4+81SCWrGnY3RKnaW2d7Zmuk3xPc4QRdPrZNIaYsBWilEbDmCWU1Wsl+YTJkkJGsEzqzkJBzPy6fQWOQAALgMjpAP54EvSobf81HSFC9HWF7ajgEvCM4ofjk+T+OP54Cun4MPperoAFBVvlI05J1rGXmWea6i1Ghjcbl31hKX4rfAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAB7bpwPoL02WGCCVhCsbDkq9GeFUwF01opVyFTijZlTUoTf5RcaR2qAH9/irkLjZeFeyozzC5mGvIVruBwnx/6l4PcAMxKK4YiheFVoO/dytpGMCj6ToNmKpjlXzOLAHelieWIUDtAFSYzENjIO01PyXTGYpxebpQCocJBvppj5HqARS9iNPcqBltMhxWrWmMu81tOG3Y7yd2xsIYXk6KjaoefLeN8Was4BPJ0zR6tTSEm6ZOvSRvlppqh84kz7LmWem7gGHAsY2G3tWBUmOdO/SMNMThqV62yLf7sKsuoE1w06lfmrf6D2zGwoEyz+TT6fdSkc34Yeh7+c01X6nFWU="],"x5t":"geiCPGtT_10T8xGLUK1LA0_YQEE","x5t#S256":"dLp3_QNGwMbYll5VecnR8Q9NSeFVfqJPBTa2_8qf48I"},{"kid":"tW6ae7TomE6_2jooM-sf9N_6lWg7HNtaQXrDsElBzM4","kty":"RSA","alg":"PS512","use":"sig","n":"p32N7jqKfMUB6_dKY1uZ3wizzPlBAXg9XrntfUcwNLRPfTBnshpt4uQBf3T8fexkbzhtR18oHvim-YvcWfC5eLGQmWHYiVwACa_C7oGqx51ijK2LRbUg4TKhnZX2X3Ld9xvr3HsosKh2UXn_Ay8nuvdfH-U6S7btT6a-AIFlt3BpqZP0EOl7rY-ie8nXoA13xX6BoyzYiNcugdYCU6czQcmTIJ1JLS0zohi4aTNehRt-1VMRpIMx7q7Ouq3Zhbi7RcDo-_D8FPRhWc2eEKd-h8ebFTIxEOrkguBIomjEFTf3SfYbOB_h-14v9Q2yz-NzyId3-ujRCQGC0hn-cixe2w","e":"AQAB","x5c":["MIICmzCCAYMCBgF4BKAxqzANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjEwMzA1MjMwMDEwWhcNMzEwMzA1MjMwMTUwWjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCnfY3uOop8xQHr90pjW5nfCLPM+UEBeD1eue19RzA0tE99MGeyGm3i5AF/dPx97GRvOG1HXyge+Kb5i9xZ8Ll4sZCZYdiJXAAJr8LugarHnWKMrYtFtSDhMqGdlfZfct33G+vceyiwqHZRef8DLye6918f5TpLtu1Ppr4AgWW3cGmpk/QQ6Xutj6J7ydegDXfFfoGjLNiI1y6B1gJTpzNByZMgnUktLTOiGLhpM16FG37VUxGkgzHurs66rdmFuLtFwOj78PwU9GFZzZ4Qp36Hx5sVMjEQ6uSC4EiiaMQVN/dJ9hs4H+H7Xi/1DbLP43PIh3f66NEJAYLSGf5yLF7bAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAHVWNBTExqlg4LTcyhUXI5U0iNPcMIVdKDoGPDc3EPjXyYNyjURX0oZ6b1Wv5t+XGmpZRqJNYb92xraQatIzLEsRn4IrmzViP+dIyFU8BEDubixTxeqx7LSw2j6LIFnZ05XdmWknlksNTlqi4CT6KL+1c24+QU3CcmU3mkQEIPA2yC4SdAB1oXI0jh49uP6a+JrE7JREZGAdwbIpZ1cqV6acPiJW3tOYfLrHwo7KYn3KwJvIBHXgFBNwx7fl2gYNQ0VEGKub3qVwW5RO5R/6Tcla9uZEfEiamms/Pn4hFA1qbsNHtA9IRGVRSmVeBKDxRvo0fxOUXp+NuZxEnhsoP3I="],"x5t":"f1l1fxICz1fe9mI-sSrtc19EDhU","x5t#S256":"NUJWRA4ADpLEg_SMkSoE4FKQN0H1Tlz85L-i7puVcqQ"},{"kid":"Lx1FmayP2YBtxaqS1SKJRJGiXRKnw2ov5WmYIMG-BLE","kty":"RSA","alg":"PS384","use":"sig","n":"q7WM4SnrdzlFSo_A1DRhc-8Ho-pBsfs49kGRbw3O_OKFIUyZrzHaRuovW_QaEAyiO3HX8CNcGPcpHdmpl4DhTGEBLcd6xXtCaa65ct00Mq7ZHCRRCrKLh6lJ0rY9fP8vCV0RBigpkNoRfrqLQQN4VeVFTbGSrDaS0LzPbap0-q5FKXUR-OQmQEtOupXhKFQtbB73tL83YnG6Swl7nXsx54ulEoDzcCCYt7pjCVVp7L9fzI2_ucTdtQclAJVQZGKpsx7vabOJuiMUwuAIz56lOJyXRMePsW8UogwC4FA2A52STsYlhOPsDEW4iIExFVNqs-CGoDGhYLIavaCkZhXM0w","e":"AQAB","x5c":["MIICmzCCAYMCBgF4HR+9XjANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjEwMzEwMTcxMDIyWhcNMzEwMzEwMTcxMjAyWjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrtYzhKet3OUVKj8DUNGFz7wej6kGx+zj2QZFvDc784oUhTJmvMdpG6i9b9BoQDKI7cdfwI1wY9ykd2amXgOFMYQEtx3rFe0Jprrly3TQyrtkcJFEKsouHqUnStj18/y8JXREGKCmQ2hF+uotBA3hV5UVNsZKsNpLQvM9tqnT6rkUpdRH45CZAS066leEoVC1sHve0vzdicbpLCXudezHni6USgPNwIJi3umMJVWnsv1/Mjb+5xN21ByUAlVBkYqmzHu9ps4m6IxTC4AjPnqU4nJdEx4+xbxSiDALgUDYDnZJOxiWE4+wMRbiIgTEVU2qz4IagMaFgshq9oKRmFczTAgMBAAEwDQYJKoZIhvcNAQELBQADggEBADTgP3SrcG3p9XUB7sM4a2IeY0J4bSEtqlZBuHgdgekYJ5DXETJ3hV/82GjitU50NBup0IJyI9KZ0KCwqHIKC2Jn/6biOpM9Ipk4BtNVzx3qKNsDac9qZmyMpm4V9QuWakajknerhwyynG3siGUntbPmLvf5UKvKtbiKlWS4dBPwfedIUnC85mYEnNKSzSI1NiM6TWHB9zQYkARXlb89sh0HBYs08BfRMyBVM+l3OczIyGeQAfhcL+pxPP/0jqPr1ctHUBj2zXkjZxDw1oJFgeD9GDtPcjc3spB20vsRtQUBlzbJElbGflqWGHJK5l5n7gNd3ZXZT0HJ+wUpPE8EUaM="],"x5t":"fjRYR1986VCLzbaZaw5r25UKahw","x5t#S256":"ZHNHpizlsjD3qSZh7gJQQBu8W9jBL2HR0y7-3u2Wb-g"},{"kid":"gnmAfvmlsi3kKH3VlM1AJ85P2hekQ8ON_XvJqs3xPD8","kty":"RSA","alg":"RS384","use":"sig","n":"qUNQewKl3APQcbpACMNJ2XphPpupt395z6OZvj5CW9tiRXY3J7dqi8U0bWoIhtmmc7Js6hjp-A5W_FVStuXlT1hLyjJsHeu9ZVPnfIl2MnYN83zQBKw8E4mFsVv0UXNvkVPBF_k0yXrz-ABleWLOgFGnkNU9csc3Z5aihHcwRmC_oS7PZ9Vc-l0xBCyF3YRHI-al8ppSHwFreOweF3-JP3poNAXd906_tjX2KlHSJmNqcUNiSfEluyCp02ALlRFKXUQ1HlfSupHcHySDlanfUyIzZgM9ysCvC1vfNdAuwZ44oUBMul_XPxxhzlewL2Y8PtSDLUDWGTIou8M8049D8Q","e":"AQAB","x5c":["MIICmzCCAYMCBgF4BJVfaDANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjEwMzA1MjI0ODIxWhcNMzEwMzA1MjI1MDAxWjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpQ1B7AqXcA9BxukAIw0nZemE+m6m3f3nPo5m+PkJb22JFdjcnt2qLxTRtagiG2aZzsmzqGOn4Dlb8VVK25eVPWEvKMmwd671lU+d8iXYydg3zfNAErDwTiYWxW/RRc2+RU8EX+TTJevP4AGV5Ys6AUaeQ1T1yxzdnlqKEdzBGYL+hLs9n1Vz6XTEELIXdhEcj5qXymlIfAWt47B4Xf4k/emg0Bd33Tr+2NfYqUdImY2pxQ2JJ8SW7IKnTYAuVEUpdRDUeV9K6kdwfJIOVqd9TIjNmAz3KwK8LW9810C7BnjihQEy6X9c/HGHOV7AvZjw+1IMtQNYZMii7wzzTj0PxAgMBAAEwDQYJKoZIhvcNAQELBQADggEBABoThxhMd7Xiq4x0GJeoJFv2yDKXCL3dJEAEWtOr2+PqdeJl/ZfOxBXynIvrdtYnQdICztN5ydEgDsZ02piDsxZ+s/0SA0iqjw/MEoBYobmr8V+xwUv+WtRLpTBXqWGMuG7NEtrbjKid0iKLLAOAU4dcHQ49iOF9VLnbTkf1EXp4iphJreaubOXMwT6/JDzQPT1dRR34hlhYeKKzMSA0Cz5aYL1tI+eH12rar0MDczXykLChNS/8MlyTzreEf0siUiS9S1kj/lOZKQDg9E/z8fm5vmHEHzAVwf4ON5iO29tDsqLw7BeJqC4AESjliXIqMrdpFynfPnIsGgf3dnph5BM="],"x5t":"CmRnQVduZWtEsdOC4mauUUsSWxA","x5t#S256":"BvC0LmuM8ZIApN3TQQZWWbGO-d082Ah5d3D6vPvahGw"},{"kid":"CGt0ZWS4Lc5faiKSdi0tU0fjCAdvGROQRGU9iR7tV0A","kty":"EC","alg":"ES256","use":"sig","crv":"P-256","x":"DPW7n9yjfE6Rt-VvVmEdeu4QdW44qifocAPPDxACDDY","y":"-ejsVw8222-hg2dJWx3QV0hE4-I0Ujp7ZsWebE68JE0"},{"kid":"C65q0EKQyhpd1m4fr7SKO2He_nAxgCtAdws64d2BLt8","kty":"RSA","alg":"RS256","use":"sig","n":"ja99ybDrLvw11Z4CvNlDI-kkqJEBpSnvDf0pZF2DvBlvYmeVYL_ChqIe8E9GyHUmLMdtO_jifSgOqE5b8vILwi1kZnJR7N857uEnbWM9YTeevi_RZ-E_hr4frW2NKJ78YGvCzwLKG2GgtSjj0zuTLnSaK8fCGzqXgy6paXNhgHUSZgGwvO0YItpMlyJeqEj1wGTWz1IyA1sguF1cC7K0fojPbPoBwrhvaAeoGRPLraE0rrBsQv8iiLwnRBIez9B1j0NiUG8Iad953Y7UzaKOAw8crIEK45NIK_yxHUpxqcHLjPIcRyIyJGioRyGK7cp-_7iPLOCutQc-u46mom1_ZQ","e":"AQAB","x5c":["MIICmzCCAYMCBgF4BJRpbzANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjEwMzA1MjI0NzE4WhcNMzEwMzA1MjI0ODU4WjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCNr33JsOsu/DXVngK82UMj6SSokQGlKe8N/SlkXYO8GW9iZ5Vgv8KGoh7wT0bIdSYsx207+OJ9KA6oTlvy8gvCLWRmclHs3znu4SdtYz1hN56+L9Fn4T+Gvh+tbY0onvxga8LPAsobYaC1KOPTO5MudJorx8IbOpeDLqlpc2GAdRJmAbC87Rgi2kyXIl6oSPXAZNbPUjIDWyC4XVwLsrR+iM9s+gHCuG9oB6gZE8utoTSusGxC/yKIvCdEEh7P0HWPQ2JQbwhp33ndjtTNoo4DDxysgQrjk0gr/LEdSnGpwcuM8hxHIjIkaKhHIYrtyn7/uI8s4K61Bz67jqaibX9lAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAHrGJFhVNiQupIwkn2jiW/jBobm9CHUxOwQL5E7WdRz5uaOJ0v62PrynOQE9xim9Qk8bT3q7DThZs66U9bpIk3msKVRgXRfn5FZy1H5RKOlEEFZhGakPqSlC1yPbhUNhHXMs3GTzdGMLtYaGvSy6XM/8/zqVqVwgh6BpbAR9RfiSdyaiNTSBriu+n/tHW934G9J8UIzdfpVcb0Yt9y4o0UgIXt64NtGFq7zmNJijH88AxBZFB6eUUmQQCczebzoAjyYbVOes5gGFzboVWcyLe3iyD0vvsAVHJViXeiGoxhpKnc8ryISpRUBzsKngf5uZo3bnrD9PHLYBoGOHgzII1xw="],"x5t":"5GNr3LeRXHWI4YR8-QTSsF98oTI","x5t#S256":"Dgd0_wZZqvRuf4GEISPNHREX-1ixTMIsrPeGzk0bCxs"},{"kty":"OKP","d":"TJ0UPkOZDPfneEDSH2ETbLQWjrALD-BPZQR-E7mgPvY","use":"sig","crv":"Ed25519","kid":"Q56A","x":"iZli54E2SkbrOvAThwrnxn1AMIOaazi_ckl6B-hbDK8"},{"kty":"oct","use":"sig","kid":"hmac","k":"V_8Ob8dVs6JuZx6expyjShoUgFgxoaovGjmGhesL2jA"}]}` ) // TestInvalidServer performs initialization + refresh initialization with a server providing invalid data. @@ -169,39 +162,6 @@ func TestJWKS(t *testing.T) { } } -// TestJWKS_Use tests that JWKs with a use value "enc" are not returned from keyfunc() -func TestJWKS_Use(t *testing.T) { - path := "/jwks.json" - - handler := http.NewServeMux() - handler.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) { - _, err := w.Write([]byte(jwksJSON)) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - }) - - server := httptest.NewServer(handler) - defer server.Close() - - jwksURL := server.URL + path - opts := keyfunc.Options{ - AllowedJWKUses: []keyfunc.JWKUse{keyfunc.UseOmitted, keyfunc.UseSignature}, - } - jwks, err := keyfunc.Get(jwksURL, opts) - if err != nil { - t.Fatalf(logFmt, "Failed to get JWKS from testing URL.", err) - } - - // We have the kid ("WW91IGdldCBhIGdvbGQgc3RhciDwn4yfCg"), but the JWK use is marked as "enc" - token := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IldXOTFJR2RsZENCaElHZHZiR1FnYzNSaGNpRHduNHlmQ2cifQ.eyJleHAiOjE2MTU0MDY5NjIsImlhdCI6MTYxNTQwNjkwMiwianRpIjoiNWIyZGY5N2EtNDQyOS00ZTA0LWFkMzgtOWZmNjVlZDU2MTZjIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiJhZDEyOGRmMS0xMTQwLTRlNGMtYjA5Ny1hY2RjZTcwNWJkOWIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJ0b2tlbmRlbG1lIiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwiY2xpZW50SG9zdCI6IjE3Mi4yMC4wLjEiLCJjbGllbnRJZCI6InRva2VuZGVsbWUiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInByZWZlcnJlZF91c2VybmFtZSI6InNlcnZpY2UtYWNjb3VudC10b2tlbmRlbG1lIiwiY2xpZW50QWRkcmVzcyI6IjE3Mi4yMC4wLjEifQ.tvRomWtEUyeXkDLoiBt-sGJdoelyNpa1ohvI-YRrHezEkEhtGKdQinhsOoeWJpwofUqX5GthZxY4gVUFumxsZODEQ_vYsb482RnnQavsZlD6P51UVGNO4Pp9ujU-YO2tXk5qZY3ArqvMnc5OH-e-vExvC7GGGEMxVdL9yfunsiTP2KmVZoYk-WUlFGQYlzEN9Wg1ZR0OBbpXZp69xYeA_I6GrtAgs80tmAam1qihisePjjsbWVDVJ1wphlQIn_fMsAVWw64uLPlZIy3STdaRbjFdAocekzzJUd8X1qhM9MMPFivwFzIPqH_nsyBmX5aLeNsDB9W-FsngdPN7XHv7Aw" - - _, err = jwt.Parse(token, jwks.Keyfunc) - if !errors.Is(err, keyfunc.ErrJWKUse) { - t.Fatal("the kid should been found, but not authorized for signature verification") - } -} - // TestKIDs confirms the JWKS.KIDs returns the key IDs (`kid`) stored in the JWKS. func TestJWKS_KIDs(t *testing.T) { jwks, err := keyfunc.NewJSON([]byte(jwksJSON)) @@ -221,7 +181,6 @@ func TestJWKS_KIDs(t *testing.T) { "C65q0EKQyhpd1m4fr7SKO2He_nAxgCtAdws64d2BLt8", "Q56A", "hmac", - "WW91IGdldCBhIGdvbGQgc3RhciDwn4yfCg", } actual := jwks.KIDs() @@ -265,7 +224,6 @@ func TestJWKS_Len(t *testing.T) { "C65q0EKQyhpd1m4fr7SKO2He_nAxgCtAdws64d2BLt8", "Q56A", "hmac", - "WW91IGdldCBhIGdvbGQgc3RhciDwn4yfCg", } actualLen := jwks.Len() @@ -612,23 +570,3 @@ func TestUnknownKIDRefresh(t *testing.T) { } } } - -// TestReadOnlyKeys verifies that the keys are of an expected type -func TestReadOnlyKeys(t *testing.T) { - jwks, err := keyfunc.NewJSON([]byte(jwksJSON)) - if err != nil { - t.Fatalf(logFmt, "Failed to create a JWKS from JSON.", err) - } - - for _, key := range jwks.ReadOnlyKeys() { - switch key.(type) { - case *rsa.PublicKey: - case *ecdsa.PublicKey: - case ed25519.PublicKey: - case []uint8: - continue - default: - t.Errorf("invalid type %T in readonly keys", key) - } - } -} diff --git a/options.go b/options.go index 08c28b2..bfd7395 100644 --- a/options.go +++ b/options.go @@ -21,11 +21,6 @@ var ErrInvalidHTTPStatusCode = errors.New("invalid HTTP status code") // When using a background refresh goroutine, make sure to use RefreshRateLimit if paired with RefreshUnknownKID. Also // make sure to end the background refresh goroutine with the JWKS.EndBackground method when it's no longer needed. type Options struct { - - // AllowedJWKUses can be used to limit which JWK `use` values will be returned by keyfunc(). - // By default, the only allowed key use values are `"sig"` or the use value omitted - AllowedJWKUses []JWKUse - // Client is the HTTP client used to get the JWKS via HTTP. Client *http.Client @@ -108,7 +103,6 @@ func applyOptions(jwks *JWKS, options Options) { } } - jwks.allowedJWKUses = options.AllowedJWKUses jwks.client = options.Client jwks.givenKIDOverride = options.GivenKIDOverride jwks.refreshErrorHandler = options.RefreshErrorHandler