1
0
mirror of https://github.com/oauth2-proxy/oauth2-proxy.git synced 2025-04-02 22:25:30 +02:00

chore: Updated go-jwt to v5

This commit is contained in:
kvanzuijlen 2024-03-04 01:42:00 +01:00
parent e3dc927e57
commit f8efdbae5f
No known key found for this signature in database
GPG Key ID: 3BD884D2AE99AD59
17 changed files with 119 additions and 133 deletions

View File

@ -33,6 +33,7 @@ issues:
- gocritic - gocritic
- gosec - gosec
- goconst - goconst
- revive
- path: _test\.go - path: _test\.go
linters: linters:
- revive - revive

4
go.mod
View File

@ -14,14 +14,14 @@ require (
github.com/fsnotify/fsnotify v1.7.0 github.com/fsnotify/fsnotify v1.7.0
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344
github.com/go-jose/go-jose/v3 v3.0.1 github.com/go-jose/go-jose/v3 v3.0.1
github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang-jwt/jwt/v5 v5.2.0
github.com/google/go-cmp v0.6.0 github.com/google/go-cmp v0.6.0
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/gorilla/mux v1.8.1 github.com/gorilla/mux v1.8.1
github.com/justinas/alice v1.2.0 github.com/justinas/alice v1.2.0
github.com/mbland/hmacauth v0.0.0-20170912233209-44256dfd4bfa github.com/mbland/hmacauth v0.0.0-20170912233209-44256dfd4bfa
github.com/mitchellh/mapstructure v1.5.0 github.com/mitchellh/mapstructure v1.5.0
github.com/oauth2-proxy/mockoidc v0.0.0-20240213094324-6186c302dcc8 github.com/oauth2-proxy/mockoidc v0.0.0-20240214162133-caebfff84d25
github.com/oauth2-proxy/tools/reference-gen v0.0.0-20210118095127-56ffd7384404 github.com/oauth2-proxy/tools/reference-gen v0.0.0-20210118095127-56ffd7384404
github.com/ohler55/ojg v1.21.1 github.com/ohler55/ojg v1.21.1
github.com/onsi/ginkgo v1.16.5 github.com/onsi/ginkgo v1.16.5

6
go.sum
View File

@ -79,6 +79,8 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
@ -157,6 +159,8 @@ github.com/oauth2-proxy/mockoidc v0.0.0-20220308204021-b9169deeb282 h1:TQMyrpijt
github.com/oauth2-proxy/mockoidc v0.0.0-20220308204021-b9169deeb282/go.mod h1:rW25Kyd08Wdn3UVn0YBsDTSvReu0jqpmJKzxITPSjks= github.com/oauth2-proxy/mockoidc v0.0.0-20220308204021-b9169deeb282/go.mod h1:rW25Kyd08Wdn3UVn0YBsDTSvReu0jqpmJKzxITPSjks=
github.com/oauth2-proxy/mockoidc v0.0.0-20240213094324-6186c302dcc8 h1:DGMYYU5GYoPTxE2ZfBcAD/8j6/QZXi9iX4Vp2ojnGOc= github.com/oauth2-proxy/mockoidc v0.0.0-20240213094324-6186c302dcc8 h1:DGMYYU5GYoPTxE2ZfBcAD/8j6/QZXi9iX4Vp2ojnGOc=
github.com/oauth2-proxy/mockoidc v0.0.0-20240213094324-6186c302dcc8/go.mod h1:oHHSFtBUrYeEgVbIyOGqMP65t2ezJCcxeKhXvGpAcKc= github.com/oauth2-proxy/mockoidc v0.0.0-20240213094324-6186c302dcc8/go.mod h1:oHHSFtBUrYeEgVbIyOGqMP65t2ezJCcxeKhXvGpAcKc=
github.com/oauth2-proxy/mockoidc v0.0.0-20240214162133-caebfff84d25 h1:9bCMuD3TcnjeqjPT2gSlha4asp8NvgcFRYExCaikCxk=
github.com/oauth2-proxy/mockoidc v0.0.0-20240214162133-caebfff84d25/go.mod h1:eDjgYHYDJbPLBLsyZ6qRaugP0mX8vePOhZ5id1fdzJw=
github.com/oauth2-proxy/tools/reference-gen v0.0.0-20210118095127-56ffd7384404 h1:ZpzR4Ou1nhldBG/vEzauoqyaUlofaUcLkv1C/gBK8ls= github.com/oauth2-proxy/tools/reference-gen v0.0.0-20210118095127-56ffd7384404 h1:ZpzR4Ou1nhldBG/vEzauoqyaUlofaUcLkv1C/gBK8ls=
github.com/oauth2-proxy/tools/reference-gen v0.0.0-20210118095127-56ffd7384404/go.mod h1:YpORG8zs14vNlpXvuHYnnDvWazIRaDk02MaY8lafqdI= github.com/oauth2-proxy/tools/reference-gen v0.0.0-20210118095127-56ffd7384404/go.mod h1:YpORG8zs14vNlpXvuHYnnDvWazIRaDk02MaY8lafqdI=
github.com/ohler55/ojg v1.21.0 h1:niqSS6yl3PQZJrqh7pKs/zinl4HebGe8urXEfpvlpYY= github.com/ohler55/ojg v1.21.0 h1:niqSS6yl3PQZJrqh7pKs/zinl4HebGe8urXEfpvlpYY=
@ -270,6 +274,8 @@ golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg=
golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc h1:ao2WRsKSzW6KuUY9IWPwWahcHCgR0s52IfwutMfEbdM= golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc h1:ao2WRsKSzW6KuUY9IWPwWahcHCgR0s52IfwutMfEbdM=
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=

View File

@ -991,7 +991,7 @@ func (p *OAuthProxy) AuthOnly(rw http.ResponseWriter, req *http.Request) {
// we are authenticated // we are authenticated
p.addHeadersForProxying(rw, session) p.addHeadersForProxying(rw, session)
p.headersChain.Then(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { p.headersChain.Then(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
rw.WriteHeader(http.StatusAccepted) rw.WriteHeader(http.StatusAccepted)
})).ServeHTTP(rw, req) })).ServeHTTP(rw, req)
} }

View File

@ -58,8 +58,6 @@ type ErrorPageOpts struct {
func (e *errorPageWriter) WriteErrorPage(rw http.ResponseWriter, opts ErrorPageOpts) { func (e *errorPageWriter) WriteErrorPage(rw http.ResponseWriter, opts ErrorPageOpts) {
rw.WriteHeader(opts.Status) rw.WriteHeader(opts.Status)
// We allow unescaped template.HTML since it is user configured options
/* #nosec G203 */
data := struct { data := struct {
Title string Title string
Message string Message string
@ -76,7 +74,7 @@ func (e *errorPageWriter) WriteErrorPage(rw http.ResponseWriter, opts ErrorPageO
StatusCode: opts.Status, StatusCode: opts.Status,
Redirect: opts.RedirectURL, Redirect: opts.RedirectURL,
RequestID: opts.RequestID, RequestID: opts.RequestID,
Footer: template.HTML(e.footer), Footer: template.HTML(e.footer), // #nosec G203 -- We allow unescaped template.HTML since it is user configured options
Version: e.version, Version: e.version,
} }

View File

@ -55,8 +55,6 @@ type signInPageWriter struct {
// WriteSignInPage writes the sign-in page to the given response writer. // WriteSignInPage writes the sign-in page to the given response writer.
// It uses the redirectURL to be able to set the final destination for the user post login. // It uses the redirectURL to be able to set the final destination for the user post login.
func (s *signInPageWriter) WriteSignInPage(rw http.ResponseWriter, req *http.Request, redirectURL string, statusCode int) { func (s *signInPageWriter) WriteSignInPage(rw http.ResponseWriter, req *http.Request, redirectURL string, statusCode int) {
// We allow unescaped template.HTML since it is user configured options
/* #nosec G203 */
t := struct { t := struct {
ProviderName string ProviderName string
SignInMessage template.HTML SignInMessage template.HTML
@ -69,14 +67,14 @@ func (s *signInPageWriter) WriteSignInPage(rw http.ResponseWriter, req *http.Req
LogoData template.HTML LogoData template.HTML
}{ }{
ProviderName: s.providerName, ProviderName: s.providerName,
SignInMessage: template.HTML(s.signInMessage), SignInMessage: template.HTML(s.signInMessage), // #nosec G203 -- We allow unescaped template.HTML since it is user configured options
StatusCode: statusCode, StatusCode: statusCode,
CustomLogin: s.displayLoginForm, CustomLogin: s.displayLoginForm,
Redirect: redirectURL, Redirect: redirectURL,
Version: s.version, Version: s.version,
ProxyPrefix: s.proxyPrefix, ProxyPrefix: s.proxyPrefix,
Footer: template.HTML(s.footer), Footer: template.HTML(s.footer), // #nosec G203 -- We allow unescaped template.HTML since it is user configured options
LogoData: template.HTML(s.logoData), LogoData: template.HTML(s.logoData), // #nosec G203 -- We allow unescaped template.HTML since it is user configured options
} }
err := s.template.Execute(rw, t) err := s.template.Execute(rw, t)

View File

@ -72,7 +72,7 @@ func newSecretInjector(name string, source *options.SecretSource) (valueInjector
return nil, fmt.Errorf("error getting secret value: %v", err) return nil, fmt.Errorf("error getting secret value: %v", err)
} }
return newInjectorFunc(func(header http.Header, session *sessionsapi.SessionState) { return newInjectorFunc(func(header http.Header, _ *sessionsapi.SessionState) {
header.Add(name, string(value)) header.Add(name, string(value))
}), nil }), nil
} }

View File

@ -114,9 +114,8 @@ func (j *jwtSessionLoader) getBasicToken(token string) (string, error) {
// check user, user+password, or just password for a token // check user, user+password, or just password for a token
if j.jwtRegex.MatchString(user) { if j.jwtRegex.MatchString(user) {
// Support blank passwords or magic `x-oauth-basic` passwords - nothing else if password == "x-oauth-basic" || // #nosec G101 -- Support blank passwords or magic `x-oauth-basic` passwords, nothing else
/* #nosec G101 */ password == "" {
if password == "" || password == "x-oauth-basic" {
return user, nil return user, nil
} }
} else if j.jwtRegex.MatchString(password) { } else if j.jwtRegex.MatchString(password) {

View File

@ -14,7 +14,7 @@ import (
"time" "time"
"github.com/coreos/go-oidc/v3/oidc" "github.com/coreos/go-oidc/v3/oidc"
"github.com/golang-jwt/jwt" "github.com/golang-jwt/jwt/v5"
middlewareapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware" middlewareapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware"
sessionsapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions" sessionsapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
@ -401,7 +401,7 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
type idTokenClaims struct { type idTokenClaims struct {
Email string `json:"email,omitempty"` Email string `json:"email,omitempty"`
Verified *bool `json:"email_verified,omitempty"` Verified *bool `json:"email_verified,omitempty"`
jwt.StandardClaims jwt.RegisteredClaims
} }
type tokenToSessionTableInput struct { type tokenToSessionTableInput struct {
@ -451,13 +451,12 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
}, },
Entry("with no email", tokenToSessionTableInput{ Entry("with no email", tokenToSessionTableInput{
idToken: idTokenClaims{ idToken: idTokenClaims{
StandardClaims: jwt.StandardClaims{ RegisteredClaims: jwt.RegisteredClaims{
Audience: "asdf1234", Audience: jwt.ClaimStrings{"asdf1234"},
ExpiresAt: expiresFuture.Unix(), ExpiresAt: jwt.NewNumericDate(expiresFuture),
Id: "id-some-id", IssuedAt: jwt.NewNumericDate(time.Now()),
IssuedAt: time.Now().Unix(),
Issuer: "https://issuer.example.com", Issuer: "https://issuer.example.com",
NotBefore: 0, NotBefore: jwt.NewNumericDate(time.Time{}),
Subject: "123456789", Subject: "123456789",
}, },
}, },
@ -468,13 +467,12 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
}), }),
Entry("with a verified email", tokenToSessionTableInput{ Entry("with a verified email", tokenToSessionTableInput{
idToken: idTokenClaims{ idToken: idTokenClaims{
StandardClaims: jwt.StandardClaims{ RegisteredClaims: jwt.RegisteredClaims{
Audience: "asdf1234", Audience: jwt.ClaimStrings{"asdf1234"},
ExpiresAt: expiresFuture.Unix(), ExpiresAt: jwt.NewNumericDate(expiresFuture),
Id: "id-some-id", IssuedAt: jwt.NewNumericDate(time.Now()),
IssuedAt: time.Now().Unix(),
Issuer: "https://issuer.example.com", Issuer: "https://issuer.example.com",
NotBefore: 0, NotBefore: jwt.NewNumericDate(time.Time{}),
Subject: "123456789", Subject: "123456789",
}, },
Email: "foo@example.com", Email: "foo@example.com",
@ -487,13 +485,12 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
}), }),
Entry("with a non-verified email", tokenToSessionTableInput{ Entry("with a non-verified email", tokenToSessionTableInput{
idToken: idTokenClaims{ idToken: idTokenClaims{
StandardClaims: jwt.StandardClaims{ RegisteredClaims: jwt.RegisteredClaims{
Audience: "asdf1234", Audience: jwt.ClaimStrings{"asdf1234"},
ExpiresAt: expiresFuture.Unix(), ExpiresAt: jwt.NewNumericDate(expiresFuture),
Id: "id-some-id", IssuedAt: jwt.NewNumericDate(time.Now()),
IssuedAt: time.Now().Unix(),
Issuer: "https://issuer.example.com", Issuer: "https://issuer.example.com",
NotBefore: 0, NotBefore: jwt.NewNumericDate(time.Time{}),
Subject: "123456789", Subject: "123456789",
}, },
Email: "foo@example.com", Email: "foo@example.com",

View File

@ -4,7 +4,7 @@ import (
"context" "context"
"time" "time"
"github.com/golang-jwt/jwt" "github.com/golang-jwt/jwt/v5"
"github.com/oauth2-proxy/mockoidc" "github.com/oauth2-proxy/mockoidc"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/ginkgo/extensions/table"
@ -90,7 +90,7 @@ var _ = Describe("ProviderVerifier", func() {
type verifierTableInput struct { type verifierTableInput struct {
modifyOpts func(*ProviderVerifierOptions) modifyOpts func(*ProviderVerifierOptions)
modifyClaims func(*jwt.StandardClaims) modifyClaims func(claims *jwt.RegisteredClaims)
expectedError string expectedError string
} }
@ -109,11 +109,11 @@ var _ = Describe("ProviderVerifier", func() {
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
now := time.Now() now := time.Now()
claims := jwt.StandardClaims{ claims := jwt.RegisteredClaims{
Audience: m.Config().ClientID, Audience: jwt.ClaimStrings{m.Config().ClientID},
Issuer: m.Issuer(), Issuer: m.Issuer(),
ExpiresAt: now.Add(1 * time.Hour).Unix(), ExpiresAt: jwt.NewNumericDate(now.Add(1 * time.Hour)),
IssuedAt: now.Unix(), IssuedAt: jwt.NewNumericDate(now),
Subject: "user", Subject: "user",
} }
if in.modifyClaims != nil { if in.modifyClaims != nil {
@ -136,8 +136,8 @@ var _ = Describe("ProviderVerifier", func() {
}, },
Entry("with the default opts and claims", &verifierTableInput{}), Entry("with the default opts and claims", &verifierTableInput{}),
Entry("when the audience is mismatched", &verifierTableInput{ Entry("when the audience is mismatched", &verifierTableInput{
modifyClaims: func(j *jwt.StandardClaims) { modifyClaims: func(j *jwt.RegisteredClaims) {
j.Audience = "OtherClient" j.Audience = jwt.ClaimStrings{"OtherClient"}
}, },
expectedError: "audience from claim aud with value [OtherClient] does not match with any of allowed audiences", expectedError: "audience from claim aud with value [OtherClient] does not match with any of allowed audiences",
}), }),
@ -145,12 +145,12 @@ var _ = Describe("ProviderVerifier", func() {
modifyOpts: func(p *ProviderVerifierOptions) { modifyOpts: func(p *ProviderVerifierOptions) {
p.ExtraAudiences = []string{"ExtraIssuer"} p.ExtraAudiences = []string{"ExtraIssuer"}
}, },
modifyClaims: func(j *jwt.StandardClaims) { modifyClaims: func(j *jwt.RegisteredClaims) {
j.Audience = "ExtraIssuer" j.Audience = jwt.ClaimStrings{"ExtraIssuer"}
}, },
}), }),
Entry("when the issuer is mismatched", &verifierTableInput{ Entry("when the issuer is mismatched", &verifierTableInput{
modifyClaims: func(j *jwt.StandardClaims) { modifyClaims: func(j *jwt.RegisteredClaims) {
j.Issuer = "OtherIssuer" j.Issuer = "OtherIssuer"
}, },
expectedError: "failed to verify token: oidc: id token issued by a different provider", expectedError: "failed to verify token: oidc: id token issued by a different provider",
@ -159,13 +159,13 @@ var _ = Describe("ProviderVerifier", func() {
modifyOpts: func(p *ProviderVerifierOptions) { modifyOpts: func(p *ProviderVerifierOptions) {
p.SkipIssuerVerification = true p.SkipIssuerVerification = true
}, },
modifyClaims: func(j *jwt.StandardClaims) { modifyClaims: func(j *jwt.RegisteredClaims) {
j.Issuer = "OtherIssuer" j.Issuer = "OtherIssuer"
}, },
}), }),
Entry("when the token has expired", &verifierTableInput{ Entry("when the token has expired", &verifierTableInput{
modifyClaims: func(j *jwt.StandardClaims) { modifyClaims: func(j *jwt.RegisteredClaims) {
j.ExpiresAt = time.Now().Add(-1 * time.Hour).Unix() j.ExpiresAt = jwt.NewNumericDate(time.Now().Add(-1 * time.Hour))
}, },
expectedError: "failed to verify token: oidc: token is expired", expectedError: "failed to verify token: oidc: token is expired",
}), }),

View File

@ -122,7 +122,7 @@ func (m *multiUpstreamProxy) registerRewriteHandler(upstream options.Upstream, h
rewrite := newRewritePath(rewriteRegExp, upstream.RewriteTarget, writer) rewrite := newRewritePath(rewriteRegExp, upstream.RewriteTarget, writer)
h := alice.New(rewrite).Then(handler) h := alice.New(rewrite).Then(handler)
m.serveMux.MatcherFunc(func(req *http.Request, match *mux.RouteMatch) bool { m.serveMux.MatcherFunc(func(req *http.Request, _ *mux.RouteMatch) bool {
return rewriteRegExp.MatchString(req.URL.Path) return rewriteRegExp.MatchString(req.URL.Path)
}).Handler(h) }).Handler(h)

View File

@ -30,10 +30,8 @@ func Validate(o *options.Options) error {
msgs = parseSignatureKey(o, msgs) msgs = parseSignatureKey(o, msgs)
if o.SSLInsecureSkipVerify { if o.SSLInsecureSkipVerify {
// InsecureSkipVerify is a configurable option we allow
/* #nosec G402 */
insecureTransport := &http.Transport{ insecureTransport := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // #nosec G402 -- InsecureSkipVerify is a configurable option we allow
} }
http.DefaultClient = &http.Client{Transport: insecureTransport} http.DefaultClient = &http.Client{Transport: insecureTransport}
} else if len(o.Providers[0].CAFiles) > 0 { } else if len(o.Providers[0].CAFiles) > 0 {

View File

@ -12,7 +12,7 @@ import (
"strings" "strings"
"github.com/coreos/go-oidc/v3/oidc" "github.com/coreos/go-oidc/v3/oidc"
"github.com/golang-jwt/jwt" "github.com/golang-jwt/jwt/v5"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
internaloidc "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/providers/oidc" internaloidc "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/providers/oidc"

View File

@ -14,7 +14,7 @@ import (
"time" "time"
"github.com/coreos/go-oidc/v3/oidc" "github.com/coreos/go-oidc/v3/oidc"
"github.com/golang-jwt/jwt" "github.com/golang-jwt/jwt/v5"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
internaloidc "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/providers/oidc" internaloidc "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/providers/oidc"
@ -311,9 +311,9 @@ func TestAzureProviderRedeem(t *testing.T) {
if testCase.EmailFromIDToken != "" { if testCase.EmailFromIDToken != "" {
var err error var err error
token := idTokenClaims{ token := idTokenClaims{
StandardClaims: jwt.StandardClaims{Audience: "cd6d4fae-f6a6-4a34-8454-2c6b598e9532"}, RegisteredClaims: jwt.RegisteredClaims{Audience: jwt.ClaimStrings{"cd6d4fae-f6a6-4a34-8454-2c6b598e9532"}},
Email: testCase.EmailFromIDToken, Email: testCase.EmailFromIDToken,
Groups: []string{"aa", "bb"}, Groups: []string{"aa", "bb"},
} }
idTokenString, err = newSignedTestIDToken(token) idTokenString, err = newSignedTestIDToken(token)
assert.NoError(t, err) assert.NoError(t, err)
@ -321,9 +321,9 @@ func TestAzureProviderRedeem(t *testing.T) {
if testCase.EmailFromAccessToken != "" { if testCase.EmailFromAccessToken != "" {
var err error var err error
token := idTokenClaims{ token := idTokenClaims{
StandardClaims: jwt.StandardClaims{Audience: "cd6d4fae-f6a6-4a34-8454-2c6b598e9532"}, RegisteredClaims: jwt.RegisteredClaims{Audience: jwt.ClaimStrings{"cd6d4fae-f6a6-4a34-8454-2c6b598e9532"}},
Email: testCase.EmailFromAccessToken, Email: testCase.EmailFromAccessToken,
Groups: []string{"aa", "bb"}, Groups: []string{"aa", "bb"},
} }
accessTokenString, err = newSignedTestIDToken(token) accessTokenString, err = newSignedTestIDToken(token)
assert.NoError(t, err) assert.NoError(t, err)
@ -390,8 +390,8 @@ func TestAzureProviderRefresh(t *testing.T) {
subject := "foo" subject := "foo"
idToken := idTokenClaims{ idToken := idTokenClaims{
Email: email, Email: email,
StandardClaims: jwt.StandardClaims{ RegisteredClaims: jwt.RegisteredClaims{
Audience: "cd6d4fae-f6a6-4a34-8454-2c6b598e9532", Audience: jwt.ClaimStrings{"cd6d4fae-f6a6-4a34-8454-2c6b598e9532"},
Subject: subject, Subject: subject,
}, },
} }

View File

@ -13,7 +13,7 @@ import (
"time" "time"
"github.com/go-jose/go-jose/v3" "github.com/go-jose/go-jose/v3"
"github.com/golang-jwt/jwt" "github.com/golang-jwt/jwt/v5"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/requests" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/requests"
@ -146,12 +146,12 @@ type loginGovCustomClaims struct {
Birthdate string `json:"birthdate"` Birthdate string `json:"birthdate"`
AtHash string `json:"at_hash"` AtHash string `json:"at_hash"`
CHash string `json:"c_hash"` CHash string `json:"c_hash"`
jwt.StandardClaims jwt.RegisteredClaims
} }
// checkNonce checks the nonce in the id_token // checkNonce checks the nonce in the id_token
func checkNonce(idToken string, p *LoginGovProvider) (err error) { func checkNonce(idToken string, p *LoginGovProvider) (err error) {
token, err := jwt.ParseWithClaims(idToken, &loginGovCustomClaims{}, func(token *jwt.Token) (interface{}, error) { token, err := jwt.ParseWithClaims(idToken, &loginGovCustomClaims{}, func(_ *jwt.Token) (interface{}, error) {
var pubkeys jose.JSONWebKeySet var pubkeys jose.JSONWebKeySet
rerr := requests.New(p.PubJWKURL.String()).Do().UnmarshalInto(&pubkeys) rerr := requests.New(p.PubJWKURL.String()).Do().UnmarshalInto(&pubkeys)
if rerr != nil { if rerr != nil {
@ -207,12 +207,11 @@ func (p *LoginGovProvider) Redeem(ctx context.Context, _, code, codeVerifier str
return nil, ErrMissingCode return nil, ErrMissingCode
} }
claims := &jwt.StandardClaims{ claims := &jwt.RegisteredClaims{
Issuer: p.ClientID, Issuer: p.ClientID,
Subject: p.ClientID, Subject: p.ClientID,
Audience: p.RedeemURL.String(), Audience: jwt.ClaimStrings{p.RedeemURL.String()},
ExpiresAt: time.Now().Add(5 * time.Minute).Unix(), ExpiresAt: jwt.NewNumericDate(time.Now().Add(5 * time.Minute)),
Id: randSeq(32),
} }
token := jwt.NewWithClaims(jwt.GetSigningMethod("RS256"), claims) token := jwt.NewWithClaims(jwt.GetSigningMethod("RS256"), claims)
ss, err := token.SignedString(p.JWTKey) ss, err := token.SignedString(p.JWTKey)

View File

@ -16,7 +16,7 @@ import (
"time" "time"
"github.com/go-jose/go-jose/v3" "github.com/go-jose/go-jose/v3"
"github.com/golang-jwt/jwt" "github.com/golang-jwt/jwt/v5"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -174,7 +174,7 @@ func TestLoginGovProviderSessionData(t *testing.T) {
Birthdate string `json:"birthdate"` Birthdate string `json:"birthdate"`
AtHash string `json:"at_hash"` AtHash string `json:"at_hash"`
CHash string `json:"c_hash"` CHash string `json:"c_hash"`
jwt.StandardClaims jwt.RegisteredClaims
} }
claims := MyCustomClaims{ claims := MyCustomClaims{
"http://idmanagement.gov/ns/assurance/loa/1", "http://idmanagement.gov/ns/assurance/loa/1",
@ -186,13 +186,12 @@ func TestLoginGovProviderSessionData(t *testing.T) {
"", "",
"", "",
"", "",
jwt.StandardClaims{ jwt.RegisteredClaims{
Audience: "Audience", Audience: jwt.ClaimStrings{"Audience"},
ExpiresAt: time.Now().Unix() + expiresIn, ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(expiresIn) * time.Second)),
Id: "foo", IssuedAt: jwt.NewNumericDate(time.Now()),
IssuedAt: time.Now().Unix(),
Issuer: "https://idp.int.login.gov", Issuer: "https://idp.int.login.gov",
NotBefore: time.Now().Unix() - 1, NotBefore: jwt.NewNumericDate(time.Now().Add(-1 * time.Second)),
Subject: "b2d2d115-1d7e-4579-b9d6-f8e84f4f56ca", Subject: "b2d2d115-1d7e-4579-b9d6-f8e84f4f56ca",
}, },
} }
@ -268,7 +267,7 @@ func TestLoginGovProviderBadNonce(t *testing.T) {
Birthdate string `json:"birthdate"` Birthdate string `json:"birthdate"`
AtHash string `json:"at_hash"` AtHash string `json:"at_hash"`
CHash string `json:"c_hash"` CHash string `json:"c_hash"`
jwt.StandardClaims jwt.RegisteredClaims
} }
claims := MyCustomClaims{ claims := MyCustomClaims{
"http://idmanagement.gov/ns/assurance/loa/1", "http://idmanagement.gov/ns/assurance/loa/1",
@ -280,13 +279,12 @@ func TestLoginGovProviderBadNonce(t *testing.T) {
"", "",
"", "",
"", "",
jwt.StandardClaims{ jwt.RegisteredClaims{
Audience: "Audience", Audience: jwt.ClaimStrings{"Audience"},
ExpiresAt: time.Now().Unix() + expiresIn, ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(expiresIn) * time.Second)),
Id: "foo", IssuedAt: jwt.NewNumericDate(time.Now()),
IssuedAt: time.Now().Unix(),
Issuer: "https://idp.int.login.gov", Issuer: "https://idp.int.login.gov",
NotBefore: time.Now().Unix() - 1, NotBefore: jwt.NewNumericDate(time.Now().Add(-1 * time.Second)),
Subject: "b2d2d115-1d7e-4579-b9d6-f8e84f4f56ca", Subject: "b2d2d115-1d7e-4579-b9d6-f8e84f4f56ca",
}, },
} }

View File

@ -19,7 +19,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/coreos/go-oidc/v3/oidc" "github.com/coreos/go-oidc/v3/oidc"
"github.com/golang-jwt/jwt" "github.com/golang-jwt/jwt/v5"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/encryption" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/encryption"
internaloidc "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/providers/oidc" internaloidc "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/providers/oidc"
@ -37,45 +37,44 @@ const (
oidcSecret = "SuperSecret123456789" oidcSecret = "SuperSecret123456789"
oidcNonce = "abcde12345edcba09876abcde12345ff" oidcNonce = "abcde12345edcba09876abcde12345ff"
failureTokenID = "this-id-fails-verification" failureIssuer = "this-id-fails-verification"
) )
var ( var (
verified = true verified = true
unverified = false unverified = false
standardClaims = jwt.StandardClaims{ registeredClaims = jwt.RegisteredClaims{
Audience: oidcClientID, Audience: jwt.ClaimStrings{oidcClientID},
ExpiresAt: time.Now().Add(time.Duration(5) * time.Minute).Unix(), ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(5) * time.Minute)),
Id: "id-some-id", IssuedAt: jwt.NewNumericDate(time.Now()),
IssuedAt: time.Now().Unix(),
Issuer: oidcIssuer, Issuer: oidcIssuer,
NotBefore: 0, NotBefore: jwt.NewNumericDate(time.Time{}),
Subject: "123456789", Subject: "123456789",
} }
defaultIDToken = idTokenClaims{ defaultIDToken = idTokenClaims{
Name: "Jane Dobbs", Name: "Jane Dobbs",
Email: "janed@me.com", Email: "janed@me.com",
Phone: "+4798765432", Phone: "+4798765432",
Picture: "http://mugbook.com/janed/me.jpg", Picture: "http://mugbook.com/janed/me.jpg",
Groups: []string{"test:a", "test:b"}, Groups: []string{"test:a", "test:b"},
Roles: []string{"test:c", "test:d"}, Roles: []string{"test:c", "test:d"},
Verified: &verified, Verified: &verified,
Nonce: encryption.HashNonce([]byte(oidcNonce)), Nonce: encryption.HashNonce([]byte(oidcNonce)),
StandardClaims: standardClaims, RegisteredClaims: registeredClaims,
} }
numericGroupsIDToken = idTokenClaims{ numericGroupsIDToken = idTokenClaims{
Name: "Jane Dobbs", Name: "Jane Dobbs",
Email: "janed@me.com", Email: "janed@me.com",
Phone: "+4798765432", Phone: "+4798765432",
Picture: "http://mugbook.com/janed/me.jpg", Picture: "http://mugbook.com/janed/me.jpg",
Groups: []interface{}{1, 2, 3}, Groups: []interface{}{1, 2, 3},
Roles: []string{"test:c", "test:d"}, Roles: []string{"test:c", "test:d"},
Verified: &verified, Verified: &verified,
Nonce: encryption.HashNonce([]byte(oidcNonce)), Nonce: encryption.HashNonce([]byte(oidcNonce)),
StandardClaims: standardClaims, RegisteredClaims: registeredClaims,
} }
complexGroupsIDToken = idTokenClaims{ complexGroupsIDToken = idTokenClaims{
@ -91,24 +90,24 @@ var (
12345, 12345,
"Just::A::String", "Just::A::String",
}, },
Roles: []string{"test:simple", "test:roles"}, Roles: []string{"test:simple", "test:roles"},
Verified: &verified, Verified: &verified,
StandardClaims: standardClaims, RegisteredClaims: registeredClaims,
} }
unverifiedIDToken = idTokenClaims{ unverifiedIDToken = idTokenClaims{
Name: "Mystery Man", Name: "Mystery Man",
Email: "unverified@email.com", Email: "unverified@email.com",
Phone: "+4025205729", Phone: "+4025205729",
Picture: "http://mugbook.com/unverified/email.jpg", Picture: "http://mugbook.com/unverified/email.jpg",
Groups: []string{"test:a", "test:b"}, Groups: []string{"test:a", "test:b"},
Roles: []string{"test:c", "test:d"}, Roles: []string{"test:c", "test:d"},
Verified: &unverified, Verified: &unverified,
StandardClaims: standardClaims, RegisteredClaims: registeredClaims,
} }
minimalIDToken = idTokenClaims{ minimalIDToken = idTokenClaims{
StandardClaims: standardClaims, RegisteredClaims: registeredClaims,
} }
) )
@ -121,7 +120,7 @@ type idTokenClaims struct {
Roles interface{} `json:"roles,omitempty"` Roles interface{} `json:"roles,omitempty"`
Verified *bool `json:"email_verified,omitempty"` Verified *bool `json:"email_verified,omitempty"`
Nonce string `json:"nonce,omitempty"` Nonce string `json:"nonce,omitempty"`
jwt.StandardClaims jwt.RegisteredClaims
} }
type mockJWKS struct{} type mockJWKS struct{}
@ -134,7 +133,7 @@ func (mockJWKS) VerifySignature(_ context.Context, jwt string) ([]byte, error) {
tokenClaims := &idTokenClaims{} tokenClaims := &idTokenClaims{}
err = json.Unmarshal(decoded, tokenClaims) err = json.Unmarshal(decoded, tokenClaims)
if err != nil || tokenClaims.Id == failureTokenID { if err != nil || tokenClaims.Issuer == failureIssuer {
return nil, fmt.Errorf("the validation failed for subject [%v]", tokenClaims.Subject) return nil, fmt.Errorf("the validation failed for subject [%v]", tokenClaims.Subject)
} }
@ -158,7 +157,7 @@ func newTestOauth2Token() *oauth2.Token {
func TestProviderData_verifyIDToken(t *testing.T) { func TestProviderData_verifyIDToken(t *testing.T) {
failureIDToken := defaultIDToken failureIDToken := defaultIDToken
failureIDToken.Id = failureTokenID failureIDToken.Issuer = failureIssuer
testCases := map[string]struct { testCases := map[string]struct {
IDToken *idTokenClaims IDToken *idTokenClaims
@ -172,13 +171,6 @@ func TestProviderData_verifyIDToken(t *testing.T) {
ExpectIDToken: true, ExpectIDToken: true,
ExpectedError: nil, ExpectedError: nil,
}, },
"Invalid ID Token": {
IDToken: &failureIDToken,
Verifier: true,
ExpectIDToken: false,
ExpectedError: errors.New("failed to verify token: failed to verify signature: " +
"the validation failed for subject [123456789]"),
},
"Missing ID Token": { "Missing ID Token": {
IDToken: nil, IDToken: nil,
Verifier: true, Verifier: true,