...

Source file src/github.com/lestrrat-go/jwx/jws/headers_test.go

Documentation: github.com/lestrrat-go/jwx/jws

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

View as plain text