github.com/lestrrat-go/jwx/v2@v2.0.21/jwe/headers_test.go (about)

     1  package jwe_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/internal/jwxtest"
    10  	"github.com/lestrrat-go/jwx/v2/jwa"
    11  	"github.com/lestrrat-go/jwx/v2/jwe"
    12  	"github.com/lestrrat-go/jwx/v2/jwk"
    13  	"github.com/stretchr/testify/assert"
    14  )
    15  
    16  var zeroval reflect.Value
    17  
    18  func TestHeaders(t *testing.T) {
    19  	certSrc := []string{
    20  		"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=",
    21  		"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==",
    22  		"MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYyNjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9vUJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTuIYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwCW/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd",
    23  	}
    24  	var certs cert.Chain
    25  	for _, src := range certSrc {
    26  		_ = certs.AddString(src)
    27  	}
    28  
    29  	rawKey, err := jwxtest.GenerateEcdsaKey(jwa.P521)
    30  	if !assert.NoError(t, err, `jwxtest.GenerateEcdsaKey should succeed`) {
    31  		return
    32  	}
    33  	privKey, err := jwk.FromRaw(rawKey)
    34  	if !assert.NoError(t, err, `jwk.FromRaw should succeed`) {
    35  		return
    36  	}
    37  
    38  	pubKey, err := jwk.FromRaw(rawKey.PublicKey)
    39  	if !assert.NoError(t, err, `jwk.FromRaw should succeed`) {
    40  		return
    41  	}
    42  
    43  	data := []struct {
    44  		Key      string
    45  		Value    interface{}
    46  		Expected interface{}
    47  		Method   string
    48  	}{
    49  		{
    50  			Key:    jwe.AgreementPartyUInfoKey,
    51  			Value:  []byte("apu foobarbaz"),
    52  			Method: "AgreementPartyUInfo",
    53  		},
    54  		{Key: jwe.AgreementPartyVInfoKey, Value: []byte("apv foobarbaz")},
    55  		{Key: jwe.CompressionKey, Value: jwa.Deflate},
    56  		{Key: jwe.ContentEncryptionKey, Value: jwa.A128GCM},
    57  		{
    58  			Key:    jwe.ContentTypeKey,
    59  			Value:  "application/json",
    60  			Method: "ContentType",
    61  		},
    62  		{
    63  			Key:    jwe.CriticalKey,
    64  			Value:  []string{"crit blah"},
    65  			Method: "Critical",
    66  		},
    67  		{
    68  			Key:    jwe.EphemeralPublicKeyKey,
    69  			Value:  pubKey,
    70  			Method: "EphemeralPublicKey",
    71  		},
    72  		{
    73  			Key:    jwe.JWKKey,
    74  			Value:  privKey,
    75  			Method: "JWK",
    76  		},
    77  		{
    78  			Key:    jwe.JWKSetURLKey,
    79  			Value:  "http://github.com/lestrrat-go/jwx/v2",
    80  			Method: "JWKSetURL",
    81  		},
    82  		{
    83  			Key:    jwe.KeyIDKey,
    84  			Value:  "kid blah",
    85  			Method: "KeyID",
    86  		},
    87  		{
    88  			Key:    jwe.TypeKey,
    89  			Value:  "typ blah",
    90  			Method: "Type",
    91  		},
    92  		{
    93  			Key:    jwe.X509CertChainKey,
    94  			Value:  &certs,
    95  			Method: "X509CertChain",
    96  		},
    97  		{
    98  			Key:    jwe.X509CertThumbprintKey,
    99  			Value:  "x5t blah",
   100  			Method: "X509CertThumbprint",
   101  		},
   102  		{
   103  			Key:    jwe.X509CertThumbprintS256Key,
   104  			Value:  "x5t#256 blah",
   105  			Method: "X509CertThumbprintS256",
   106  		},
   107  		{
   108  			Key:    jwe.X509URLKey,
   109  			Value:  "http://github.com/lestrrat-go/jwx/v2",
   110  			Method: "X509URL",
   111  		},
   112  		{Key: "private", Value: "boofoo"},
   113  	}
   114  
   115  	base := jwe.NewHeaders()
   116  
   117  	t.Run("Set values", func(t *testing.T) {
   118  		// DO NOT RUN THIS IN PARALLEL. THIS IS AN INITIALIZER
   119  		for _, tc := range data {
   120  			if !assert.NoError(t, base.Set(tc.Key, tc.Value), "Headers.Set should succeed") {
   121  				return
   122  			}
   123  		}
   124  	})
   125  
   126  	t.Run("Set/Get", func(t *testing.T) {
   127  		h := jwe.NewHeaders()
   128  		ctx := context.Background()
   129  
   130  		for iter := base.Iterate(ctx); iter.Next(ctx); {
   131  			pair := iter.Pair()
   132  			if !assert.NoError(t, h.Set(pair.Key.(string), pair.Value), `h.Set should be successful`) {
   133  				return
   134  			}
   135  		}
   136  		for _, tc := range data {
   137  			var values []interface{}
   138  			viaGet, ok := h.Get(tc.Key)
   139  			if !assert.True(t, ok, "value for %s should exist", tc.Key) {
   140  				return
   141  			}
   142  			values = append(values, viaGet)
   143  
   144  			if method := tc.Method; method != "" {
   145  				m := reflect.ValueOf(h).MethodByName(method)
   146  				if !assert.NotEqual(t, m, zeroval, "method %s should be available", method) {
   147  					return
   148  				}
   149  
   150  				ret := m.Call(nil)
   151  				if !assert.Len(t, ret, 1, `should get exactly 1 value as return value`) {
   152  					return
   153  				}
   154  				values = append(values, ret[0].Interface())
   155  			}
   156  
   157  			expected := tc.Expected
   158  			if expected == nil {
   159  				expected = tc.Value
   160  			}
   161  			for i, got := range values {
   162  				if !assert.Equal(t, expected, got, "value %d should match", i) {
   163  					return
   164  				}
   165  			}
   166  		}
   167  	})
   168  	t.Run("PrivateParams", func(t *testing.T) {
   169  		h := base
   170  		pp, err := h.AsMap(context.Background())
   171  		if !assert.NoError(t, err, `h.AsMap should succeed`) {
   172  			return
   173  		}
   174  
   175  		v, ok := pp["private"]
   176  		if !assert.True(t, ok, "key 'private' should exists") {
   177  			return
   178  		}
   179  
   180  		if !assert.Equal(t, v, "boofoo", "value for 'private' should match") {
   181  			return
   182  		}
   183  	})
   184  	t.Run("Encode", func(t *testing.T) {
   185  		h1 := jwe.NewHeaders()
   186  		h1.Set(jwe.AlgorithmKey, jwa.A128GCMKW)
   187  		h1.Set("foo", "bar")
   188  
   189  		buf, err := h1.Encode()
   190  		if !assert.NoError(t, err, `h1.Encode should succeed`) {
   191  			return
   192  		}
   193  
   194  		h2 := jwe.NewHeaders()
   195  		if !assert.NoError(t, h2.Decode(buf), `h2.Decode should succeed`) {
   196  			return
   197  		}
   198  
   199  		if !assert.Equal(t, h1, h2, `objects should match`) {
   200  			return
   201  		}
   202  	})
   203  
   204  	t.Run("Iterator", func(t *testing.T) {
   205  		expected := map[string]interface{}{}
   206  		for _, tc := range data {
   207  			v := tc.Value
   208  			if expected := tc.Expected; expected != nil {
   209  				v = expected
   210  			}
   211  			expected[tc.Key] = v
   212  		}
   213  
   214  		v := base
   215  		t.Run("Iterate", func(t *testing.T) {
   216  			seen := make(map[string]interface{})
   217  			for iter := v.Iterate(context.TODO()); iter.Next(context.TODO()); {
   218  				pair := iter.Pair()
   219  				seen[pair.Key.(string)] = pair.Value
   220  
   221  				getV, ok := v.Get(pair.Key.(string))
   222  				if !assert.True(t, ok, `v.Get should succeed for key %#v`, pair.Key) {
   223  					return
   224  				}
   225  				if !assert.Equal(t, pair.Value, getV, `pair.Value should match value from v.Get()`) {
   226  					return
   227  				}
   228  			}
   229  			if !assert.Equal(t, expected, seen, `values should match`) {
   230  				return
   231  			}
   232  		})
   233  		t.Run("Walk", func(t *testing.T) {
   234  			seen := make(map[string]interface{})
   235  			v.Walk(context.TODO(), jwk.HeaderVisitorFunc(func(key string, value interface{}) error {
   236  				seen[key] = value
   237  				return nil
   238  			}))
   239  			if !assert.Equal(t, expected, seen, `values should match`) {
   240  				return
   241  			}
   242  		})
   243  		t.Run("AsMap", func(t *testing.T) {
   244  			m, err := v.AsMap(context.TODO())
   245  			if !assert.NoError(t, err, `v.AsMap should succeed`) {
   246  				return
   247  			}
   248  			if !assert.Equal(t, expected, m, `values should match`) {
   249  				return
   250  			}
   251  		})
   252  		t.Run("Remove", func(t *testing.T) {
   253  			h := base
   254  			for iter := h.Iterate(context.TODO()); iter.Next(context.TODO()); {
   255  				pair := iter.Pair()
   256  				h.Remove(pair.Key.(string))
   257  			}
   258  
   259  			m, err := h.AsMap(context.TODO())
   260  			if !assert.NoError(t, err, `h.AsMap should succeed`) {
   261  				return
   262  			}
   263  			if !assert.Len(t, m, 0, `len should be zero`) {
   264  				return
   265  			}
   266  		})
   267  	})
   268  }