github.com/lestrrat-go/jwx/v2@v2.0.21/jws/headers_test.go (about) 1 package jws_test 2 3 import ( 4 "context" 5 "reflect" 6 "testing" 7 8 "github.com/lestrrat-go/jwx/v2/cert" 9 "github.com/lestrrat-go/jwx/v2/jwa" 10 "github.com/lestrrat-go/jwx/v2/jwk" 11 "github.com/lestrrat-go/jwx/v2/jws" 12 "github.com/stretchr/testify/assert" 13 ) 14 15 var zeroval reflect.Value 16 17 func TestHeader(t *testing.T) { 18 publicKey := `{"kty":"RSA", 19 "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw", 20 "e":"AQAB", 21 "alg":"RS256", 22 "kid":"2011-04-29"}` 23 jwkPublicKey, err := jwk.ParseKey([]byte(publicKey)) 24 if !assert.NoError(t, err, `jwk.ParseKey should succeed`) { 25 return 26 } 27 28 var chain cert.Chain 29 _ = chain.AddString("MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYwMTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3HKrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQmVZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpRSgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRTcDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEuMB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDSkdRMEXGzYcs9of7dqGrU4zASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEBBCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0fBD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUHAgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IGOgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMUA2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTXRE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuHqDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWVU+4=") 30 _ = chain.AddString("MIIE+zCCBGSgAwIBAgICAQ0wDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MDYyMFoXDTI0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjggHhMIIB3TAdBgNVHQ4EFgQU0sSw0pHUTBFxs2HLPaH+3ahq1OMwgdIGA1UdIwSByjCBx6GBwaSBvjCBuzEkMCIGA1UEBxMbVmFsaUNlcnQgVmFsaWRhdGlvbiBOZXR3b3JrMRcwFQYDVQQKEw5WYWxpQ2VydCwgSW5jLjE1MDMGA1UECxMsVmFsaUNlcnQgQ2xhc3MgMiBQb2xpY3kgVmFsaWRhdGlvbiBBdXRob3JpdHkxITAfBgNVBAMTGGh0dHA6Ly93d3cudmFsaWNlcnQuY29tLzEgMB4GCSqGSIb3DQEJARYRaW5mb0B2YWxpY2VydC5jb22CAQEwDwYDVR0TAQH/BAUwAwEB/zAzBggrBgEFBQcBAQQnMCUwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmdvZGFkZHkuY29tMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeS9yb290LmNybDBLBgNVHSAERDBCMEAGBFUdIAAwODA2BggrBgEFBQcCARYqaHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOBgQC1QPmnHfbq/qQaQlpE9xXUhUaJwL6e4+PrxeNYiY+Sn1eocSxI0YGyeR+sBjUZsE4OWBsUs5iB0QQeyAfJg594RAoYC5jcdnplDQ1tgMQLARzLrUc+cb53S8wGd9D0VmsfSxOaFIqII6hR8INMqzW/Rn453HWkrugp++85j09VZw==") 31 _ = chain.AddString("MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYyNjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9vUJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTuIYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwCW/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd") 32 33 data := []struct { 34 Key string 35 Value interface{} 36 Expected interface{} 37 Method string 38 }{ 39 { 40 Key: jws.AlgorithmKey, 41 Value: jwa.ES256, 42 Method: "Algorithm", 43 }, 44 { 45 Key: jws.ContentTypeKey, 46 Value: "example", 47 Method: "ContentType", 48 }, 49 { 50 Key: jws.CriticalKey, 51 Value: []string{"exp"}, 52 Method: "Critical", 53 }, 54 { 55 Key: jws.JWKKey, 56 Value: jwkPublicKey, 57 Method: "JWK", 58 }, 59 { 60 Key: jws.JWKSetURLKey, 61 Value: "https://www.jwk.com/key.json", 62 Method: "JWKSetURL", 63 }, 64 { 65 Key: jws.TypeKey, 66 Value: "JWT", 67 Method: "Type", 68 }, 69 { 70 Key: jws.KeyIDKey, 71 Value: "e9bc097a-ce51-4036-9562-d2ade882db0d", 72 Method: "KeyID", 73 }, 74 { 75 Key: jws.X509CertChainKey, 76 Value: &chain, 77 Method: "X509CertChain", 78 }, 79 { 80 Key: jws.X509CertThumbprintKey, 81 Value: "QzY0NjREMjkyQTI4RTU2RkE4MUJBRDExNzY1MUY1N0I4QjFCODlBOQ", 82 Method: "X509CertThumbprint", 83 }, 84 { 85 Key: jws.X509URLKey, 86 Value: "https://www.x509.com/key.pem", 87 Method: "X509URL", 88 }, 89 {Key: "private", Value: "boofoo"}, 90 } 91 92 base := jws.NewHeaders() 93 94 t.Run("Set values", func(t *testing.T) { 95 // DO NOT RUN THIS IN PARALLEL. THIS IS AN INITIALIZER 96 for _, tc := range data { 97 if !assert.NoError(t, base.Set(tc.Key, tc.Value), "Headers.Set should succeed") { 98 return 99 } 100 } 101 }) 102 103 t.Run("Set/Get", func(t *testing.T) { 104 h := jws.NewHeaders() 105 ctx := context.Background() 106 107 for iter := base.Iterate(ctx); iter.Next(ctx); { 108 pair := iter.Pair() 109 if !assert.NoError(t, h.Set(pair.Key.(string), pair.Value), `h.Set should be successful`) { 110 return 111 } 112 } 113 for _, tc := range data { 114 var values []interface{} 115 viaGet, ok := h.Get(tc.Key) 116 if !assert.True(t, ok, "value for %s should exist", tc.Key) { 117 return 118 } 119 values = append(values, viaGet) 120 121 if method := tc.Method; method != "" { 122 m := reflect.ValueOf(h).MethodByName(method) 123 if !assert.NotEqual(t, m, zeroval, "method %s should be available", method) { 124 return 125 } 126 127 ret := m.Call(nil) 128 if !assert.Len(t, ret, 1, `should get exactly 1 value as return value`) { 129 return 130 } 131 values = append(values, ret[0].Interface()) 132 } 133 134 expected := tc.Expected 135 if expected == nil { 136 expected = tc.Value 137 } 138 for i, got := range values { 139 if !assert.Equal(t, expected, got, "value %d should match", i) { 140 return 141 } 142 } 143 } 144 }) 145 t.Run("PrivateParams", func(t *testing.T) { 146 h := base 147 pp, err := h.AsMap(context.Background()) 148 if !assert.NoError(t, err, `h.AsMap should succeed`) { 149 return 150 } 151 152 v, ok := pp["private"] 153 if !assert.True(t, ok, "key 'private' should exists") { 154 return 155 } 156 157 if !assert.Equal(t, v, "boofoo", "value for 'private' should match") { 158 return 159 } 160 }) 161 162 t.Run("Iterator", func(t *testing.T) { 163 expected := map[string]interface{}{} 164 for _, tc := range data { 165 v := tc.Value 166 if expected := tc.Expected; expected != nil { 167 v = expected 168 } 169 expected[tc.Key] = v 170 } 171 172 v := base 173 t.Run("Iterate", func(t *testing.T) { 174 seen := make(map[string]interface{}) 175 for iter := v.Iterate(context.TODO()); iter.Next(context.TODO()); { 176 pair := iter.Pair() 177 seen[pair.Key.(string)] = pair.Value 178 179 getV, ok := v.Get(pair.Key.(string)) 180 if !assert.True(t, ok, `v.Get should succeed for key %#v`, pair.Key) { 181 return 182 } 183 if !assert.Equal(t, pair.Value, getV, `pair.Value should match value from v.Get()`) { 184 return 185 } 186 } 187 if !assert.Equal(t, expected, seen, `values should match`) { 188 return 189 } 190 }) 191 t.Run("Walk", func(t *testing.T) { 192 seen := make(map[string]interface{}) 193 v.Walk(context.TODO(), jwk.HeaderVisitorFunc(func(key string, value interface{}) error { 194 seen[key] = value 195 return nil 196 })) 197 if !assert.Equal(t, expected, seen, `values should match`) { 198 return 199 } 200 }) 201 t.Run("AsMap", func(t *testing.T) { 202 m, err := v.AsMap(context.TODO()) 203 if !assert.NoError(t, err, `v.AsMap should succeed`) { 204 return 205 } 206 if !assert.Equal(t, expected, m, `values should match`) { 207 return 208 } 209 }) 210 t.Run("Remove", func(t *testing.T) { 211 h := base 212 for iter := h.Iterate(context.TODO()); iter.Next(context.TODO()); { 213 pair := iter.Pair() 214 h.Remove(pair.Key.(string)) 215 } 216 217 m, err := h.AsMap(context.TODO()) 218 if !assert.NoError(t, err, `h.AsMap should succeed`) { 219 return 220 } 221 if !assert.Len(t, m, 0, `len should be zero`) { 222 return 223 } 224 }) 225 }) 226 }