Merge pull request #5596 from laurazard/update-jwt-dep-v4

deps: update `go-jose/go-jose` to `v4`
This commit is contained in:
Sebastiaan van Stijn 2024-11-05 15:29:00 +01:00 committed by GitHub
commit 8c22315e31
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
42 changed files with 558 additions and 310 deletions

View File

@ -1,7 +1,8 @@
package oauth package oauth
import ( import (
"github.com/go-jose/go-jose/v3/jwt" "github.com/go-jose/go-jose/v4"
"github.com/go-jose/go-jose/v4/jwt"
) )
// Claims represents standard claims along with some custom ones. // Claims represents standard claims along with some custom ones.
@ -66,8 +67,23 @@ func GetClaims(accessToken string) (claims Claims, err error) {
return return
} }
// allowedSignatureAlgorithms is a list of allowed signature algorithms for JWTs.
// We add all supported algorithms for Auth0, including with higher key lengths.
// See auth0 docs: https://auth0.com/docs/get-started/applications/signing-algorithms
var allowedSignatureAlgorithms = []jose.SignatureAlgorithm{
jose.HS256,
jose.HS384,
jose.HS512,
jose.RS256, // currently used for auth0
jose.RS384,
jose.RS512,
jose.PS256,
jose.PS384,
jose.PS512,
}
// parseSigned parses a JWT and returns the signature object or error. This does // parseSigned parses a JWT and returns the signature object or error. This does
// not verify the validity of the JWT. // not verify the validity of the JWT.
func parseSigned(token string) (*jwt.JSONWebToken, error) { func parseSigned(token string) (*jwt.JSONWebToken, error) {
return jwt.ParseSigned(token) return jwt.ParseSigned(token, allowedSignatureAlgorithms)
} }

View File

@ -18,7 +18,7 @@ require (
github.com/docker/go-connections v0.5.0 github.com/docker/go-connections v0.5.0
github.com/docker/go-units v0.5.0 github.com/docker/go-units v0.5.0
github.com/fvbommel/sortorder v1.1.0 github.com/fvbommel/sortorder v1.1.0
github.com/go-jose/go-jose/v3 v3.0.3 github.com/go-jose/go-jose/v4 v4.0.4
github.com/go-viper/mapstructure/v2 v2.0.0 github.com/go-viper/mapstructure/v2 v2.0.0
github.com/gogo/protobuf v1.3.2 github.com/gogo/protobuf v1.3.2
github.com/google/go-cmp v0.6.0 github.com/google/go-cmp v0.6.0

View File

@ -76,8 +76,8 @@ github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw=
github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E=
github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
@ -106,7 +106,6 @@ github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519
github.com/google/certificate-transparency-go v1.1.4 h1:hCyXHDbtqlr/lMXU0D4WgbalXL0Zk4dSWWMbPV8VrqY= github.com/google/certificate-transparency-go v1.1.4 h1:hCyXHDbtqlr/lMXU0D4WgbalXL0Zk4dSWWMbPV8VrqY=
github.com/google/certificate-transparency-go v1.1.4/go.mod h1:D6lvbfwckhNrbM9WVl1EVeMOyzC19mpIjMOI4nxBHtQ= github.com/google/certificate-transparency-go v1.1.4/go.mod h1:D6lvbfwckhNrbM9WVl1EVeMOyzC19mpIjMOI4nxBHtQ=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@ -280,7 +279,6 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zmap/zcrypto v0.0.0-20210511125630-18f1e0152cfc h1:zkGwegkOW709y0oiAraH/3D8njopUR/pARHv4tZZ6pw= github.com/zmap/zcrypto v0.0.0-20210511125630-18f1e0152cfc h1:zkGwegkOW709y0oiAraH/3D8njopUR/pARHv4tZZ6pw=
github.com/zmap/zcrypto v0.0.0-20210511125630-18f1e0152cfc/go.mod h1:FM4U1E3NzlNMRnSUTU3P1UdukWhYGifqEsjk9fn7BCk= github.com/zmap/zcrypto v0.0.0-20210511125630-18f1e0152cfc/go.mod h1:FM4U1E3NzlNMRnSUTU3P1UdukWhYGifqEsjk9fn7BCk=
github.com/zmap/zlint/v3 v3.1.0 h1:WjVytZo79m/L1+/Mlphl09WBob6YTGljN5IGWZFpAv0= github.com/zmap/zlint/v3 v3.1.0 h1:WjVytZo79m/L1+/Mlphl09WBob6YTGljN5IGWZFpAv0=
@ -318,14 +316,10 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/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-20181114220301-adae6a3d119a/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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@ -333,10 +327,6 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -345,8 +335,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -358,32 +346,16 @@ golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
@ -392,8 +364,6 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -1,133 +0,0 @@
/*-
* Copyright 2016 Zbigniew Mandziejewicz
* Copyright 2016 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jwt
import (
"fmt"
"strings"
jose "github.com/go-jose/go-jose/v3"
"github.com/go-jose/go-jose/v3/json"
)
// JSONWebToken represents a JSON Web Token (as specified in RFC7519).
type JSONWebToken struct {
payload func(k interface{}) ([]byte, error)
unverifiedPayload func() []byte
Headers []jose.Header
}
type NestedJSONWebToken struct {
enc *jose.JSONWebEncryption
Headers []jose.Header
}
// Claims deserializes a JSONWebToken into dest using the provided key.
func (t *JSONWebToken) Claims(key interface{}, dest ...interface{}) error {
b, err := t.payload(key)
if err != nil {
return err
}
for _, d := range dest {
if err := json.Unmarshal(b, d); err != nil {
return err
}
}
return nil
}
// UnsafeClaimsWithoutVerification deserializes the claims of a
// JSONWebToken into the dests. For signed JWTs, the claims are not
// verified. This function won't work for encrypted JWTs.
func (t *JSONWebToken) UnsafeClaimsWithoutVerification(dest ...interface{}) error {
if t.unverifiedPayload == nil {
return fmt.Errorf("go-jose/go-jose: Cannot get unverified claims")
}
claims := t.unverifiedPayload()
for _, d := range dest {
if err := json.Unmarshal(claims, d); err != nil {
return err
}
}
return nil
}
func (t *NestedJSONWebToken) Decrypt(decryptionKey interface{}) (*JSONWebToken, error) {
b, err := t.enc.Decrypt(decryptionKey)
if err != nil {
return nil, err
}
sig, err := ParseSigned(string(b))
if err != nil {
return nil, err
}
return sig, nil
}
// ParseSigned parses token from JWS form.
func ParseSigned(s string) (*JSONWebToken, error) {
sig, err := jose.ParseSigned(s)
if err != nil {
return nil, err
}
headers := make([]jose.Header, len(sig.Signatures))
for i, signature := range sig.Signatures {
headers[i] = signature.Header
}
return &JSONWebToken{
payload: sig.Verify,
unverifiedPayload: sig.UnsafePayloadWithoutVerification,
Headers: headers,
}, nil
}
// ParseEncrypted parses token from JWE form.
func ParseEncrypted(s string) (*JSONWebToken, error) {
enc, err := jose.ParseEncrypted(s)
if err != nil {
return nil, err
}
return &JSONWebToken{
payload: enc.Decrypt,
Headers: []jose.Header{enc.Header},
}, nil
}
// ParseSignedAndEncrypted parses signed-then-encrypted token from JWE form.
func ParseSignedAndEncrypted(s string) (*NestedJSONWebToken, error) {
enc, err := jose.ParseEncrypted(s)
if err != nil {
return nil, err
}
contentType, _ := enc.Header.ExtraHeaders[jose.HeaderContentType].(string)
if strings.ToUpper(contentType) != "JWT" {
return nil, ErrInvalidContentType
}
return &NestedJSONWebToken{
enc: enc,
Headers: []jose.Header{enc.Header},
}, nil
}

View File

@ -1,3 +1,27 @@
# v4.0.4
## Fixed
- Reverted "Allow unmarshalling JSONWebKeySets with unsupported key types" as a
breaking change. See #136 / #137.
# v4.0.3
## Changed
- Allow unmarshalling JSONWebKeySets with unsupported key types (#130)
- Document that OpaqueKeyEncrypter can't be implemented (for now) (#129)
- Dependency updates
# v4.0.2
## Changed
- Improved documentation of Verify() to note that JSONWebKeySet is a supported
argument type (#104)
- Defined exported error values for missing x5c header and unsupported elliptic
curves error cases (#117)
# v4.0.1 # v4.0.1
## Fixed ## Fixed
@ -45,12 +69,6 @@ token".
[1]: https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf [1]: https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf
# v3.0.3
## Fixed
- Limit decompression output size to prevent a DoS. Backport from v4.0.1.
# v3.0.2 # v3.0.2
## Fixed ## Fixed

View File

@ -1,17 +1,9 @@
# Go JOSE # Go JOSE
### Versions [![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v4.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v4)
[![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v4/jwt.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v4/jwt)
[Version 4](https://github.com/go-jose/go-jose) [![license](https://img.shields.io/badge/license-apache_2.0-blue.svg?style=flat)](https://raw.githubusercontent.com/go-jose/go-jose/master/LICENSE)
([branch](https://github.com/go-jose/go-jose/), [![test](https://img.shields.io/github/checks-status/go-jose/go-jose/v4)](https://github.com/go-jose/go-jose/actions)
[doc](https://pkg.go.dev/github.com/go-jose/go-jose/v4), [releases](https://github.com/go-jose/go-jose/releases)) is the current stable version:
import "github.com/go-jose/go-jose/v4"
The old [square/go-jose](https://github.com/square/go-jose) repo contains the prior v1 and v2 versions, which
are deprecated.
### Summary
Package jose aims to provide an implementation of the Javascript Object Signing Package jose aims to provide an implementation of the Javascript Object Signing
and Encryption set of standards. This includes support for JSON Web Encryption, and Encryption set of standards. This includes support for JSON Web Encryption,
@ -43,6 +35,20 @@ of [case-insensitive matching](https://www.ietf.org/mail-archive/web/json/curren
This is to avoid differences in interpretation of messages between go-jose and This is to avoid differences in interpretation of messages between go-jose and
libraries in other languages. libraries in other languages.
### Versions
[Version 4](https://github.com/go-jose/go-jose)
([branch](https://github.com/go-jose/go-jose/tree/main),
[doc](https://pkg.go.dev/github.com/go-jose/go-jose/v4), [releases](https://github.com/go-jose/go-jose/releases)) is the current stable version:
import "github.com/go-jose/go-jose/v4"
The old [square/go-jose](https://github.com/square/go-jose) repo contains the prior v1 and v2 versions, which
are still useable but not actively developed anymore.
Version 3, in this repo, is still receiving security fixes but not functionality
updates.
### Supported algorithms ### Supported algorithms
See below for a table of supported algorithms. Algorithm identifiers match See below for a table of supported algorithms. Algorithm identifiers match
@ -98,11 +104,11 @@ allows attaching a key id.
## Examples ## Examples
[![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v3.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v3) [![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v4.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v4)
[![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v3/jwt.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v3/jwt) [![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v4/jwt.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v4/jwt)
Examples can be found in the Godoc Examples can be found in the Godoc
reference for this package. The reference for this package. The
[`jose-util`](https://github.com/go-jose/go-jose/tree/v3/jose-util) [`jose-util`](https://github.com/go-jose/go-jose/tree/v4/jose-util)
subdirectory also contains a small command-line utility which might be useful subdirectory also contains a small command-line utility which might be useful
as an example as well. as an example as well.

View File

@ -29,8 +29,8 @@ import (
"fmt" "fmt"
"math/big" "math/big"
josecipher "github.com/go-jose/go-jose/v3/cipher" josecipher "github.com/go-jose/go-jose/v4/cipher"
"github.com/go-jose/go-jose/v3/json" "github.com/go-jose/go-jose/v4/json"
) )
// A generic RSA-based encrypter/verifier // A generic RSA-based encrypter/verifier

View File

@ -22,7 +22,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/go-jose/go-jose/v3/json" "github.com/go-jose/go-jose/v4/json"
) )
// Encrypter represents an encrypter which produces an encrypted JWE object. // Encrypter represents an encrypter which produces an encrypted JWE object.
@ -459,7 +459,10 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
return nil, fmt.Errorf("go-jose/go-jose: unsupported crit header") return nil, fmt.Errorf("go-jose/go-jose: unsupported crit header")
} }
key := tryJWKS(decryptionKey, obj.Header) key, err := tryJWKS(decryptionKey, obj.Header)
if err != nil {
return nil, err
}
decrypter, err := newDecrypter(key) decrypter, err := newDecrypter(key)
if err != nil { if err != nil {
return nil, err return nil, err
@ -529,7 +532,10 @@ func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Heade
return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: unsupported crit header") return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: unsupported crit header")
} }
key := tryJWKS(decryptionKey, obj.Header) key, err := tryJWKS(decryptionKey, obj.Header)
if err != nil {
return -1, Header{}, nil, err
}
decrypter, err := newDecrypter(key) decrypter, err := newDecrypter(key)
if err != nil { if err != nil {
return -1, Header{}, nil, err return -1, Header{}, nil, err

View File

@ -27,7 +27,7 @@ import (
"strings" "strings"
"unicode" "unicode"
"github.com/go-jose/go-jose/v3/json" "github.com/go-jose/go-jose/v4/json"
) )
// Helper function to serialize known-good objects. // Helper function to serialize known-good objects.
@ -106,10 +106,7 @@ func inflate(input []byte) ([]byte, error) {
output := new(bytes.Buffer) output := new(bytes.Buffer)
reader := flate.NewReader(bytes.NewBuffer(input)) reader := flate.NewReader(bytes.NewBuffer(input))
maxCompressedSize := 10 * int64(len(input)) maxCompressedSize := max(250_000, 10*int64(len(input)))
if maxCompressedSize < 250000 {
maxCompressedSize = 250000
}
limit := maxCompressedSize + 1 limit := maxCompressedSize + 1
n, err := io.CopyN(output, reader, limit) n, err := io.CopyN(output, reader, limit)
@ -167,7 +164,7 @@ func (b *byteBuffer) UnmarshalJSON(data []byte) error {
return nil return nil
} }
decoded, err := base64URLDecode(encoded) decoded, err := base64.RawURLEncoding.DecodeString(encoded)
if err != nil { if err != nil {
return err return err
} }
@ -197,12 +194,6 @@ func (b byteBuffer) toInt() int {
return int(b.bigInt().Int64()) return int(b.bigInt().Int64())
} }
// base64URLDecode is implemented as defined in https://www.rfc-editor.org/rfc/rfc7515.html#appendix-C
func base64URLDecode(value string) ([]byte, error) {
value = strings.TrimRight(value, "=")
return base64.RawURLEncoding.DecodeString(value)
}
func base64EncodeLen(sl []byte) int { func base64EncodeLen(sl []byte) int {
return base64.RawURLEncoding.EncodedLen(len(sl)) return base64.RawURLEncoding.EncodedLen(len(sl))
} }

View File

@ -18,10 +18,11 @@ package jose
import ( import (
"encoding/base64" "encoding/base64"
"errors"
"fmt" "fmt"
"strings" "strings"
"github.com/go-jose/go-jose/v3/json" "github.com/go-jose/go-jose/v4/json"
) )
// rawJSONWebEncryption represents a raw JWE JSON object. Used for parsing/serializing. // rawJSONWebEncryption represents a raw JWE JSON object. Used for parsing/serializing.
@ -104,29 +105,75 @@ func (obj JSONWebEncryption) computeAuthData() []byte {
return output return output
} }
// ParseEncrypted parses an encrypted message in compact or JWE JSON Serialization format. func containsKeyAlgorithm(haystack []KeyAlgorithm, needle KeyAlgorithm) bool {
func ParseEncrypted(input string) (*JSONWebEncryption, error) { for _, algorithm := range haystack {
input = stripWhitespace(input) if algorithm == needle {
if strings.HasPrefix(input, "{") { return true
return parseEncryptedFull(input) }
} }
return false
return parseEncryptedCompact(input)
} }
// parseEncryptedFull parses a message in compact format. func containsContentEncryption(haystack []ContentEncryption, needle ContentEncryption) bool {
func parseEncryptedFull(input string) (*JSONWebEncryption, error) { for _, algorithm := range haystack {
if algorithm == needle {
return true
}
}
return false
}
// ParseEncrypted parses an encrypted message in JWE Compact or JWE JSON Serialization.
//
// https://datatracker.ietf.org/doc/html/rfc7516#section-3.1
// https://datatracker.ietf.org/doc/html/rfc7516#section-3.2
//
// The keyAlgorithms and contentEncryption parameters are used to validate the "alg" and "enc"
// header parameters respectively. They must be nonempty, and each "alg" or "enc" header in
// parsed data must contain a value that is present in the corresponding parameter. That
// includes the protected and unprotected headers as well as all recipients. To accept
// multiple algorithms, pass a slice of all the algorithms you want to accept.
func ParseEncrypted(input string,
keyEncryptionAlgorithms []KeyAlgorithm,
contentEncryption []ContentEncryption,
) (*JSONWebEncryption, error) {
input = stripWhitespace(input)
if strings.HasPrefix(input, "{") {
return ParseEncryptedJSON(input, keyEncryptionAlgorithms, contentEncryption)
}
return ParseEncryptedCompact(input, keyEncryptionAlgorithms, contentEncryption)
}
// ParseEncryptedJSON parses a message in JWE JSON Serialization.
//
// https://datatracker.ietf.org/doc/html/rfc7516#section-3.2
func ParseEncryptedJSON(
input string,
keyEncryptionAlgorithms []KeyAlgorithm,
contentEncryption []ContentEncryption,
) (*JSONWebEncryption, error) {
var parsed rawJSONWebEncryption var parsed rawJSONWebEncryption
err := json.Unmarshal([]byte(input), &parsed) err := json.Unmarshal([]byte(input), &parsed)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return parsed.sanitized() return parsed.sanitized(keyEncryptionAlgorithms, contentEncryption)
} }
// sanitized produces a cleaned-up JWE object from the raw JSON. // sanitized produces a cleaned-up JWE object from the raw JSON.
func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) { func (parsed *rawJSONWebEncryption) sanitized(
keyEncryptionAlgorithms []KeyAlgorithm,
contentEncryption []ContentEncryption,
) (*JSONWebEncryption, error) {
if len(keyEncryptionAlgorithms) == 0 {
return nil, errors.New("go-jose/go-jose: no key algorithms provided")
}
if len(contentEncryption) == 0 {
return nil, errors.New("go-jose/go-jose: no content encryption algorithms provided")
}
obj := &JSONWebEncryption{ obj := &JSONWebEncryption{
original: parsed, original: parsed,
unprotected: parsed.Unprotected, unprotected: parsed.Unprotected,
@ -170,7 +217,7 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
} else { } else {
obj.recipients = make([]recipientInfo, len(parsed.Recipients)) obj.recipients = make([]recipientInfo, len(parsed.Recipients))
for r := range parsed.Recipients { for r := range parsed.Recipients {
encryptedKey, err := base64URLDecode(parsed.Recipients[r].EncryptedKey) encryptedKey, err := base64.RawURLEncoding.DecodeString(parsed.Recipients[r].EncryptedKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -185,10 +232,31 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
} }
} }
for _, recipient := range obj.recipients { for i, recipient := range obj.recipients {
headers := obj.mergedHeaders(&recipient) headers := obj.mergedHeaders(&recipient)
if headers.getAlgorithm() == "" || headers.getEncryption() == "" { if headers.getAlgorithm() == "" {
return nil, fmt.Errorf("go-jose/go-jose: message is missing alg/enc headers") return nil, fmt.Errorf(`go-jose/go-jose: recipient %d: missing header "alg"`, i)
}
if headers.getEncryption() == "" {
return nil, fmt.Errorf(`go-jose/go-jose: recipient %d: missing header "enc"`, i)
}
err := validateAlgEnc(headers, keyEncryptionAlgorithms, contentEncryption)
if err != nil {
return nil, fmt.Errorf("go-jose/go-jose: recipient %d: %s", i, err)
}
}
if obj.protected != nil {
err := validateAlgEnc(*obj.protected, keyEncryptionAlgorithms, contentEncryption)
if err != nil {
return nil, fmt.Errorf("go-jose/go-jose: protected header: %s", err)
}
}
if obj.unprotected != nil {
err := validateAlgEnc(*obj.unprotected, keyEncryptionAlgorithms, contentEncryption)
if err != nil {
return nil, fmt.Errorf("go-jose/go-jose: unprotected header: %s", err)
} }
} }
@ -200,34 +268,52 @@ func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
return obj, nil return obj, nil
} }
// parseEncryptedCompact parses a message in compact format. func validateAlgEnc(headers rawHeader, keyAlgorithms []KeyAlgorithm, contentEncryption []ContentEncryption) error {
func parseEncryptedCompact(input string) (*JSONWebEncryption, error) { alg := headers.getAlgorithm()
enc := headers.getEncryption()
if alg != "" && !containsKeyAlgorithm(keyAlgorithms, alg) {
return fmt.Errorf("unexpected key algorithm %q; expected %q", alg, keyAlgorithms)
}
if alg != "" && !containsContentEncryption(contentEncryption, enc) {
return fmt.Errorf("unexpected content encryption algorithm %q; expected %q", enc, contentEncryption)
}
return nil
}
// ParseEncryptedCompact parses a message in JWE Compact Serialization.
//
// https://datatracker.ietf.org/doc/html/rfc7516#section-3.1
func ParseEncryptedCompact(
input string,
keyAlgorithms []KeyAlgorithm,
contentEncryption []ContentEncryption,
) (*JSONWebEncryption, error) {
parts := strings.Split(input, ".") parts := strings.Split(input, ".")
if len(parts) != 5 { if len(parts) != 5 {
return nil, fmt.Errorf("go-jose/go-jose: compact JWE format must have five parts") return nil, fmt.Errorf("go-jose/go-jose: compact JWE format must have five parts")
} }
rawProtected, err := base64URLDecode(parts[0]) rawProtected, err := base64.RawURLEncoding.DecodeString(parts[0])
if err != nil { if err != nil {
return nil, err return nil, err
} }
encryptedKey, err := base64URLDecode(parts[1]) encryptedKey, err := base64.RawURLEncoding.DecodeString(parts[1])
if err != nil { if err != nil {
return nil, err return nil, err
} }
iv, err := base64URLDecode(parts[2]) iv, err := base64.RawURLEncoding.DecodeString(parts[2])
if err != nil { if err != nil {
return nil, err return nil, err
} }
ciphertext, err := base64URLDecode(parts[3]) ciphertext, err := base64.RawURLEncoding.DecodeString(parts[3])
if err != nil { if err != nil {
return nil, err return nil, err
} }
tag, err := base64URLDecode(parts[4]) tag, err := base64.RawURLEncoding.DecodeString(parts[4])
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -240,7 +326,7 @@ func parseEncryptedCompact(input string) (*JSONWebEncryption, error) {
Tag: newBuffer(tag), Tag: newBuffer(tag),
} }
return raw.sanitized() return raw.sanitized(keyAlgorithms, contentEncryption)
} }
// CompactSerialize serializes an object using the compact serialization format. // CompactSerialize serializes an object using the compact serialization format.

View File

@ -35,7 +35,7 @@ import (
"reflect" "reflect"
"strings" "strings"
"github.com/go-jose/go-jose/v3/json" "github.com/go-jose/go-jose/v4/json"
) )
// rawJSONWebKey represents a public or private key in JWK format, used for parsing/serializing. // rawJSONWebKey represents a public or private key in JWK format, used for parsing/serializing.
@ -266,7 +266,7 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
// x5t parameters are base64url-encoded SHA thumbprints // x5t parameters are base64url-encoded SHA thumbprints
// See RFC 7517, Section 4.8, https://tools.ietf.org/html/rfc7517#section-4.8 // See RFC 7517, Section 4.8, https://tools.ietf.org/html/rfc7517#section-4.8
x5tSHA1bytes, err := base64URLDecode(raw.X5tSHA1) x5tSHA1bytes, err := base64.RawURLEncoding.DecodeString(raw.X5tSHA1)
if err != nil { if err != nil {
return errors.New("go-jose/go-jose: invalid JWK, x5t header has invalid encoding") return errors.New("go-jose/go-jose: invalid JWK, x5t header has invalid encoding")
} }
@ -286,7 +286,7 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
k.CertificateThumbprintSHA1 = x5tSHA1bytes k.CertificateThumbprintSHA1 = x5tSHA1bytes
x5tSHA256bytes, err := base64URLDecode(raw.X5tSHA256) x5tSHA256bytes, err := base64.RawURLEncoding.DecodeString(raw.X5tSHA256)
if err != nil { if err != nil {
return errors.New("go-jose/go-jose: invalid JWK, x5t#S256 header has invalid encoding") return errors.New("go-jose/go-jose: invalid JWK, x5t#S256 header has invalid encoding")
} }
@ -779,7 +779,13 @@ func (key rawJSONWebKey) symmetricKey() ([]byte, error) {
return key.K.bytes(), nil return key.K.bytes(), nil
} }
func tryJWKS(key interface{}, headers ...Header) interface{} { var (
// ErrJWKSKidNotFound is returned when a JWKS does not contain a JWK with a
// key ID which matches one in the provided tokens headers.
ErrJWKSKidNotFound = errors.New("go-jose/go-jose: JWK with matching kid not found in JWK Set")
)
func tryJWKS(key interface{}, headers ...Header) (interface{}, error) {
var jwks JSONWebKeySet var jwks JSONWebKeySet
switch jwksType := key.(type) { switch jwksType := key.(type) {
@ -788,9 +794,11 @@ func tryJWKS(key interface{}, headers ...Header) interface{} {
case JSONWebKeySet: case JSONWebKeySet:
jwks = jwksType jwks = jwksType
default: default:
return key // If the specified key is not a JWKS, return as is.
return key, nil
} }
// Determine the KID to search for from the headers.
var kid string var kid string
for _, header := range headers { for _, header := range headers {
if header.KeyID != "" { if header.KeyID != "" {
@ -799,14 +807,17 @@ func tryJWKS(key interface{}, headers ...Header) interface{} {
} }
} }
// If no KID is specified in the headers, reject.
if kid == "" { if kid == "" {
return key return nil, ErrJWKSKidNotFound
} }
// Find the JWK with the matching KID. If no JWK with the specified KID is
// found, reject.
keys := jwks.Key(kid) keys := jwks.Key(kid)
if len(keys) == 0 { if len(keys) == 0 {
return key return nil, ErrJWKSKidNotFound
} }
return keys[0].Key return keys[0].Key, nil
} }

View File

@ -23,7 +23,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/go-jose/go-jose/v3/json" "github.com/go-jose/go-jose/v4/json"
) )
// rawJSONWebSignature represents a raw JWS JSON object. Used for parsing/serializing. // rawJSONWebSignature represents a raw JWS JSON object. Used for parsing/serializing.
@ -75,22 +75,41 @@ type Signature struct {
original *rawSignatureInfo original *rawSignatureInfo
} }
// ParseSigned parses a signed message in compact or JWS JSON Serialization format. // ParseSigned parses a signed message in JWS Compact or JWS JSON Serialization.
func ParseSigned(signature string) (*JSONWebSignature, error) { //
// https://datatracker.ietf.org/doc/html/rfc7515#section-7
func ParseSigned(
signature string,
signatureAlgorithms []SignatureAlgorithm,
) (*JSONWebSignature, error) {
signature = stripWhitespace(signature) signature = stripWhitespace(signature)
if strings.HasPrefix(signature, "{") { if strings.HasPrefix(signature, "{") {
return parseSignedFull(signature) return ParseSignedJSON(signature, signatureAlgorithms)
} }
return parseSignedCompact(signature, nil) return parseSignedCompact(signature, nil, signatureAlgorithms)
}
// ParseSignedCompact parses a message in JWS Compact Serialization.
//
// https://datatracker.ietf.org/doc/html/rfc7515#section-7.1
func ParseSignedCompact(
signature string,
signatureAlgorithms []SignatureAlgorithm,
) (*JSONWebSignature, error) {
return parseSignedCompact(signature, nil, signatureAlgorithms)
} }
// ParseDetached parses a signed message in compact serialization format with detached payload. // ParseDetached parses a signed message in compact serialization format with detached payload.
func ParseDetached(signature string, payload []byte) (*JSONWebSignature, error) { func ParseDetached(
signature string,
payload []byte,
signatureAlgorithms []SignatureAlgorithm,
) (*JSONWebSignature, error) {
if payload == nil { if payload == nil {
return nil, errors.New("go-jose/go-jose: nil payload") return nil, errors.New("go-jose/go-jose: nil payload")
} }
return parseSignedCompact(stripWhitespace(signature), payload) return parseSignedCompact(stripWhitespace(signature), payload, signatureAlgorithms)
} }
// Get a header value // Get a header value
@ -137,19 +156,36 @@ func (obj JSONWebSignature) computeAuthData(payload []byte, signature *Signature
return authData.Bytes(), nil return authData.Bytes(), nil
} }
// parseSignedFull parses a message in full format. // ParseSignedJSON parses a message in JWS JSON Serialization.
func parseSignedFull(input string) (*JSONWebSignature, error) { //
// https://datatracker.ietf.org/doc/html/rfc7515#section-7.2
func ParseSignedJSON(
input string,
signatureAlgorithms []SignatureAlgorithm,
) (*JSONWebSignature, error) {
var parsed rawJSONWebSignature var parsed rawJSONWebSignature
err := json.Unmarshal([]byte(input), &parsed) err := json.Unmarshal([]byte(input), &parsed)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return parsed.sanitized() return parsed.sanitized(signatureAlgorithms)
}
func containsSignatureAlgorithm(haystack []SignatureAlgorithm, needle SignatureAlgorithm) bool {
for _, algorithm := range haystack {
if algorithm == needle {
return true
}
}
return false
} }
// sanitized produces a cleaned-up JWS object from the raw JSON. // sanitized produces a cleaned-up JWS object from the raw JSON.
func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) { func (parsed *rawJSONWebSignature) sanitized(signatureAlgorithms []SignatureAlgorithm) (*JSONWebSignature, error) {
if len(signatureAlgorithms) == 0 {
return nil, errors.New("go-jose/go-jose: no signature algorithms specified")
}
if parsed.Payload == nil { if parsed.Payload == nil {
return nil, fmt.Errorf("go-jose/go-jose: missing payload in JWS message") return nil, fmt.Errorf("go-jose/go-jose: missing payload in JWS message")
} }
@ -198,6 +234,12 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
return nil, err return nil, err
} }
alg := SignatureAlgorithm(signature.Header.Algorithm)
if !containsSignatureAlgorithm(signatureAlgorithms, alg) {
return nil, fmt.Errorf("go-jose/go-jose: unexpected signature algorithm %q; expected %q",
alg, signatureAlgorithms)
}
if signature.header != nil { if signature.header != nil {
signature.Unprotected, err = signature.header.sanitized() signature.Unprotected, err = signature.header.sanitized()
if err != nil { if err != nil {
@ -241,6 +283,12 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
return nil, err return nil, err
} }
alg := SignatureAlgorithm(obj.Signatures[i].Header.Algorithm)
if !containsSignatureAlgorithm(signatureAlgorithms, alg) {
return nil, fmt.Errorf("go-jose/go-jose: unexpected signature algorithm %q; expected %q",
alg, signatureAlgorithms)
}
if obj.Signatures[i].header != nil { if obj.Signatures[i].header != nil {
obj.Signatures[i].Unprotected, err = obj.Signatures[i].header.sanitized() obj.Signatures[i].Unprotected, err = obj.Signatures[i].header.sanitized()
if err != nil { if err != nil {
@ -274,7 +322,11 @@ func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
} }
// parseSignedCompact parses a message in compact format. // parseSignedCompact parses a message in compact format.
func parseSignedCompact(input string, payload []byte) (*JSONWebSignature, error) { func parseSignedCompact(
input string,
payload []byte,
signatureAlgorithms []SignatureAlgorithm,
) (*JSONWebSignature, error) {
parts := strings.Split(input, ".") parts := strings.Split(input, ".")
if len(parts) != 3 { if len(parts) != 3 {
return nil, fmt.Errorf("go-jose/go-jose: compact JWS format must have three parts") return nil, fmt.Errorf("go-jose/go-jose: compact JWS format must have three parts")
@ -284,19 +336,19 @@ func parseSignedCompact(input string, payload []byte) (*JSONWebSignature, error)
return nil, fmt.Errorf("go-jose/go-jose: payload is not detached") return nil, fmt.Errorf("go-jose/go-jose: payload is not detached")
} }
rawProtected, err := base64URLDecode(parts[0]) rawProtected, err := base64.RawURLEncoding.DecodeString(parts[0])
if err != nil { if err != nil {
return nil, err return nil, err
} }
if payload == nil { if payload == nil {
payload, err = base64URLDecode(parts[1]) payload, err = base64.RawURLEncoding.DecodeString(parts[1])
if err != nil { if err != nil {
return nil, err return nil, err
} }
} }
signature, err := base64URLDecode(parts[2]) signature, err := base64.RawURLEncoding.DecodeString(parts[2])
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -306,7 +358,7 @@ func parseSignedCompact(input string, payload []byte) (*JSONWebSignature, error)
Protected: newBuffer(rawProtected), Protected: newBuffer(rawProtected),
Signature: newBuffer(signature), Signature: newBuffer(signature),
} }
return raw.sanitized() return raw.sanitized(signatureAlgorithms)
} }
func (obj JSONWebSignature) compactSerialize(detached bool) (string, error) { func (obj JSONWebSignature) compactSerialize(detached bool) (string, error) {

View File

@ -21,13 +21,13 @@ import (
"bytes" "bytes"
"reflect" "reflect"
"github.com/go-jose/go-jose/v3/json" "github.com/go-jose/go-jose/v4/json"
"github.com/go-jose/go-jose/v3" "github.com/go-jose/go-jose/v4"
) )
// Builder is a utility for making JSON Web Tokens. Calls can be chained, and // Builder is a utility for making JSON Web Tokens. Calls can be chained, and
// errors are accumulated until the final call to CompactSerialize/FullSerialize. // errors are accumulated until the final call to Serialize.
type Builder interface { type Builder interface {
// Claims encodes claims into JWE/JWS form. Multiple calls will merge claims // Claims encodes claims into JWE/JWS form. Multiple calls will merge claims
// into single JSON object. If you are passing private claims, make sure to set // into single JSON object. If you are passing private claims, make sure to set
@ -36,15 +36,13 @@ type Builder interface {
Claims(i interface{}) Builder Claims(i interface{}) Builder
// Token builds a JSONWebToken from provided data. // Token builds a JSONWebToken from provided data.
Token() (*JSONWebToken, error) Token() (*JSONWebToken, error)
// FullSerialize serializes a token using the JWS/JWE JSON Serialization format. // Serialize serializes a token.
FullSerialize() (string, error) Serialize() (string, error)
// CompactSerialize serializes a token using the compact serialization format.
CompactSerialize() (string, error)
} }
// NestedBuilder is a utility for making Signed-Then-Encrypted JSON Web Tokens. // NestedBuilder is a utility for making Signed-Then-Encrypted JSON Web Tokens.
// Calls can be chained, and errors are accumulated until final call to // Calls can be chained, and errors are accumulated until final call to
// CompactSerialize/FullSerialize. // Serialize.
type NestedBuilder interface { type NestedBuilder interface {
// Claims encodes claims into JWE/JWS form. Multiple calls will merge claims // Claims encodes claims into JWE/JWS form. Multiple calls will merge claims
// into single JSON object. If you are passing private claims, make sure to set // into single JSON object. If you are passing private claims, make sure to set
@ -53,10 +51,8 @@ type NestedBuilder interface {
Claims(i interface{}) NestedBuilder Claims(i interface{}) NestedBuilder
// Token builds a NestedJSONWebToken from provided data. // Token builds a NestedJSONWebToken from provided data.
Token() (*NestedJSONWebToken, error) Token() (*NestedJSONWebToken, error)
// FullSerialize serializes a token using the JSON Serialization format. // Serialize serializes a token.
FullSerialize() (string, error) Serialize() (string, error)
// CompactSerialize serializes a token using the compact serialization format.
CompactSerialize() (string, error)
} }
type builder struct { type builder struct {
@ -194,7 +190,7 @@ func (b *signedBuilder) Token() (*JSONWebToken, error) {
return b.builder.token(sig.Verify, h) return b.builder.token(sig.Verify, h)
} }
func (b *signedBuilder) CompactSerialize() (string, error) { func (b *signedBuilder) Serialize() (string, error) {
sig, err := b.sign() sig, err := b.sign()
if err != nil { if err != nil {
return "", err return "", err
@ -203,15 +199,6 @@ func (b *signedBuilder) CompactSerialize() (string, error) {
return sig.CompactSerialize() return sig.CompactSerialize()
} }
func (b *signedBuilder) FullSerialize() (string, error) {
sig, err := b.sign()
if err != nil {
return "", err
}
return sig.FullSerialize(), nil
}
func (b *signedBuilder) sign() (*jose.JSONWebSignature, error) { func (b *signedBuilder) sign() (*jose.JSONWebSignature, error) {
if b.err != nil { if b.err != nil {
return nil, b.err return nil, b.err
@ -232,7 +219,7 @@ func (b *encryptedBuilder) Claims(i interface{}) Builder {
} }
} }
func (b *encryptedBuilder) CompactSerialize() (string, error) { func (b *encryptedBuilder) Serialize() (string, error) {
enc, err := b.encrypt() enc, err := b.encrypt()
if err != nil { if err != nil {
return "", err return "", err
@ -241,15 +228,6 @@ func (b *encryptedBuilder) CompactSerialize() (string, error) {
return enc.CompactSerialize() return enc.CompactSerialize()
} }
func (b *encryptedBuilder) FullSerialize() (string, error) {
enc, err := b.encrypt()
if err != nil {
return "", err
}
return enc.FullSerialize(), nil
}
func (b *encryptedBuilder) Token() (*JSONWebToken, error) { func (b *encryptedBuilder) Token() (*JSONWebToken, error) {
enc, err := b.encrypt() enc, err := b.encrypt()
if err != nil { if err != nil {
@ -280,6 +258,8 @@ func (b *nestedBuilder) Claims(i interface{}) NestedBuilder {
} }
} }
// Token produced a token suitable for serialization. It cannot be decrypted
// without serializing and then deserializing.
func (b *nestedBuilder) Token() (*NestedJSONWebToken, error) { func (b *nestedBuilder) Token() (*NestedJSONWebToken, error) {
enc, err := b.signAndEncrypt() enc, err := b.signAndEncrypt()
if err != nil { if err != nil {
@ -287,12 +267,13 @@ func (b *nestedBuilder) Token() (*NestedJSONWebToken, error) {
} }
return &NestedJSONWebToken{ return &NestedJSONWebToken{
enc: enc, allowedSignatureAlgorithms: nil,
Headers: []jose.Header{enc.Header}, enc: enc,
Headers: []jose.Header{enc.Header},
}, nil }, nil
} }
func (b *nestedBuilder) CompactSerialize() (string, error) { func (b *nestedBuilder) Serialize() (string, error) {
enc, err := b.signAndEncrypt() enc, err := b.signAndEncrypt()
if err != nil { if err != nil {
return "", err return "", err

View File

@ -21,7 +21,7 @@ import (
"strconv" "strconv"
"time" "time"
"github.com/go-jose/go-jose/v3/json" "github.com/go-jose/go-jose/v4/json"
) )
// Claims represents public claim values (as specified in RFC 7519). // Claims represents public claim values (as specified in RFC 7519).

198
vendor/github.com/go-jose/go-jose/v4/jwt/jwt.go generated vendored Normal file
View File

@ -0,0 +1,198 @@
/*-
* Copyright 2016 Zbigniew Mandziejewicz
* Copyright 2016 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jwt
import (
"fmt"
"strings"
jose "github.com/go-jose/go-jose/v4"
"github.com/go-jose/go-jose/v4/json"
)
// JSONWebToken represents a JSON Web Token (as specified in RFC7519).
type JSONWebToken struct {
payload func(k interface{}) ([]byte, error)
unverifiedPayload func() []byte
Headers []jose.Header
}
type NestedJSONWebToken struct {
enc *jose.JSONWebEncryption
Headers []jose.Header
// Used when parsing and decrypting an input
allowedSignatureAlgorithms []jose.SignatureAlgorithm
}
// Claims deserializes a JSONWebToken into dest using the provided key.
func (t *JSONWebToken) Claims(key interface{}, dest ...interface{}) error {
b, err := t.payload(key)
if err != nil {
return err
}
for _, d := range dest {
if err := json.Unmarshal(b, d); err != nil {
return err
}
}
return nil
}
// UnsafeClaimsWithoutVerification deserializes the claims of a
// JSONWebToken into the dests. For signed JWTs, the claims are not
// verified. This function won't work for encrypted JWTs.
func (t *JSONWebToken) UnsafeClaimsWithoutVerification(dest ...interface{}) error {
if t.unverifiedPayload == nil {
return fmt.Errorf("go-jose/go-jose: Cannot get unverified claims")
}
claims := t.unverifiedPayload()
for _, d := range dest {
if err := json.Unmarshal(claims, d); err != nil {
return err
}
}
return nil
}
func (t *NestedJSONWebToken) Decrypt(decryptionKey interface{}) (*JSONWebToken, error) {
b, err := t.enc.Decrypt(decryptionKey)
if err != nil {
return nil, err
}
sig, err := ParseSigned(string(b), t.allowedSignatureAlgorithms)
if err != nil {
return nil, err
}
return sig, nil
}
// ParseSigned parses token from JWS form.
func ParseSigned(s string, signatureAlgorithms []jose.SignatureAlgorithm) (*JSONWebToken, error) {
sig, err := jose.ParseSignedCompact(s, signatureAlgorithms)
if err != nil {
return nil, err
}
headers := make([]jose.Header, len(sig.Signatures))
for i, signature := range sig.Signatures {
headers[i] = signature.Header
}
return &JSONWebToken{
payload: sig.Verify,
unverifiedPayload: sig.UnsafePayloadWithoutVerification,
Headers: headers,
}, nil
}
func validateKeyEncryptionAlgorithm(algs []jose.KeyAlgorithm) error {
for _, alg := range algs {
switch alg {
case jose.ED25519,
jose.RSA1_5,
jose.RSA_OAEP,
jose.RSA_OAEP_256,
jose.ECDH_ES,
jose.ECDH_ES_A128KW,
jose.ECDH_ES_A192KW,
jose.ECDH_ES_A256KW:
return fmt.Errorf("asymmetric encryption algorithms not supported for JWT: "+
"invalid key encryption algorithm: %s", alg)
case jose.PBES2_HS256_A128KW,
jose.PBES2_HS384_A192KW,
jose.PBES2_HS512_A256KW:
return fmt.Errorf("password-based encryption not supported for JWT: "+
"invalid key encryption algorithm: %s", alg)
}
}
return nil
}
func parseEncryptedCompact(
s string,
keyAlgorithms []jose.KeyAlgorithm,
contentEncryption []jose.ContentEncryption,
) (*jose.JSONWebEncryption, error) {
err := validateKeyEncryptionAlgorithm(keyAlgorithms)
if err != nil {
return nil, err
}
enc, err := jose.ParseEncryptedCompact(s, keyAlgorithms, contentEncryption)
if err != nil {
return nil, err
}
return enc, nil
}
// ParseEncrypted parses token from JWE form.
//
// The keyAlgorithms and contentEncryption parameters are used to validate the "alg" and "enc"
// header parameters respectively. They must be nonempty, and each "alg" or "enc" header in
// parsed data must contain a value that is present in the corresponding parameter. That
// includes the protected and unprotected headers as well as all recipients. To accept
// multiple algorithms, pass a slice of all the algorithms you want to accept.
func ParseEncrypted(s string,
keyAlgorithms []jose.KeyAlgorithm,
contentEncryption []jose.ContentEncryption,
) (*JSONWebToken, error) {
enc, err := parseEncryptedCompact(s, keyAlgorithms, contentEncryption)
if err != nil {
return nil, err
}
return &JSONWebToken{
payload: enc.Decrypt,
Headers: []jose.Header{enc.Header},
}, nil
}
// ParseSignedAndEncrypted parses signed-then-encrypted token from JWE form.
//
// The encryptionKeyAlgorithms and contentEncryption parameters are used to validate the "alg" and "enc"
// header parameters, respectively, of the outer JWE. They must be nonempty, and each "alg" or "enc"
// header in parsed data must contain a value that is present in the corresponding parameter. That
// includes the protected and unprotected headers as well as all recipients. To accept
// multiple algorithms, pass a slice of all the algorithms you want to accept.
//
// The signatureAlgorithms parameter is used to validate the "alg" header parameter of the
// inner JWS. It must be nonempty, and the "alg" header in the inner JWS must contain a value
// that is present in the parameter.
func ParseSignedAndEncrypted(s string,
encryptionKeyAlgorithms []jose.KeyAlgorithm,
contentEncryption []jose.ContentEncryption,
signatureAlgorithms []jose.SignatureAlgorithm,
) (*NestedJSONWebToken, error) {
enc, err := parseEncryptedCompact(s, encryptionKeyAlgorithms, contentEncryption)
if err != nil {
return nil, err
}
contentType, _ := enc.Header.ExtraHeaders[jose.HeaderContentType].(string)
if strings.ToUpper(contentType) != "JWT" {
return nil, ErrInvalidContentType
}
return &NestedJSONWebToken{
allowedSignatureAlgorithms: signatureAlgorithms,
enc: enc,
Headers: []jose.Header{enc.Header},
}, nil
}

View File

@ -33,8 +33,9 @@ type Expected struct {
Issuer string Issuer string
// Subject matches the "sub" claim exactly. // Subject matches the "sub" claim exactly.
Subject string Subject string
// Audience matches the values in "aud" claim, regardless of their order. // AnyAudience matches if there is a non-empty intersection between
Audience Audience // its values and the values in the "aud" claim.
AnyAudience Audience
// ID matches the "jti" claim exactly. // ID matches the "jti" claim exactly.
ID string ID string
// Time matches the "exp", "nbf" and "iat" claims with leeway. // Time matches the "exp", "nbf" and "iat" claims with leeway.
@ -88,12 +89,18 @@ func (c Claims) ValidateWithLeeway(e Expected, leeway time.Duration) error {
return ErrInvalidID return ErrInvalidID
} }
if len(e.Audience) != 0 { if len(e.AnyAudience) != 0 {
for _, v := range e.Audience { var intersection bool
if !c.Audience.Contains(v) { for _, v := range e.AnyAudience {
return ErrInvalidAudience if c.Audience.Contains(v) {
intersection = true
break
} }
} }
if !intersection {
return ErrInvalidAudience
}
} }
// validate using the e.Time, or time.Now if not provided // validate using the e.Time, or time.Now if not provided

View File

@ -83,6 +83,9 @@ func (o *opaqueVerifier) verifyPayload(payload []byte, signature []byte, alg Sig
} }
// OpaqueKeyEncrypter is an interface that supports encrypting keys with an opaque key. // OpaqueKeyEncrypter is an interface that supports encrypting keys with an opaque key.
//
// Note: this cannot currently be implemented outside this package because of its
// unexported method.
type OpaqueKeyEncrypter interface { type OpaqueKeyEncrypter interface {
// KeyID returns the kid // KeyID returns the kid
KeyID() string KeyID() string

View File

@ -23,7 +23,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/go-jose/go-jose/v3/json" "github.com/go-jose/go-jose/v4/json"
) )
// KeyAlgorithm represents a key management algorithm. // KeyAlgorithm represents a key management algorithm.
@ -71,6 +71,12 @@ var (
// ErrUnprotectedNonce indicates that while parsing a JWS or JWE object, a // ErrUnprotectedNonce indicates that while parsing a JWS or JWE object, a
// nonce header parameter was included in an unprotected header object. // nonce header parameter was included in an unprotected header object.
ErrUnprotectedNonce = errors.New("go-jose/go-jose: Nonce parameter included in unprotected header") ErrUnprotectedNonce = errors.New("go-jose/go-jose: Nonce parameter included in unprotected header")
// ErrMissingX5cHeader indicates that the JWT header is missing x5c headers.
ErrMissingX5cHeader = errors.New("go-jose/go-jose: no x5c header present in message")
// ErrUnsupportedEllipticCurve indicates unsupported or unknown elliptic curve has been found.
ErrUnsupportedEllipticCurve = errors.New("go-jose/go-jose: unsupported/unknown elliptic curve")
) )
// Key management algorithms // Key management algorithms
@ -199,7 +205,7 @@ type Header struct {
// not be validated with the given verify options. // not be validated with the given verify options.
func (h Header) Certificates(opts x509.VerifyOptions) ([][]*x509.Certificate, error) { func (h Header) Certificates(opts x509.VerifyOptions) ([][]*x509.Certificate, error) {
if len(h.certificates) == 0 { if len(h.certificates) == 0 {
return nil, errors.New("go-jose/go-jose: no x5c header present in message") return nil, ErrMissingX5cHeader
} }
leaf := h.certificates[0] leaf := h.certificates[0]
@ -501,7 +507,7 @@ func curveName(crv elliptic.Curve) (string, error) {
case elliptic.P521(): case elliptic.P521():
return "P-521", nil return "P-521", nil
default: default:
return "", fmt.Errorf("go-jose/go-jose: unsupported/unknown elliptic curve") return "", ErrUnsupportedEllipticCurve
} }
} }

View File

@ -25,7 +25,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/go-jose/go-jose/v3/json" "github.com/go-jose/go-jose/v4/json"
) )
// NonceSource represents a source of random nonces to go into JWS objects // NonceSource represents a source of random nonces to go into JWS objects
@ -49,6 +49,11 @@ type Signer interface {
// - JSONWebKey // - JSONWebKey
// - []byte (an HMAC key) // - []byte (an HMAC key)
// - Any type that satisfies the OpaqueSigner interface // - Any type that satisfies the OpaqueSigner interface
//
// If the key is an HMAC key, it must have at least as many bytes as the relevant hash output:
// - HS256: 32 bytes
// - HS384: 48 bytes
// - HS512: 64 bytes
type SigningKey struct { type SigningKey struct {
Algorithm SignatureAlgorithm Algorithm SignatureAlgorithm
Key interface{} Key interface{}
@ -353,8 +358,15 @@ func (ctx *genericSigner) Options() SignerOptions {
// - *rsa.PublicKey // - *rsa.PublicKey
// - *JSONWebKey // - *JSONWebKey
// - JSONWebKey // - JSONWebKey
// - *JSONWebKeySet
// - JSONWebKeySet
// - []byte (an HMAC key) // - []byte (an HMAC key)
// - Any type that implements the OpaqueVerifier interface. // - Any type that implements the OpaqueVerifier interface.
//
// If the key is an HMAC key, it must have at least as many bytes as the relevant hash output:
// - HS256: 32 bytes
// - HS384: 48 bytes
// - HS512: 64 bytes
func (obj JSONWebSignature) Verify(verificationKey interface{}) ([]byte, error) { func (obj JSONWebSignature) Verify(verificationKey interface{}) ([]byte, error) {
err := obj.DetachedVerify(obj.payload, verificationKey) err := obj.DetachedVerify(obj.payload, verificationKey)
if err != nil { if err != nil {
@ -378,7 +390,10 @@ func (obj JSONWebSignature) UnsafePayloadWithoutVerification() []byte {
// The verificationKey argument must have one of the types allowed for the // The verificationKey argument must have one of the types allowed for the
// verificationKey argument of JSONWebSignature.Verify(). // verificationKey argument of JSONWebSignature.Verify().
func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey interface{}) error { func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey interface{}) error {
key := tryJWKS(verificationKey, obj.headers()...) key, err := tryJWKS(verificationKey, obj.headers()...)
if err != nil {
return err
}
verifier, err := newVerifier(key) verifier, err := newVerifier(key)
if err != nil { if err != nil {
return err return err
@ -443,7 +458,10 @@ func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signa
// The verificationKey argument must have one of the types allowed for the // The verificationKey argument must have one of the types allowed for the
// verificationKey argument of JSONWebSignature.Verify(). // verificationKey argument of JSONWebSignature.Verify().
func (obj JSONWebSignature) DetachedVerifyMulti(payload []byte, verificationKey interface{}) (int, Signature, error) { func (obj JSONWebSignature) DetachedVerifyMulti(payload []byte, verificationKey interface{}) (int, Signature, error) {
key := tryJWKS(verificationKey, obj.headers()...) key, err := tryJWKS(verificationKey, obj.headers()...)
if err != nil {
return -1, Signature{}, err
}
verifier, err := newVerifier(key) verifier, err := newVerifier(key)
if err != nil { if err != nil {
return -1, Signature{}, err return -1, Signature{}, err

View File

@ -32,7 +32,7 @@ import (
"golang.org/x/crypto/pbkdf2" "golang.org/x/crypto/pbkdf2"
josecipher "github.com/go-jose/go-jose/v3/cipher" josecipher "github.com/go-jose/go-jose/v4/cipher"
) )
// RandReader is a cryptographically secure random number generator (stubbed out in tests). // RandReader is a cryptographically secure random number generator (stubbed out in tests).
@ -454,7 +454,7 @@ func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipien
func (ctx symmetricMac) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) { func (ctx symmetricMac) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
mac, err := ctx.hmac(payload, alg) mac, err := ctx.hmac(payload, alg)
if err != nil { if err != nil {
return Signature{}, errors.New("go-jose/go-jose: failed to compute hmac") return Signature{}, err
} }
return Signature{ return Signature{
@ -486,12 +486,24 @@ func (ctx symmetricMac) verifyPayload(payload []byte, mac []byte, alg SignatureA
func (ctx symmetricMac) hmac(payload []byte, alg SignatureAlgorithm) ([]byte, error) { func (ctx symmetricMac) hmac(payload []byte, alg SignatureAlgorithm) ([]byte, error) {
var hash func() hash.Hash var hash func() hash.Hash
// https://datatracker.ietf.org/doc/html/rfc7518#section-3.2
// A key of the same size as the hash output (for instance, 256 bits for
// "HS256") or larger MUST be used
switch alg { switch alg {
case HS256: case HS256:
if len(ctx.key)*8 < 256 {
return nil, ErrInvalidKeySize
}
hash = sha256.New hash = sha256.New
case HS384: case HS384:
if len(ctx.key)*8 < 384 {
return nil, ErrInvalidKeySize
}
hash = sha512.New384 hash = sha512.New384
case HS512: case HS512:
if len(ctx.key)*8 < 512 {
return nil, ErrInvalidKeySize
}
hash = sha512.New hash = sha512.New
default: default:
return nil, ErrUnsupportedAlgorithm return nil, ErrUnsupportedAlgorithm

12
vendor/modules.txt vendored
View File

@ -123,12 +123,12 @@ github.com/felixge/httpsnoop
# github.com/fvbommel/sortorder v1.1.0 # github.com/fvbommel/sortorder v1.1.0
## explicit; go 1.13 ## explicit; go 1.13
github.com/fvbommel/sortorder github.com/fvbommel/sortorder
# github.com/go-jose/go-jose/v3 v3.0.3 # github.com/go-jose/go-jose/v4 v4.0.4
## explicit; go 1.12 ## explicit; go 1.21
github.com/go-jose/go-jose/v3 github.com/go-jose/go-jose/v4
github.com/go-jose/go-jose/v3/cipher github.com/go-jose/go-jose/v4/cipher
github.com/go-jose/go-jose/v3/json github.com/go-jose/go-jose/v4/json
github.com/go-jose/go-jose/v3/jwt github.com/go-jose/go-jose/v4/jwt
# github.com/go-logr/logr v1.4.2 # github.com/go-logr/logr v1.4.2
## explicit; go 1.18 ## explicit; go 1.18
github.com/go-logr/logr github.com/go-logr/logr