go.mod: github.com/Azure/go-autorest/autorest v0.11.24
Update the indirect dependency to remove the transitional github.com/form3tech-oss/jwt-go
dependency from the dependency graph.
Updates:
- github.com/Azure/go-autorest/autorest v0.11.24: https://github.com/Azure/go-autorest/compare/autorest/v0.11.20...autorest/v0.11.24
- github.com/Azure/go-autorest/autorest/adal v0.9.18: https://github.com/Azure/go-autorest/compare/autorest/adal/v0.9.15...autorest/adal/v0.9.18
- github.com/golang-jwt/jwt v4.2.0: https://github.com/golang-jwt/jwt/compare/v4.0.0...v4.2.0
- golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3: 32db794688...e495a2d5b3
Before this:
    go mod graph | grep 'jwt'
    github.com/Azure/go-autorest/autorest/adal@v0.9.15 github.com/golang-jwt/jwt/v4@v4.0.0
    github.com/Azure/go-autorest/autorest/adal@v0.9.13 github.com/form3tech-oss/jwt-go@v3.2.2+incompatible
After this:
    go mod graph | grep 'jwt'
    github.com/Azure/go-autorest/autorest@v0.11.24 github.com/golang-jwt/jwt/v4@v4.2.0
    github.com/Azure/go-autorest/autorest/adal@v0.9.18 github.com/golang-jwt/jwt/v4@v4.0.0
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
			
			
				master
			
			
		
							parent
							
								
									be4c921514
								
							
						
					
					
						commit
						4f1c1e4268
					
				
							
								
								
									
										5
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										5
									
								
								go.mod
								
								
								
								
							|  | @ -4,8 +4,7 @@ go 1.16 | |||
| 
 | ||||
| require ( | ||||
| 	github.com/Azure/azure-sdk-for-go v56.3.0+incompatible | ||||
| 	github.com/Azure/go-autorest/autorest v0.11.20 // indirect | ||||
| 	github.com/Azure/go-autorest/autorest/adal v0.9.15 // indirect | ||||
| 	github.com/Azure/go-autorest/autorest v0.11.24 // indirect | ||||
| 	github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect | ||||
| 	github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d | ||||
| 	github.com/aws/aws-sdk-go v1.42.27 | ||||
|  | @ -33,7 +32,7 @@ require ( | |||
| 	github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 // indirect | ||||
| 	github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 | ||||
| 	github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f // indirect | ||||
| 	golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 | ||||
| 	golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 | ||||
| 	golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 | ||||
| 	google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff | ||||
| 	// when updating google.golang.org/cloud, update (or remove) the replace | ||||
|  |  | |||
							
								
								
									
										22
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										22
									
								
								go.sum
								
								
								
								
							|  | @ -4,11 +4,10 @@ github.com/Azure/azure-sdk-for-go v56.3.0+incompatible h1:DmhwMrUIvpeoTDiWRDtNHq | |||
| github.com/Azure/azure-sdk-for-go v56.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= | ||||
| github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= | ||||
| github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= | ||||
| github.com/Azure/go-autorest/autorest v0.11.20 h1:s8H1PbCZSqg/DH7JMlOz6YMig6htWLNPsjDdlLqCx3M= | ||||
| github.com/Azure/go-autorest/autorest v0.11.20/go.mod h1:o3tqFY+QR40VOlk+pV4d77mORO64jOXSgEnPQgLK6JY= | ||||
| github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= | ||||
| github.com/Azure/go-autorest/autorest/adal v0.9.15 h1:X+p2GF0GWyOiSmqohIaEeuNFNDY4I4EOlVuUQvFdWMk= | ||||
| github.com/Azure/go-autorest/autorest/adal v0.9.15/go.mod h1:tGMin8I49Yij6AQ+rvV+Xa/zwxYQB5hmsd6DkfAx2+A= | ||||
| github.com/Azure/go-autorest/autorest v0.11.24 h1:1fIGgHKqVm54KIPT+q8Zmd1QlVsmHqeUGso5qm2BqqE= | ||||
| github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= | ||||
| github.com/Azure/go-autorest/autorest/adal v0.9.18 h1:kLnPsRjzZZUF3K5REu/Kc+qMQrvuza2bwSnNdhmzLfQ= | ||||
| github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= | ||||
| github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= | ||||
| github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= | ||||
| github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= | ||||
|  | @ -65,7 +64,6 @@ github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arX | |||
| github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= | ||||
| github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= | ||||
| github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= | ||||
| github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= | ||||
| github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= | ||||
| github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= | ||||
| github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= | ||||
|  | @ -76,8 +74,9 @@ github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPh | |||
| github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= | ||||
| github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= | ||||
| github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= | ||||
| github.com/golang-jwt/jwt/v4 v4.0.0 h1:RAqyYixv1p7uEnocuy8P1nru5wprCh/MH2BIlW5z5/o= | ||||
| github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= | ||||
| github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= | ||||
| github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= | ||||
| github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= | ||||
| github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= | ||||
| github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||||
|  | @ -199,17 +198,17 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/ | |||
| go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= | ||||
| golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= | ||||
| golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||||
| golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||||
| golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= | ||||
| golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | ||||
| golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | ||||
| golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M= | ||||
| golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= | ||||
| golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||
| golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||
| golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||
| golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||
| golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||||
| golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= | ||||
| golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||||
| golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | ||||
| golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||||
| golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM= | ||||
| golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||||
| golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= | ||||
|  | @ -220,7 +219,6 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h | |||
| golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
|  |  | |||
|  | @ -9,5 +9,5 @@ require ( | |||
| 	github.com/Azure/go-autorest/logger v0.2.1 | ||||
| 	github.com/Azure/go-autorest/tracing v0.6.0 | ||||
| 	github.com/golang-jwt/jwt/v4 v4.0.0 | ||||
| 	golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 | ||||
| 	golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 | ||||
| ) | ||||
|  |  | |||
|  | @ -10,10 +10,11 @@ github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUM | |||
| github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= | ||||
| github.com/golang-jwt/jwt/v4 v4.0.0 h1:RAqyYixv1p7uEnocuy8P1nru5wprCh/MH2BIlW5z5/o= | ||||
| github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= | ||||
| golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||||
| golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE= | ||||
| golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||||
| golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= | ||||
| golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | ||||
| golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | ||||
| golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||||
| golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
|  |  | |||
|  | @ -16,9 +16,11 @@ package adal | |||
| 
 | ||||
| import ( | ||||
| 	"crypto/tls" | ||||
| 	"net" | ||||
| 	"net/http" | ||||
| 	"net/http/cookiejar" | ||||
| 	"sync" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/Azure/go-autorest/tracing" | ||||
| ) | ||||
|  | @ -72,15 +74,18 @@ func sender() Sender { | |||
| 	// note that we can't init defaultSender in init() since it will
 | ||||
| 	// execute before calling code has had a chance to enable tracing
 | ||||
| 	defaultSenderInit.Do(func() { | ||||
| 		// Use behaviour compatible with DefaultTransport, but require TLS minimum version.
 | ||||
| 		defaultTransport := http.DefaultTransport.(*http.Transport) | ||||
| 		// copied from http.DefaultTransport with a TLS minimum version.
 | ||||
| 		transport := &http.Transport{ | ||||
| 			Proxy:                 defaultTransport.Proxy, | ||||
| 			DialContext:           defaultTransport.DialContext, | ||||
| 			MaxIdleConns:          defaultTransport.MaxIdleConns, | ||||
| 			IdleConnTimeout:       defaultTransport.IdleConnTimeout, | ||||
| 			TLSHandshakeTimeout:   defaultTransport.TLSHandshakeTimeout, | ||||
| 			ExpectContinueTimeout: defaultTransport.ExpectContinueTimeout, | ||||
| 			Proxy: http.ProxyFromEnvironment, | ||||
| 			DialContext: (&net.Dialer{ | ||||
| 				Timeout:   30 * time.Second, | ||||
| 				KeepAlive: 30 * time.Second, | ||||
| 			}).DialContext, | ||||
| 			ForceAttemptHTTP2:     true, | ||||
| 			MaxIdleConns:          100, | ||||
| 			IdleConnTimeout:       90 * time.Second, | ||||
| 			TLSHandshakeTimeout:   10 * time.Second, | ||||
| 			ExpectContinueTimeout: 1 * time.Second, | ||||
| 			TLSClientConfig: &tls.Config{ | ||||
| 				MinVersion: tls.VersionTLS12, | ||||
| 			}, | ||||
|  |  | |||
|  | @ -676,8 +676,6 @@ const ( | |||
| 
 | ||||
| func (m msiType) String() string { | ||||
| 	switch m { | ||||
| 	case msiTypeUnavailable: | ||||
| 		return "unavailable" | ||||
| 	case msiTypeAppServiceV20170901: | ||||
| 		return "AppServiceV20170901" | ||||
| 	case msiTypeCloudShell: | ||||
|  | @ -699,13 +697,9 @@ func getMSIType() (msiType, string, error) { | |||
| 		} | ||||
| 		// if ONLY the env var MSI_ENDPOINT is set the msiType is CloudShell
 | ||||
| 		return msiTypeCloudShell, endpointEnvVar, nil | ||||
| 	} else if msiAvailableHook(context.Background(), sender()) { | ||||
| 		// if MSI_ENDPOINT is NOT set AND the IMDS endpoint is available the msiType is IMDS. This will timeout after 500 milliseconds
 | ||||
| 		return msiTypeIMDS, msiEndpoint, nil | ||||
| 	} else { | ||||
| 		// if MSI_ENDPOINT is NOT set and IMDS endpoint is not available Managed Identity is not available
 | ||||
| 		return msiTypeUnavailable, "", errors.New("MSI not available") | ||||
| 	} | ||||
| 	// if MSI_ENDPOINT is NOT set assume the msiType is IMDS
 | ||||
| 	return msiTypeIMDS, msiEndpoint, nil | ||||
| } | ||||
| 
 | ||||
| // GetMSIVMEndpoint gets the MSI endpoint on Virtual Machines.
 | ||||
|  | @ -1322,15 +1316,13 @@ func NewMultiTenantServicePrincipalTokenFromCertificate(multiTenantCfg MultiTena | |||
| } | ||||
| 
 | ||||
| // MSIAvailable returns true if the MSI endpoint is available for authentication.
 | ||||
| func MSIAvailable(ctx context.Context, sender Sender) bool { | ||||
| 	resp, err := getMSIEndpoint(ctx, sender) | ||||
| func MSIAvailable(ctx context.Context, s Sender) bool { | ||||
| 	if s == nil { | ||||
| 		s = sender() | ||||
| 	} | ||||
| 	resp, err := getMSIEndpoint(ctx, s) | ||||
| 	if err == nil { | ||||
| 		resp.Body.Close() | ||||
| 	} | ||||
| 	return err == nil | ||||
| } | ||||
| 
 | ||||
| // used for testing purposes
 | ||||
| var msiAvailableHook = func(ctx context.Context, sender Sender) bool { | ||||
| 	return MSIAvailable(ctx, sender) | ||||
| } | ||||
|  |  | |||
|  | @ -25,7 +25,7 @@ import ( | |||
| ) | ||||
| 
 | ||||
| func getMSIEndpoint(ctx context.Context, sender Sender) (*http.Response, error) { | ||||
| 	tempCtx, cancel := context.WithTimeout(ctx, 500*time.Millisecond) | ||||
| 	tempCtx, cancel := context.WithTimeout(ctx, 2*time.Second) | ||||
| 	defer cancel() | ||||
| 	// http.NewRequestWithContext() was added in Go 1.13
 | ||||
| 	req, _ := http.NewRequestWithContext(tempCtx, http.MethodGet, msiEndpoint, nil) | ||||
|  |  | |||
|  | @ -24,7 +24,7 @@ import ( | |||
| ) | ||||
| 
 | ||||
| func getMSIEndpoint(ctx context.Context, sender Sender) (*http.Response, error) { | ||||
| 	tempCtx, cancel := context.WithTimeout(ctx, 500*time.Millisecond) | ||||
| 	tempCtx, cancel := context.WithTimeout(ctx, 2*time.Second) | ||||
| 	defer cancel() | ||||
| 	req, _ := http.NewRequest(http.MethodGet, msiEndpoint, nil) | ||||
| 	req = req.WithContext(tempCtx) | ||||
|  |  | |||
|  | @ -68,7 +68,7 @@ func (se ServiceError) Error() string { | |||
| 		if err != nil { | ||||
| 			result += fmt.Sprintf(" Details=%v", se.Details) | ||||
| 		} | ||||
| 		result += fmt.Sprintf(" Details=%v", string(d)) | ||||
| 		result += fmt.Sprintf(" Details=%s", d) | ||||
| 	} | ||||
| 
 | ||||
| 	if se.InnerError != nil { | ||||
|  | @ -76,7 +76,7 @@ func (se ServiceError) Error() string { | |||
| 		if err != nil { | ||||
| 			result += fmt.Sprintf(" InnerError=%v", se.InnerError) | ||||
| 		} | ||||
| 		result += fmt.Sprintf(" InnerError=%v", string(d)) | ||||
| 		result += fmt.Sprintf(" InnerError=%s", d) | ||||
| 	} | ||||
| 
 | ||||
| 	if se.AdditionalInfo != nil { | ||||
|  | @ -84,7 +84,7 @@ func (se ServiceError) Error() string { | |||
| 		if err != nil { | ||||
| 			result += fmt.Sprintf(" AdditionalInfo=%v", se.AdditionalInfo) | ||||
| 		} | ||||
| 		result += fmt.Sprintf(" AdditionalInfo=%v", string(d)) | ||||
| 		result += fmt.Sprintf(" AdditionalInfo=%s", d) | ||||
| 	} | ||||
| 
 | ||||
| 	return result | ||||
|  | @ -335,13 +335,13 @@ func WithErrorUnlessStatusCode(codes ...int) autorest.RespondDecorator { | |||
| 				b, decodeErr := autorest.CopyAndDecode(encodedAs, resp.Body, &e) | ||||
| 				resp.Body = ioutil.NopCloser(&b) | ||||
| 				if decodeErr != nil { | ||||
| 					return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b.String(), decodeErr) | ||||
| 					return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b, decodeErr) | ||||
| 				} | ||||
| 				if e.ServiceError == nil { | ||||
| 					// Check if error is unwrapped ServiceError
 | ||||
| 					decoder := autorest.NewDecoder(encodedAs, bytes.NewReader(b.Bytes())) | ||||
| 					if err := decoder.Decode(&e.ServiceError); err != nil { | ||||
| 						return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b.String(), err) | ||||
| 						return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b, err) | ||||
| 					} | ||||
| 
 | ||||
| 					// for example, should the API return the literal value `null` as the response
 | ||||
|  | @ -364,7 +364,7 @@ func WithErrorUnlessStatusCode(codes ...int) autorest.RespondDecorator { | |||
| 					rawBody := map[string]interface{}{} | ||||
| 					decoder := autorest.NewDecoder(encodedAs, bytes.NewReader(b.Bytes())) | ||||
| 					if err := decoder.Decode(&rawBody); err != nil { | ||||
| 						return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b.String(), err) | ||||
| 						return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b, err) | ||||
| 					} | ||||
| 
 | ||||
| 					e.ServiceError = &ServiceError{ | ||||
|  |  | |||
|  | @ -49,6 +49,8 @@ type ResourceIdentifier struct { | |||
| 	Storage             string `json:"storage"` | ||||
| 	Synapse             string `json:"synapse"` | ||||
| 	ServiceBus          string `json:"serviceBus"` | ||||
| 	SQLDatabase         string `json:"sqlDatabase"` | ||||
| 	CosmosDB            string `json:"cosmosDB"` | ||||
| } | ||||
| 
 | ||||
| // Environment represents a set of endpoints for each of Azure's Clouds.
 | ||||
|  | @ -121,6 +123,8 @@ var ( | |||
| 			Storage:             "https://storage.azure.com/", | ||||
| 			Synapse:             "https://dev.azuresynapse.net", | ||||
| 			ServiceBus:          "https://servicebus.azure.net/", | ||||
| 			SQLDatabase:         "https://database.windows.net/", | ||||
| 			CosmosDB:            "https://cosmos.azure.com", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
|  | @ -162,6 +166,8 @@ var ( | |||
| 			Storage:             "https://storage.azure.com/", | ||||
| 			Synapse:             NotAvailable, | ||||
| 			ServiceBus:          "https://servicebus.azure.net/", | ||||
| 			SQLDatabase:         "https://database.usgovcloudapi.net/", | ||||
| 			CosmosDB:            "https://cosmos.azure.com", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
|  | @ -203,6 +209,8 @@ var ( | |||
| 			Storage:             "https://storage.azure.com/", | ||||
| 			Synapse:             "https://dev.azuresynapse.net", | ||||
| 			ServiceBus:          "https://servicebus.azure.net/", | ||||
| 			SQLDatabase:         "https://database.chinacloudapi.cn/", | ||||
| 			CosmosDB:            "https://cosmos.azure.com", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
|  | @ -244,6 +252,8 @@ var ( | |||
| 			Storage:             "https://storage.azure.com/", | ||||
| 			Synapse:             NotAvailable, | ||||
| 			ServiceBus:          "https://servicebus.azure.net/", | ||||
| 			SQLDatabase:         "https://database.cloudapi.de/", | ||||
| 			CosmosDB:            "https://cosmos.azure.com", | ||||
| 		}, | ||||
| 	} | ||||
| ) | ||||
|  |  | |||
|  | @ -4,9 +4,10 @@ go 1.15 | |||
| 
 | ||||
| require ( | ||||
| 	github.com/Azure/go-autorest v14.2.0+incompatible | ||||
| 	github.com/Azure/go-autorest/autorest/adal v0.9.13 | ||||
| 	github.com/Azure/go-autorest/autorest/adal v0.9.18 | ||||
| 	github.com/Azure/go-autorest/autorest/mocks v0.4.1 | ||||
| 	github.com/Azure/go-autorest/logger v0.2.1 | ||||
| 	github.com/Azure/go-autorest/tracing v0.6.0 | ||||
| 	golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 | ||||
| 	github.com/golang-jwt/jwt/v4 v4.2.0 // indirect | ||||
| 	golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 | ||||
| ) | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= | ||||
| github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= | ||||
| github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q= | ||||
| github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= | ||||
| github.com/Azure/go-autorest/autorest/adal v0.9.18 h1:kLnPsRjzZZUF3K5REu/Kc+qMQrvuza2bwSnNdhmzLfQ= | ||||
| github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= | ||||
| github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= | ||||
| github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= | ||||
| github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= | ||||
|  | @ -10,14 +10,18 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z | |||
| github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= | ||||
| github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= | ||||
| github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= | ||||
| github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= | ||||
| github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= | ||||
| golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= | ||||
| golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||||
| golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE= | ||||
| golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||||
| golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= | ||||
| github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= | ||||
| github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= | ||||
| golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | ||||
| golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M= | ||||
| golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= | ||||
| golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | ||||
| golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||||
| golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||||
| golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
|  |  | |||
|  | @ -241,6 +241,8 @@ func WithBaseURL(baseURL string) PrepareDecorator { | |||
| 					return r, fmt.Errorf("autorest: No scheme detected in URL %s", baseURL) | ||||
| 				} | ||||
| 				if u.RawQuery != "" { | ||||
| 					// handle unencoded semicolons (ideally the server would send them already encoded)
 | ||||
| 					u.RawQuery = strings.Replace(u.RawQuery, ";", "%3B", -1) | ||||
| 					q, err := url.ParseQuery(u.RawQuery) | ||||
| 					if err != nil { | ||||
| 						return r, err | ||||
|  |  | |||
|  | @ -20,6 +20,7 @@ import ( | |||
| 	"fmt" | ||||
| 	"log" | ||||
| 	"math" | ||||
| 	"net" | ||||
| 	"net/http" | ||||
| 	"net/http/cookiejar" | ||||
| 	"strconv" | ||||
|  | @ -129,15 +130,18 @@ func sender(renengotiation tls.RenegotiationSupport) Sender { | |||
| 	// note that we can't init defaultSenders in init() since it will
 | ||||
| 	// execute before calling code has had a chance to enable tracing
 | ||||
| 	defaultSenders[renengotiation].init.Do(func() { | ||||
| 		// Use behaviour compatible with DefaultTransport, but require TLS minimum version.
 | ||||
| 		defaultTransport := http.DefaultTransport.(*http.Transport) | ||||
| 		// copied from http.DefaultTransport with a TLS minimum version.
 | ||||
| 		transport := &http.Transport{ | ||||
| 			Proxy:                 defaultTransport.Proxy, | ||||
| 			DialContext:           defaultTransport.DialContext, | ||||
| 			MaxIdleConns:          defaultTransport.MaxIdleConns, | ||||
| 			IdleConnTimeout:       defaultTransport.IdleConnTimeout, | ||||
| 			TLSHandshakeTimeout:   defaultTransport.TLSHandshakeTimeout, | ||||
| 			ExpectContinueTimeout: defaultTransport.ExpectContinueTimeout, | ||||
| 			Proxy: http.ProxyFromEnvironment, | ||||
| 			DialContext: (&net.Dialer{ | ||||
| 				Timeout:   30 * time.Second, | ||||
| 				KeepAlive: 30 * time.Second, | ||||
| 			}).DialContext, | ||||
| 			ForceAttemptHTTP2:     true, | ||||
| 			MaxIdleConns:          100, | ||||
| 			IdleConnTimeout:       90 * time.Second, | ||||
| 			TLSHandshakeTimeout:   10 * time.Second, | ||||
| 			ExpectContinueTimeout: 1 * time.Second, | ||||
| 			TLSClientConfig: &tls.Config{ | ||||
| 				MinVersion:    tls.VersionTLS12, | ||||
| 				Renegotiation: renengotiation, | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| ## Migration Guide (v4.0.0) | ||||
| 
 | ||||
| Starting from [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0]), the import path will be: | ||||
| Starting from [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0), the import path will be: | ||||
| 
 | ||||
|     "github.com/golang-jwt/jwt/v4" | ||||
| 
 | ||||
|  | @ -19,4 +19,4 @@ go mod tidy | |||
| 
 | ||||
| ## Older releases (before v3.2.0) | ||||
| 
 | ||||
| The original migration guide for older releases can be found at https://github.com/dgrijalva/jwt-go/blob/master/MIGRATION_GUIDE.md. | ||||
| The original migration guide for older releases can be found at https://github.com/dgrijalva/jwt-go/blob/master/MIGRATION_GUIDE.md. | ||||
|  |  | |||
|  | @ -1,12 +1,12 @@ | |||
| # jwt-go | ||||
| 
 | ||||
| [](https://github.com/golang-jwt/jwt/actions/workflows/build.yml) | ||||
| [](https://pkg.go.dev/github.com/golang-jwt/jwt) | ||||
| [](https://pkg.go.dev/github.com/golang-jwt/jwt/v4) | ||||
| 
 | ||||
| A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](https://datatracker.ietf.org/doc/html/rfc7519). | ||||
| 
 | ||||
| Starting with [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0) this project adds Go module support, but maintains backwards compataibility with older `v3.x.y` tags and upstream `github.com/dgrijalva/jwt-go`. | ||||
| See the `MIGRATION_GUIDE.md` for more information. | ||||
| Starting with [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0) this project adds Go module support, but maintains backwards compatibility with older `v3.x.y` tags and upstream `github.com/dgrijalva/jwt-go`. | ||||
| See the [`MIGRATION_GUIDE.md`](./MIGRATION_GUIDE.md) for more information. | ||||
| 
 | ||||
| > After the original author of the library suggested migrating the maintenance of `jwt-go`, a dedicated team of open source maintainers decided to clone the existing library into this repository. See [dgrijalva/jwt-go#462](https://github.com/dgrijalva/jwt-go/issues/462) for a detailed discussion on this topic. | ||||
| 
 | ||||
|  | @ -52,7 +52,7 @@ Here's an example of an extension that integrates with multiple Google Cloud Pla | |||
| 
 | ||||
| ## Compliance | ||||
| 
 | ||||
| This library was last reviewed to comply with [RTF 7519](https://datatracker.ietf.org/doc/html/rfc7519) dated May 2015 with a few notable differences: | ||||
| This library was last reviewed to comply with [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519) dated May 2015 with a few notable differences: | ||||
| 
 | ||||
| * In order to protect against accidental use of [Unsecured JWTs](https://datatracker.ietf.org/doc/html/rfc7519#section-6), tokens using `alg=none` will only be accepted if the constant `jwt.UnsafeAllowNoneSignatureType` is provided as the key. | ||||
| 
 | ||||
|  | @ -91,6 +91,7 @@ Each signing method expects a different object type for its signing keys. See th | |||
| * The [HMAC signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodHMAC) (`HS256`,`HS384`,`HS512`) expect `[]byte` values for signing and validation | ||||
| * The [RSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodRSA) (`RS256`,`RS384`,`RS512`) expect `*rsa.PrivateKey` for signing and `*rsa.PublicKey` for validation | ||||
| * The [ECDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodECDSA) (`ES256`,`ES384`,`ES512`) expect `*ecdsa.PrivateKey` for signing and `*ecdsa.PublicKey` for validation | ||||
| * The [EdDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodEd25519) (`Ed25519`) expect `ed25519.PrivateKey` for signing and `ed25519.PublicKey` for validation | ||||
| 
 | ||||
| ### JWT and OAuth | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,9 +12,122 @@ type Claims interface { | |||
| 	Valid() error | ||||
| } | ||||
| 
 | ||||
| // StandardClaims are a structured version of the Claims Section, as referenced at
 | ||||
| // https://tools.ietf.org/html/rfc7519#section-4.1
 | ||||
| // See examples for how to use this with your own claim types
 | ||||
| // RegisteredClaims are a structured version of the JWT Claims Set,
 | ||||
| // restricted to Registered Claim Names, as referenced at
 | ||||
| // https://datatracker.ietf.org/doc/html/rfc7519#section-4.1
 | ||||
| //
 | ||||
| // This type can be used on its own, but then additional private and
 | ||||
| // public claims embedded in the JWT will not be parsed. The typical usecase
 | ||||
| // therefore is to embedded this in a user-defined claim type.
 | ||||
| //
 | ||||
| // See examples for how to use this with your own claim types.
 | ||||
| type RegisteredClaims struct { | ||||
| 	// the `iss` (Issuer) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1
 | ||||
| 	Issuer string `json:"iss,omitempty"` | ||||
| 
 | ||||
| 	// the `sub` (Subject) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.2
 | ||||
| 	Subject string `json:"sub,omitempty"` | ||||
| 
 | ||||
| 	// the `aud` (Audience) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3
 | ||||
| 	Audience ClaimStrings `json:"aud,omitempty"` | ||||
| 
 | ||||
| 	// the `exp` (Expiration Time) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4
 | ||||
| 	ExpiresAt *NumericDate `json:"exp,omitempty"` | ||||
| 
 | ||||
| 	// the `nbf` (Not Before) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5
 | ||||
| 	NotBefore *NumericDate `json:"nbf,omitempty"` | ||||
| 
 | ||||
| 	// the `iat` (Issued At) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6
 | ||||
| 	IssuedAt *NumericDate `json:"iat,omitempty"` | ||||
| 
 | ||||
| 	// the `jti` (JWT ID) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.7
 | ||||
| 	ID string `json:"jti,omitempty"` | ||||
| } | ||||
| 
 | ||||
| // Valid validates time based claims "exp, iat, nbf".
 | ||||
| // There is no accounting for clock skew.
 | ||||
| // As well, if any of the above claims are not in the token, it will still
 | ||||
| // be considered a valid claim.
 | ||||
| func (c RegisteredClaims) Valid() error { | ||||
| 	vErr := new(ValidationError) | ||||
| 	now := TimeFunc() | ||||
| 
 | ||||
| 	// The claims below are optional, by default, so if they are set to the
 | ||||
| 	// default value in Go, let's not fail the verification for them.
 | ||||
| 	if !c.VerifyExpiresAt(now, false) { | ||||
| 		delta := now.Sub(c.ExpiresAt.Time) | ||||
| 		vErr.Inner = fmt.Errorf("token is expired by %v", delta) | ||||
| 		vErr.Errors |= ValidationErrorExpired | ||||
| 	} | ||||
| 
 | ||||
| 	if !c.VerifyIssuedAt(now, false) { | ||||
| 		vErr.Inner = fmt.Errorf("token used before issued") | ||||
| 		vErr.Errors |= ValidationErrorIssuedAt | ||||
| 	} | ||||
| 
 | ||||
| 	if !c.VerifyNotBefore(now, false) { | ||||
| 		vErr.Inner = fmt.Errorf("token is not valid yet") | ||||
| 		vErr.Errors |= ValidationErrorNotValidYet | ||||
| 	} | ||||
| 
 | ||||
| 	if vErr.valid() { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	return vErr | ||||
| } | ||||
| 
 | ||||
| // VerifyAudience compares the aud claim against cmp.
 | ||||
| // If required is false, this method will return true if the value matches or is unset
 | ||||
| func (c *RegisteredClaims) VerifyAudience(cmp string, req bool) bool { | ||||
| 	return verifyAud(c.Audience, cmp, req) | ||||
| } | ||||
| 
 | ||||
| // VerifyExpiresAt compares the exp claim against cmp (cmp < exp).
 | ||||
| // If req is false, it will return true, if exp is unset.
 | ||||
| func (c *RegisteredClaims) VerifyExpiresAt(cmp time.Time, req bool) bool { | ||||
| 	if c.ExpiresAt == nil { | ||||
| 		return verifyExp(nil, cmp, req) | ||||
| 	} | ||||
| 
 | ||||
| 	return verifyExp(&c.ExpiresAt.Time, cmp, req) | ||||
| } | ||||
| 
 | ||||
| // VerifyIssuedAt compares the iat claim against cmp (cmp >= iat).
 | ||||
| // If req is false, it will return true, if iat is unset.
 | ||||
| func (c *RegisteredClaims) VerifyIssuedAt(cmp time.Time, req bool) bool { | ||||
| 	if c.IssuedAt == nil { | ||||
| 		return verifyIat(nil, cmp, req) | ||||
| 	} | ||||
| 
 | ||||
| 	return verifyIat(&c.IssuedAt.Time, cmp, req) | ||||
| } | ||||
| 
 | ||||
| // VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf).
 | ||||
| // If req is false, it will return true, if nbf is unset.
 | ||||
| func (c *RegisteredClaims) VerifyNotBefore(cmp time.Time, req bool) bool { | ||||
| 	if c.NotBefore == nil { | ||||
| 		return verifyNbf(nil, cmp, req) | ||||
| 	} | ||||
| 
 | ||||
| 	return verifyNbf(&c.NotBefore.Time, cmp, req) | ||||
| } | ||||
| 
 | ||||
| // VerifyIssuer compares the iss claim against cmp.
 | ||||
| // If required is false, this method will return true if the value matches or is unset
 | ||||
| func (c *RegisteredClaims) VerifyIssuer(cmp string, req bool) bool { | ||||
| 	return verifyIss(c.Issuer, cmp, req) | ||||
| } | ||||
| 
 | ||||
| // StandardClaims are a structured version of the JWT Claims Set, as referenced at
 | ||||
| // https://datatracker.ietf.org/doc/html/rfc7519#section-4. They do not follow the
 | ||||
| // specification exactly, since they were based on an earlier draft of the
 | ||||
| // specification and not updated. The main difference is that they only
 | ||||
| // support integer-based date fields and singular audiences. This might lead to
 | ||||
| // incompatibilities with other JWT implementations. The use of this is discouraged, instead
 | ||||
| // the newer RegisteredClaims struct should be used.
 | ||||
| //
 | ||||
| // Deprecated: Use RegisteredClaims instead for a forward-compatible way to access registered claims in a struct.
 | ||||
| type StandardClaims struct { | ||||
| 	Audience  string `json:"aud,omitempty"` | ||||
| 	ExpiresAt int64  `json:"exp,omitempty"` | ||||
|  | @ -41,7 +154,7 @@ func (c StandardClaims) Valid() error { | |||
| 	} | ||||
| 
 | ||||
| 	if !c.VerifyIssuedAt(now, false) { | ||||
| 		vErr.Inner = fmt.Errorf("Token used before issued") | ||||
| 		vErr.Inner = fmt.Errorf("token used before issued") | ||||
| 		vErr.Errors |= ValidationErrorIssuedAt | ||||
| 	} | ||||
| 
 | ||||
|  | @ -63,16 +176,37 @@ func (c *StandardClaims) VerifyAudience(cmp string, req bool) bool { | |||
| 	return verifyAud([]string{c.Audience}, cmp, req) | ||||
| } | ||||
| 
 | ||||
| // VerifyExpiresAt compares the exp claim against cmp.
 | ||||
| // If required is false, this method will return true if the value matches or is unset
 | ||||
| // VerifyExpiresAt compares the exp claim against cmp (cmp < exp).
 | ||||
| // If req is false, it will return true, if exp is unset.
 | ||||
| func (c *StandardClaims) VerifyExpiresAt(cmp int64, req bool) bool { | ||||
| 	return verifyExp(c.ExpiresAt, cmp, req) | ||||
| 	if c.ExpiresAt == 0 { | ||||
| 		return verifyExp(nil, time.Unix(cmp, 0), req) | ||||
| 	} | ||||
| 
 | ||||
| 	t := time.Unix(c.ExpiresAt, 0) | ||||
| 	return verifyExp(&t, time.Unix(cmp, 0), req) | ||||
| } | ||||
| 
 | ||||
| // VerifyIssuedAt compares the iat claim against cmp.
 | ||||
| // If required is false, this method will return true if the value matches or is unset
 | ||||
| // VerifyIssuedAt compares the iat claim against cmp (cmp >= iat).
 | ||||
| // If req is false, it will return true, if iat is unset.
 | ||||
| func (c *StandardClaims) VerifyIssuedAt(cmp int64, req bool) bool { | ||||
| 	return verifyIat(c.IssuedAt, cmp, req) | ||||
| 	if c.IssuedAt == 0 { | ||||
| 		return verifyIat(nil, time.Unix(cmp, 0), req) | ||||
| 	} | ||||
| 
 | ||||
| 	t := time.Unix(c.IssuedAt, 0) | ||||
| 	return verifyIat(&t, time.Unix(cmp, 0), req) | ||||
| } | ||||
| 
 | ||||
| // VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf).
 | ||||
| // If req is false, it will return true, if nbf is unset.
 | ||||
| func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool { | ||||
| 	if c.NotBefore == 0 { | ||||
| 		return verifyNbf(nil, time.Unix(cmp, 0), req) | ||||
| 	} | ||||
| 
 | ||||
| 	t := time.Unix(c.NotBefore, 0) | ||||
| 	return verifyNbf(&t, time.Unix(cmp, 0), req) | ||||
| } | ||||
| 
 | ||||
| // VerifyIssuer compares the iss claim against cmp.
 | ||||
|  | @ -81,12 +215,6 @@ func (c *StandardClaims) VerifyIssuer(cmp string, req bool) bool { | |||
| 	return verifyIss(c.Issuer, cmp, req) | ||||
| } | ||||
| 
 | ||||
| // VerifyNotBefore compares the nbf claim against cmp.
 | ||||
| // If required is false, this method will return true if the value matches or is unset
 | ||||
| func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool { | ||||
| 	return verifyNbf(c.NotBefore, cmp, req) | ||||
| } | ||||
| 
 | ||||
| // ----- helpers
 | ||||
| 
 | ||||
| func verifyAud(aud []string, cmp string, required bool) bool { | ||||
|  | @ -112,18 +240,25 @@ func verifyAud(aud []string, cmp string, required bool) bool { | |||
| 	return result | ||||
| } | ||||
| 
 | ||||
| func verifyExp(exp int64, now int64, required bool) bool { | ||||
| 	if exp == 0 { | ||||
| func verifyExp(exp *time.Time, now time.Time, required bool) bool { | ||||
| 	if exp == nil { | ||||
| 		return !required | ||||
| 	} | ||||
| 	return now <= exp | ||||
| 	return now.Before(*exp) | ||||
| } | ||||
| 
 | ||||
| func verifyIat(iat int64, now int64, required bool) bool { | ||||
| 	if iat == 0 { | ||||
| func verifyIat(iat *time.Time, now time.Time, required bool) bool { | ||||
| 	if iat == nil { | ||||
| 		return !required | ||||
| 	} | ||||
| 	return now >= iat | ||||
| 	return now.After(*iat) || now.Equal(*iat) | ||||
| } | ||||
| 
 | ||||
| func verifyNbf(nbf *time.Time, now time.Time, required bool) bool { | ||||
| 	if nbf == nil { | ||||
| 		return !required | ||||
| 	} | ||||
| 	return now.After(*nbf) || now.Equal(*nbf) | ||||
| } | ||||
| 
 | ||||
| func verifyIss(iss string, cmp string, required bool) bool { | ||||
|  | @ -136,10 +271,3 @@ func verifyIss(iss string, cmp string, required bool) bool { | |||
| 		return false | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func verifyNbf(nbf int64, now int64, required bool) bool { | ||||
| 	if nbf == 0 { | ||||
| 		return !required | ||||
| 	} | ||||
| 	return now >= nbf | ||||
| } | ||||
|  |  | |||
|  | @ -3,7 +3,9 @@ package jwt | |||
| import ( | ||||
| 	"errors" | ||||
| 
 | ||||
| 	"crypto" | ||||
| 	"crypto/ed25519" | ||||
| 	"crypto/rand" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
|  | @ -62,20 +64,22 @@ func (m *SigningMethodEd25519) Verify(signingString, signature string, key inter | |||
| // Sign implements token signing for the SigningMethod.
 | ||||
| // For this signing method, key must be an ed25519.PrivateKey
 | ||||
| func (m *SigningMethodEd25519) Sign(signingString string, key interface{}) (string, error) { | ||||
| 	var ed25519Key ed25519.PrivateKey | ||||
| 	var ed25519Key crypto.Signer | ||||
| 	var ok bool | ||||
| 
 | ||||
| 	if ed25519Key, ok = key.(ed25519.PrivateKey); !ok { | ||||
| 	if ed25519Key, ok = key.(crypto.Signer); !ok { | ||||
| 		return "", ErrInvalidKeyType | ||||
| 	} | ||||
| 
 | ||||
| 	// ed25519.Sign panics if private key not equal to ed25519.PrivateKeySize
 | ||||
| 	// this allows to avoid recover usage
 | ||||
| 	if len(ed25519Key) != ed25519.PrivateKeySize { | ||||
| 	if _, ok := ed25519Key.Public().(ed25519.PublicKey); !ok { | ||||
| 		return "", ErrInvalidKey | ||||
| 	} | ||||
| 
 | ||||
| 	// Sign the string and return the encoded result
 | ||||
| 	sig := ed25519.Sign(ed25519Key, []byte(signingString)) | ||||
| 	// ed25519 performs a two-pass hash as part of its algorithm. Therefore, we need to pass a non-prehashed message into the Sign function, as indicated by crypto.Hash(0)
 | ||||
| 	sig, err := ed25519Key.Sign(rand.Reader, []byte(signingString), crypto.Hash(0)) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return EncodeSegment(sig), nil | ||||
| } | ||||
|  |  | |||
|  | @ -53,6 +53,11 @@ func (e ValidationError) Error() string { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Unwrap gives errors.Is and errors.As access to the inner error.
 | ||||
| func (e *ValidationError) Unwrap() error { | ||||
| 	return e.Inner | ||||
| } | ||||
| 
 | ||||
| // No errors
 | ||||
| func (e *ValidationError) valid() bool { | ||||
| 	return e.Errors == 0 | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ package jwt | |||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"time" | ||||
| 	// "fmt"
 | ||||
| ) | ||||
| 
 | ||||
|  | @ -31,37 +32,81 @@ func (m MapClaims) VerifyAudience(cmp string, req bool) bool { | |||
| 	return verifyAud(aud, cmp, req) | ||||
| } | ||||
| 
 | ||||
| // VerifyExpiresAt compares the exp claim against cmp.
 | ||||
| // If required is false, this method will return true if the value matches or is unset
 | ||||
| // VerifyExpiresAt compares the exp claim against cmp (cmp <= exp).
 | ||||
| // If req is false, it will return true, if exp is unset.
 | ||||
| func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool { | ||||
| 	exp, ok := m["exp"] | ||||
| 	cmpTime := time.Unix(cmp, 0) | ||||
| 
 | ||||
| 	v, ok := m["exp"] | ||||
| 	if !ok { | ||||
| 		return !req | ||||
| 	} | ||||
| 	switch expType := exp.(type) { | ||||
| 
 | ||||
| 	switch exp := v.(type) { | ||||
| 	case float64: | ||||
| 		return verifyExp(int64(expType), cmp, req) | ||||
| 		if exp == 0 { | ||||
| 			return verifyExp(nil, cmpTime, req) | ||||
| 		} | ||||
| 
 | ||||
| 		return verifyExp(&newNumericDateFromSeconds(exp).Time, cmpTime, req) | ||||
| 	case json.Number: | ||||
| 		v, _ := expType.Int64() | ||||
| 		return verifyExp(v, cmp, req) | ||||
| 		v, _ := exp.Float64() | ||||
| 
 | ||||
| 		return verifyExp(&newNumericDateFromSeconds(v).Time, cmpTime, req) | ||||
| 	} | ||||
| 
 | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| // VerifyIssuedAt compares the iat claim against cmp.
 | ||||
| // If required is false, this method will return true if the value matches or is unset
 | ||||
| // VerifyIssuedAt compares the exp claim against cmp (cmp >= iat).
 | ||||
| // If req is false, it will return true, if iat is unset.
 | ||||
| func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool { | ||||
| 	iat, ok := m["iat"] | ||||
| 	cmpTime := time.Unix(cmp, 0) | ||||
| 
 | ||||
| 	v, ok := m["iat"] | ||||
| 	if !ok { | ||||
| 		return !req | ||||
| 	} | ||||
| 	switch iatType := iat.(type) { | ||||
| 
 | ||||
| 	switch iat := v.(type) { | ||||
| 	case float64: | ||||
| 		return verifyIat(int64(iatType), cmp, req) | ||||
| 		if iat == 0 { | ||||
| 			return verifyIat(nil, cmpTime, req) | ||||
| 		} | ||||
| 
 | ||||
| 		return verifyIat(&newNumericDateFromSeconds(iat).Time, cmpTime, req) | ||||
| 	case json.Number: | ||||
| 		v, _ := iatType.Int64() | ||||
| 		return verifyIat(v, cmp, req) | ||||
| 		v, _ := iat.Float64() | ||||
| 
 | ||||
| 		return verifyIat(&newNumericDateFromSeconds(v).Time, cmpTime, req) | ||||
| 	} | ||||
| 
 | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| // VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf).
 | ||||
| // If req is false, it will return true, if nbf is unset.
 | ||||
| func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool { | ||||
| 	cmpTime := time.Unix(cmp, 0) | ||||
| 
 | ||||
| 	v, ok := m["nbf"] | ||||
| 	if !ok { | ||||
| 		return !req | ||||
| 	} | ||||
| 
 | ||||
| 	switch nbf := v.(type) { | ||||
| 	case float64: | ||||
| 		if nbf == 0 { | ||||
| 			return verifyNbf(nil, cmpTime, req) | ||||
| 		} | ||||
| 
 | ||||
| 		return verifyNbf(&newNumericDateFromSeconds(nbf).Time, cmpTime, req) | ||||
| 	case json.Number: | ||||
| 		v, _ := nbf.Float64() | ||||
| 
 | ||||
| 		return verifyNbf(&newNumericDateFromSeconds(v).Time, cmpTime, req) | ||||
| 	} | ||||
| 
 | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
|  | @ -72,24 +117,7 @@ func (m MapClaims) VerifyIssuer(cmp string, req bool) bool { | |||
| 	return verifyIss(iss, cmp, req) | ||||
| } | ||||
| 
 | ||||
| // VerifyNotBefore compares the nbf claim against cmp.
 | ||||
| // If required is false, this method will return true if the value matches or is unset
 | ||||
| func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool { | ||||
| 	nbf, ok := m["nbf"] | ||||
| 	if !ok { | ||||
| 		return !req | ||||
| 	} | ||||
| 	switch nbfType := nbf.(type) { | ||||
| 	case float64: | ||||
| 		return verifyNbf(int64(nbfType), cmp, req) | ||||
| 	case json.Number: | ||||
| 		v, _ := nbfType.Int64() | ||||
| 		return verifyNbf(v, cmp, req) | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| // Valid calidates time based claims "exp, iat, nbf".
 | ||||
| // Valid validates time based claims "exp, iat, nbf".
 | ||||
| // There is no accounting for clock skew.
 | ||||
| // As well, if any of the above claims are not in the token, it will still
 | ||||
| // be considered a valid claim.
 | ||||
|  |  | |||
|  | @ -8,14 +8,36 @@ import ( | |||
| ) | ||||
| 
 | ||||
| type Parser struct { | ||||
| 	ValidMethods         []string // If populated, only these methods will be considered valid
 | ||||
| 	UseJSONNumber        bool     // Use JSON Number format in JSON decoder
 | ||||
| 	SkipClaimsValidation bool     // Skip claims validation during token parsing
 | ||||
| 	// If populated, only these methods will be considered valid.
 | ||||
| 	//
 | ||||
| 	// Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead.
 | ||||
| 	ValidMethods []string | ||||
| 
 | ||||
| 	// Use JSON Number format in JSON decoder.
 | ||||
| 	//
 | ||||
| 	// Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead.
 | ||||
| 	UseJSONNumber bool | ||||
| 
 | ||||
| 	// Skip claims validation during token parsing.
 | ||||
| 	//
 | ||||
| 	// Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead.
 | ||||
| 	SkipClaimsValidation bool | ||||
| } | ||||
| 
 | ||||
| // Parse parses, validates, and returns a token.
 | ||||
| // NewParser creates a new Parser with the specified options
 | ||||
| func NewParser(options ...ParserOption) *Parser { | ||||
| 	p := &Parser{} | ||||
| 
 | ||||
| 	// loop through our parsing options and apply them
 | ||||
| 	for _, option := range options { | ||||
| 		option(p) | ||||
| 	} | ||||
| 
 | ||||
| 	return p | ||||
| } | ||||
| 
 | ||||
| // Parse parses, validates, verifies the signature and returns the parsed token.
 | ||||
| // keyFunc will receive the parsed token and should return the key for validating.
 | ||||
| // If everything is kosher, err will be nil
 | ||||
| func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { | ||||
| 	return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc) | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,29 @@ | |||
| package jwt | ||||
| 
 | ||||
| // ParserOption is used to implement functional-style options that modify the behaviour of the parser. To add
 | ||||
| // new options, just create a function (ideally beginning with With or Without) that returns an anonymous function that
 | ||||
| // takes a *Parser type as input and manipulates its configuration accordingly.
 | ||||
| type ParserOption func(*Parser) | ||||
| 
 | ||||
| // WithValidMethods is an option to supply algorithm methods that the parser will check. Only those methods will be considered valid.
 | ||||
| // It is heavily encouraged to use this option in order to prevent attacks such as https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/.
 | ||||
| func WithValidMethods(methods []string) ParserOption { | ||||
| 	return func(p *Parser) { | ||||
| 		p.ValidMethods = methods | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // WithJSONNumber is an option to configure the underyling JSON parser with UseNumber
 | ||||
| func WithJSONNumber() ParserOption { | ||||
| 	return func(p *Parser) { | ||||
| 		p.UseJSONNumber = true | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // WithoutClaimsValidation is an option to disable claims validation. This option should only be used if you exactly know
 | ||||
| // what you are doing.
 | ||||
| func WithoutClaimsValidation() ParserOption { | ||||
| 	return func(p *Parser) { | ||||
| 		p.SkipClaimsValidation = true | ||||
| 	} | ||||
| } | ||||
|  | @ -33,3 +33,14 @@ func GetSigningMethod(alg string) (method SigningMethod) { | |||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // GetAlgorithms returns a list of registered "alg" names
 | ||||
| func GetAlgorithms() (algs []string) { | ||||
| 	signingMethodLock.RLock() | ||||
| 	defer signingMethodLock.RUnlock() | ||||
| 
 | ||||
| 	for alg := range signingMethods { | ||||
| 		algs = append(algs, alg) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  |  | |||
|  | @ -7,6 +7,14 @@ import ( | |||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
| // DecodePaddingAllowed will switch the codec used for decoding JWTs respectively. Note that the JWS RFC7515
 | ||||
| // states that the tokens will utilize a Base64url encoding with no padding. Unfortunately, some implementations
 | ||||
| // of JWT are producing non-standard tokens, and thus require support for decoding. Note that this is a global
 | ||||
| // variable, and updating it will change the behavior on a package level, and is also NOT go-routine safe.
 | ||||
| // To use the non-recommended decoding, set this boolean to `true` prior to using this package.
 | ||||
| var DecodePaddingAllowed bool | ||||
| 
 | ||||
| // TimeFunc provides the current time when parsing token to validate "exp" claim (expiration time).
 | ||||
| // You can override it to use another time value.  This is useful for testing or if your
 | ||||
| // server uses a different time zone than your tokens.
 | ||||
|  | @ -29,11 +37,12 @@ type Token struct { | |||
| 	Valid     bool                   // Is the token valid?  Populated when you Parse/Verify a token
 | ||||
| } | ||||
| 
 | ||||
| // New creates a new Token.  Takes a signing method
 | ||||
| // New creates a new Token with the specified signing method and an empty map of claims.
 | ||||
| func New(method SigningMethod) *Token { | ||||
| 	return NewWithClaims(method, MapClaims{}) | ||||
| } | ||||
| 
 | ||||
| // NewWithClaims creates a new Token with the specified signing method and claims.
 | ||||
| func NewWithClaims(method SigningMethod, claims Claims) *Token { | ||||
| 	return &Token{ | ||||
| 		Header: map[string]interface{}{ | ||||
|  | @ -45,7 +54,8 @@ func NewWithClaims(method SigningMethod, claims Claims) *Token { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| // SignedString retrieves the complete, signed token
 | ||||
| // SignedString creates and returns a complete, signed JWT.
 | ||||
| // The token is signed using the SigningMethod specified in the token.
 | ||||
| func (t *Token) SignedString(key interface{}) (string, error) { | ||||
| 	var sig, sstr string | ||||
| 	var err error | ||||
|  | @ -82,15 +92,19 @@ func (t *Token) SigningString() (string, error) { | |||
| 	return strings.Join(parts, "."), nil | ||||
| } | ||||
| 
 | ||||
| // Parse parses, validates, and returns a token.
 | ||||
| // keyFunc will receive the parsed token and should return the key for validating.
 | ||||
| // If everything is kosher, err will be nil
 | ||||
| func Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { | ||||
| 	return new(Parser).Parse(tokenString, keyFunc) | ||||
| // Parse parses, validates, verifies the signature and returns the parsed token.
 | ||||
| // keyFunc will receive the parsed token and should return the cryptographic key
 | ||||
| // for verifying the signature.
 | ||||
| // The caller is strongly encouraged to set the WithValidMethods option to
 | ||||
| // validate the 'alg' claim in the token matches the expected algorithm.
 | ||||
| // For more details about the importance of validating the 'alg' claim,
 | ||||
| // see https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/
 | ||||
| func Parse(tokenString string, keyFunc Keyfunc, options ...ParserOption) (*Token, error) { | ||||
| 	return NewParser(options...).Parse(tokenString, keyFunc) | ||||
| } | ||||
| 
 | ||||
| func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) { | ||||
| 	return new(Parser).ParseWithClaims(tokenString, claims, keyFunc) | ||||
| func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc, options ...ParserOption) (*Token, error) { | ||||
| 	return NewParser(options...).ParseWithClaims(tokenString, claims, keyFunc) | ||||
| } | ||||
| 
 | ||||
| // EncodeSegment encodes a JWT specific base64url encoding with padding stripped
 | ||||
|  | @ -106,5 +120,12 @@ func EncodeSegment(seg []byte) string { | |||
| // Deprecated: In a future release, we will demote this function to a non-exported function, since it
 | ||||
| // should only be used internally
 | ||||
| func DecodeSegment(seg string) ([]byte, error) { | ||||
| 	if DecodePaddingAllowed { | ||||
| 		if l := len(seg) % 4; l > 0 { | ||||
| 			seg += strings.Repeat("=", 4-l) | ||||
| 		} | ||||
| 		return base64.URLEncoding.DecodeString(seg) | ||||
| 	} | ||||
| 
 | ||||
| 	return base64.RawURLEncoding.DecodeString(seg) | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,127 @@ | |||
| package jwt | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"math" | ||||
| 	"reflect" | ||||
| 	"strconv" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| // TimePrecision sets the precision of times and dates within this library.
 | ||||
| // This has an influence on the precision of times when comparing expiry or
 | ||||
| // other related time fields. Furthermore, it is also the precision of times
 | ||||
| // when serializing.
 | ||||
| //
 | ||||
| // For backwards compatibility the default precision is set to seconds, so that
 | ||||
| // no fractional timestamps are generated.
 | ||||
| var TimePrecision = time.Second | ||||
| 
 | ||||
| // MarshalSingleStringAsArray modifies the behaviour of the ClaimStrings type, especially
 | ||||
| // its MarshalJSON function.
 | ||||
| //
 | ||||
| // If it is set to true (the default), it will always serialize the type as an
 | ||||
| // array of strings, even if it just contains one element, defaulting to the behaviour
 | ||||
| // of the underlying []string. If it is set to false, it will serialize to a single
 | ||||
| // string, if it contains one element. Otherwise, it will serialize to an array of strings.
 | ||||
| var MarshalSingleStringAsArray = true | ||||
| 
 | ||||
| // NumericDate represents a JSON numeric date value, as referenced at
 | ||||
| // https://datatracker.ietf.org/doc/html/rfc7519#section-2.
 | ||||
| type NumericDate struct { | ||||
| 	time.Time | ||||
| } | ||||
| 
 | ||||
| // NewNumericDate constructs a new *NumericDate from a standard library time.Time struct.
 | ||||
| // It will truncate the timestamp according to the precision specified in TimePrecision.
 | ||||
| func NewNumericDate(t time.Time) *NumericDate { | ||||
| 	return &NumericDate{t.Truncate(TimePrecision)} | ||||
| } | ||||
| 
 | ||||
| // newNumericDateFromSeconds creates a new *NumericDate out of a float64 representing a
 | ||||
| // UNIX epoch with the float fraction representing non-integer seconds.
 | ||||
| func newNumericDateFromSeconds(f float64) *NumericDate { | ||||
| 	round, frac := math.Modf(f) | ||||
| 	return NewNumericDate(time.Unix(int64(round), int64(frac*1e9))) | ||||
| } | ||||
| 
 | ||||
| // MarshalJSON is an implementation of the json.RawMessage interface and serializes the UNIX epoch
 | ||||
| // represented in NumericDate to a byte array, using the precision specified in TimePrecision.
 | ||||
| func (date NumericDate) MarshalJSON() (b []byte, err error) { | ||||
| 	f := float64(date.Truncate(TimePrecision).UnixNano()) / float64(time.Second) | ||||
| 
 | ||||
| 	return []byte(strconv.FormatFloat(f, 'f', -1, 64)), nil | ||||
| } | ||||
| 
 | ||||
| // UnmarshalJSON is an implementation of the json.RawMessage interface and deserializses a
 | ||||
| // NumericDate from a JSON representation, i.e. a json.Number. This number represents an UNIX epoch
 | ||||
| // with either integer or non-integer seconds.
 | ||||
| func (date *NumericDate) UnmarshalJSON(b []byte) (err error) { | ||||
| 	var ( | ||||
| 		number json.Number | ||||
| 		f      float64 | ||||
| 	) | ||||
| 
 | ||||
| 	if err = json.Unmarshal(b, &number); err != nil { | ||||
| 		return fmt.Errorf("could not parse NumericData: %w", err) | ||||
| 	} | ||||
| 
 | ||||
| 	if f, err = number.Float64(); err != nil { | ||||
| 		return fmt.Errorf("could not convert json number value to float: %w", err) | ||||
| 	} | ||||
| 
 | ||||
| 	n := newNumericDateFromSeconds(f) | ||||
| 	*date = *n | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // ClaimStrings is basically just a slice of strings, but it can be either serialized from a string array or just a string.
 | ||||
| // This type is necessary, since the "aud" claim can either be a single string or an array.
 | ||||
| type ClaimStrings []string | ||||
| 
 | ||||
| func (s *ClaimStrings) UnmarshalJSON(data []byte) (err error) { | ||||
| 	var value interface{} | ||||
| 
 | ||||
| 	if err = json.Unmarshal(data, &value); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	var aud []string | ||||
| 
 | ||||
| 	switch v := value.(type) { | ||||
| 	case string: | ||||
| 		aud = append(aud, v) | ||||
| 	case []string: | ||||
| 		aud = ClaimStrings(v) | ||||
| 	case []interface{}: | ||||
| 		for _, vv := range v { | ||||
| 			vs, ok := vv.(string) | ||||
| 			if !ok { | ||||
| 				return &json.UnsupportedTypeError{Type: reflect.TypeOf(vv)} | ||||
| 			} | ||||
| 			aud = append(aud, vs) | ||||
| 		} | ||||
| 	case nil: | ||||
| 		return nil | ||||
| 	default: | ||||
| 		return &json.UnsupportedTypeError{Type: reflect.TypeOf(v)} | ||||
| 	} | ||||
| 
 | ||||
| 	*s = aud | ||||
| 
 | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (s ClaimStrings) MarshalJSON() (b []byte, err error) { | ||||
| 	// This handles a special case in the JWT RFC. If the string array, e.g. used by the "aud" field,
 | ||||
| 	// only contains one element, it MAY be serialized as a single string. This may or may not be
 | ||||
| 	// desired based on the ecosystem of other JWT library used, so we make it configurable by the
 | ||||
| 	// variable MarshalSingleStringAsArray.
 | ||||
| 	if len(s) == 1 && !MarshalSingleStringAsArray { | ||||
| 		return json.Marshal(s[0]) | ||||
| 	} | ||||
| 
 | ||||
| 	return json.Marshal([]string(s)) | ||||
| } | ||||
|  | @ -4,7 +4,7 @@ | |||
| 
 | ||||
| // Package acme provides an implementation of the
 | ||||
| // Automatic Certificate Management Environment (ACME) spec.
 | ||||
| // The intial implementation was based on ACME draft-02 and
 | ||||
| // The initial implementation was based on ACME draft-02 and
 | ||||
| // is now being extended to comply with RFC 8555.
 | ||||
| // See https://tools.ietf.org/html/draft-ietf-acme-acme-02
 | ||||
| // and https://tools.ietf.org/html/rfc8555 for details.
 | ||||
|  |  | |||
|  | @ -410,3 +410,29 @@ func isAlreadyRevoked(err error) bool { | |||
| 	e, ok := err.(*Error) | ||||
| 	return ok && e.ProblemType == "urn:ietf:params:acme:error:alreadyRevoked" | ||||
| } | ||||
| 
 | ||||
| // ListCertAlternates retrieves any alternate certificate chain URLs for the
 | ||||
| // given certificate chain URL. These alternate URLs can be passed to FetchCert
 | ||||
| // in order to retrieve the alternate certificate chains.
 | ||||
| //
 | ||||
| // If there are no alternate issuer certificate chains, a nil slice will be
 | ||||
| // returned.
 | ||||
| func (c *Client) ListCertAlternates(ctx context.Context, url string) ([]string, error) { | ||||
| 	if _, err := c.Discover(ctx); err != nil { // required by c.accountKID
 | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	defer res.Body.Close() | ||||
| 
 | ||||
| 	// We don't need the body but we need to discard it so we don't end up
 | ||||
| 	// preventing keep-alive
 | ||||
| 	if _, err := io.Copy(ioutil.Discard, res.Body); err != nil { | ||||
| 		return nil, fmt.Errorf("acme: cert alternates response stream: %v", err) | ||||
| 	} | ||||
| 	alts := linkHeader(res.Header, "alternate") | ||||
| 	return alts, nil | ||||
| } | ||||
|  |  | |||
|  | @ -6,12 +6,11 @@ github.com/Azure/azure-sdk-for-go/storage | |||
| github.com/Azure/azure-sdk-for-go/version | ||||
| # github.com/Azure/go-autorest v14.2.0+incompatible | ||||
| github.com/Azure/go-autorest | ||||
| # github.com/Azure/go-autorest/autorest v0.11.20 | ||||
| # github.com/Azure/go-autorest/autorest v0.11.24 | ||||
| ## explicit | ||||
| github.com/Azure/go-autorest/autorest | ||||
| github.com/Azure/go-autorest/autorest/azure | ||||
| # github.com/Azure/go-autorest/autorest/adal v0.9.15 | ||||
| ## explicit | ||||
| # github.com/Azure/go-autorest/autorest/adal v0.9.18 | ||||
| github.com/Azure/go-autorest/autorest/adal | ||||
| # github.com/Azure/go-autorest/autorest/date v0.3.0 | ||||
| github.com/Azure/go-autorest/autorest/date | ||||
|  | @ -115,7 +114,7 @@ github.com/felixge/httpsnoop | |||
| # github.com/gofrs/uuid v4.0.0+incompatible | ||||
| ## explicit | ||||
| github.com/gofrs/uuid | ||||
| # github.com/golang-jwt/jwt/v4 v4.0.0 | ||||
| # github.com/golang-jwt/jwt/v4 v4.2.0 | ||||
| github.com/golang-jwt/jwt/v4 | ||||
| # github.com/golang/protobuf v1.3.2 | ||||
| github.com/golang/protobuf/proto | ||||
|  | @ -184,7 +183,7 @@ github.com/yvasiyarov/gorelic | |||
| # github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f | ||||
| ## explicit | ||||
| github.com/yvasiyarov/newrelic_platform_go | ||||
| # golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 | ||||
| # golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 | ||||
| ## explicit | ||||
| golang.org/x/crypto/acme | ||||
| golang.org/x/crypto/acme/autocert | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue