git.iko.soy/typeable/oauth2-proxy
on master help sign in
chore: Updated go-jwt to v5
commitf8efdbae5fadd312fe528213c48277387a4078c4 authorkvanzuijlen <8818390+kvanzuijlen@users.noreply.github.com> dateMon 4 Mar 2024, 01:42 (3 years ago) parente3dc927
17 files changed+119−133
.golangci.yml+1 go.mod+2−2 go.sum+6 oauthproxy.go+1−1 pkg/app/pagewriter/error_page.go+1−3 pkg/app/pagewriter/sign_in_page.go+3−5 pkg/header/injector.go+1−1 pkg/middleware/jwt_session.go+2−3 pkg/middleware/jwt_session_test.go+17−20 pkg/providers/oidc/provider_verifier_test.go+14−14 pkg/upstream/proxy.go+1−1 pkg/validation/options.go+1−3 providers/adfs_test.go+1−1 providers/azure_test.go+9−9 providers/logingov.go+6−7 providers/logingov_test.go+13−15 providers/provider_data_test.go+40−48
.golangci.yml+1
@@ -33,6 +33,7 @@ issues:
3333 - gocritic
3434 - gosec
3535 - goconst
36+ - revive
3637 - path: _test\.go
3738 linters:
3839 - revive
go.mod+2−2
@@ -14,14 +14,14 @@ require (
1414 github.com/fsnotify/fsnotify v1.7.0
1515 github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344
1616 github.com/go-jose/go-jose/v3 v3.0.1
17− github.com/golang-jwt/jwt v3.2.2+incompatible
17+ github.com/golang-jwt/jwt/v5 v5.2.0
1818 github.com/google/go-cmp v0.6.0
1919 github.com/google/uuid v1.6.0
2020 github.com/gorilla/mux v1.8.1
2121 github.com/justinas/alice v1.2.0
2222 github.com/mbland/hmacauth v0.0.0-20170912233209-44256dfd4bfa
2323 github.com/mitchellh/mapstructure v1.5.0
24− github.com/oauth2-proxy/mockoidc v0.0.0-20240213094324-6186c302dcc8
24+ github.com/oauth2-proxy/mockoidc v0.0.0-20240214162133-caebfff84d25
2525 github.com/oauth2-proxy/tools/reference-gen v0.0.0-20210118095127-56ffd7384404
2626 github.com/ohler55/ojg v1.21.1
2727 github.com/onsi/ginkgo v1.16.5
go.sum+6
@@ -79,6 +79,8 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe
7979github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
8080github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
8181github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
82+github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
83+github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
8284github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
8385github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
8486github.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
157159github.com/oauth2-proxy/mockoidc v0.0.0-20220308204021-b9169deeb282/go.mod h1:rW25Kyd08Wdn3UVn0YBsDTSvReu0jqpmJKzxITPSjks=
158160github.com/oauth2-proxy/mockoidc v0.0.0-20240213094324-6186c302dcc8 h1:DGMYYU5GYoPTxE2ZfBcAD/8j6/QZXi9iX4Vp2ojnGOc=
159161github.com/oauth2-proxy/mockoidc v0.0.0-20240213094324-6186c302dcc8/go.mod h1:oHHSFtBUrYeEgVbIyOGqMP65t2ezJCcxeKhXvGpAcKc=
162+github.com/oauth2-proxy/mockoidc v0.0.0-20240214162133-caebfff84d25 h1:9bCMuD3TcnjeqjPT2gSlha4asp8NvgcFRYExCaikCxk=
163+github.com/oauth2-proxy/mockoidc v0.0.0-20240214162133-caebfff84d25/go.mod h1:eDjgYHYDJbPLBLsyZ6qRaugP0mX8vePOhZ5id1fdzJw=
160164github.com/oauth2-proxy/tools/reference-gen v0.0.0-20210118095127-56ffd7384404 h1:ZpzR4Ou1nhldBG/vEzauoqyaUlofaUcLkv1C/gBK8ls=
161165github.com/oauth2-proxy/tools/reference-gen v0.0.0-20210118095127-56ffd7384404/go.mod h1:YpORG8zs14vNlpXvuHYnnDvWazIRaDk02MaY8lafqdI=
162166github.com/ohler55/ojg v1.21.0 h1:niqSS6yl3PQZJrqh7pKs/zinl4HebGe8urXEfpvlpYY=
@@ -270,6 +274,8 @@ golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
270274golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
271275golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
272276golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
277+golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg=
278+golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ=
273279golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
274280golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc h1:ao2WRsKSzW6KuUY9IWPwWahcHCgR0s52IfwutMfEbdM=
275281golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
oauthproxy.go+1−1
@@ -991,7 +991,7 @@ func (p *OAuthProxy) AuthOnly(rw http.ResponseWriter, req *http.Request) {
991991
992992 // we are authenticated
993993 p.addHeadersForProxying(rw, session)
994− p.headersChain.Then(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
994+ p.headersChain.Then(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
995995 rw.WriteHeader(http.StatusAccepted)
996996 })).ServeHTTP(rw, req)
997997}
pkg/app/pagewriter/error_page.go+1−3
@@ -58,8 +58,6 @@ type ErrorPageOpts struct {
5858func (e *errorPageWriter) WriteErrorPage(rw http.ResponseWriter, opts ErrorPageOpts) {
5959 rw.WriteHeader(opts.Status)
6060
61− // We allow unescaped template.HTML since it is user configured options
62− /* #nosec G203 */
6361 data := struct {
6462 Title string
6563 Message string
@@ -76,7 +74,7 @@ func (e *errorPageWriter) WriteErrorPage(rw http.ResponseWriter, opts ErrorPageO
7674 StatusCode: opts.Status,
7775 Redirect: opts.RedirectURL,
7876 RequestID: opts.RequestID,
79− Footer: template.HTML(e.footer),
77+ Footer: template.HTML(e.footer), // #nosec G203 -- We allow unescaped template.HTML since it is user configured options
8078 Version: e.version,
8179 }
8280
pkg/app/pagewriter/sign_in_page.go+3−5
@@ -55,8 +55,6 @@ type signInPageWriter struct {
5555// WriteSignInPage writes the sign-in page to the given response writer.
5656// It uses the redirectURL to be able to set the final destination for the user post login.
5757func (s *signInPageWriter) WriteSignInPage(rw http.ResponseWriter, req *http.Request, redirectURL string, statusCode int) {
58− // We allow unescaped template.HTML since it is user configured options
59− /* #nosec G203 */
6058 t := struct {
6159 ProviderName string
6260 SignInMessage template.HTML
@@ -69,14 +67,14 @@ func (s *signInPageWriter) WriteSignInPage(rw http.ResponseWriter, req *http.Req
6967 LogoData template.HTML
7068 }{
7169 ProviderName: s.providerName,
72− SignInMessage: template.HTML(s.signInMessage),
70+ SignInMessage: template.HTML(s.signInMessage), // #nosec G203 -- We allow unescaped template.HTML since it is user configured options
7371 StatusCode: statusCode,
7472 CustomLogin: s.displayLoginForm,
7573 Redirect: redirectURL,
7674 Version: s.version,
7775 ProxyPrefix: s.proxyPrefix,
78− Footer: template.HTML(s.footer),
79− LogoData: template.HTML(s.logoData),
76+ Footer: template.HTML(s.footer), // #nosec G203 -- We allow unescaped template.HTML since it is user configured options
77+ LogoData: template.HTML(s.logoData), // #nosec G203 -- We allow unescaped template.HTML since it is user configured options
8078 }
8179
8280 err := s.template.Execute(rw, t)
pkg/header/injector.go+1−1
@@ -72,7 +72,7 @@ func newSecretInjector(name string, source *options.SecretSource) (valueInjector
7272 return nil, fmt.Errorf("error getting secret value: %v", err)
7373 }
7474
75− return newInjectorFunc(func(header http.Header, session *sessionsapi.SessionState) {
75+ return newInjectorFunc(func(header http.Header, _ *sessionsapi.SessionState) {
7676 header.Add(name, string(value))
7777 }), nil
7878}
pkg/middleware/jwt_session.go+2−3
@@ -114,9 +114,8 @@ func (j *jwtSessionLoader) getBasicToken(token string) (string, error) {
114114
115115 // check user, user+password, or just password for a token
116116 if j.jwtRegex.MatchString(user) {
117− // Support blank passwords or magic `x-oauth-basic` passwords - nothing else
118− /* #nosec G101 */
119− if password == "" || password == "x-oauth-basic" {
117+ if password == "x-oauth-basic" || // #nosec G101 -- Support blank passwords or magic `x-oauth-basic` passwords, nothing else
118+ password == "" {
120119 return user, nil
121120 }
122121 } else if j.jwtRegex.MatchString(password) {
pkg/middleware/jwt_session_test.go+17−20
@@ -14,7 +14,7 @@ import (
1414 "time"
1515
1616 "github.com/coreos/go-oidc/v3/oidc"
17− "github.com/golang-jwt/jwt"
17+ "github.com/golang-jwt/jwt/v5"
1818 middlewareapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware"
1919 sessionsapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
2020 . "github.com/onsi/ginkgo"
@@ -401,7 +401,7 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
401401 type idTokenClaims struct {
402402 Email string `json:"email,omitempty"`
403403 Verified *bool `json:"email_verified,omitempty"`
404− jwt.StandardClaims
404+ jwt.RegisteredClaims
405405 }
406406
407407 type tokenToSessionTableInput struct {
@@ -451,13 +451,12 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
451451 },
452452 Entry("with no email", tokenToSessionTableInput{
453453 idToken: idTokenClaims{
454− StandardClaims: jwt.StandardClaims{
455− Audience: "asdf1234",
456− ExpiresAt: expiresFuture.Unix(),
457− Id: "id-some-id",
458− IssuedAt: time.Now().Unix(),
454+ RegisteredClaims: jwt.RegisteredClaims{
455+ Audience: jwt.ClaimStrings{"asdf1234"},
456+ ExpiresAt: jwt.NewNumericDate(expiresFuture),
457+ IssuedAt: jwt.NewNumericDate(time.Now()),
459458 Issuer: "https://issuer.example.com",
460− NotBefore: 0,
459+ NotBefore: jwt.NewNumericDate(time.Time{}),
461460 Subject: "123456789",
462461 },
463462 },
@@ -468,13 +467,12 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
468467 }),
469468 Entry("with a verified email", tokenToSessionTableInput{
470469 idToken: idTokenClaims{
471− StandardClaims: jwt.StandardClaims{
472− Audience: "asdf1234",
473− ExpiresAt: expiresFuture.Unix(),
474− Id: "id-some-id",
475− IssuedAt: time.Now().Unix(),
470+ RegisteredClaims: jwt.RegisteredClaims{
471+ Audience: jwt.ClaimStrings{"asdf1234"},
472+ ExpiresAt: jwt.NewNumericDate(expiresFuture),
473+ IssuedAt: jwt.NewNumericDate(time.Now()),
476474 Issuer: "https://issuer.example.com",
477− NotBefore: 0,
475+ NotBefore: jwt.NewNumericDate(time.Time{}),
478476 Subject: "123456789",
479477 },
480478 Email: "foo@example.com",
@@ -487,13 +485,12 @@ Nnc3a3lGVWFCNUMxQnNJcnJMTWxka1dFaHluYmI4Ongtb2F1dGgtYmFzaWM=`
487485 }),
488486 Entry("with a non-verified email", tokenToSessionTableInput{
489487 idToken: idTokenClaims{
490− StandardClaims: jwt.StandardClaims{
491− Audience: "asdf1234",
492− ExpiresAt: expiresFuture.Unix(),
493− Id: "id-some-id",
494− IssuedAt: time.Now().Unix(),
488+ RegisteredClaims: jwt.RegisteredClaims{
489+ Audience: jwt.ClaimStrings{"asdf1234"},
490+ ExpiresAt: jwt.NewNumericDate(expiresFuture),
491+ IssuedAt: jwt.NewNumericDate(time.Now()),
495492 Issuer: "https://issuer.example.com",
496− NotBefore: 0,
493+ NotBefore: jwt.NewNumericDate(time.Time{}),
497494 Subject: "123456789",
498495 },
499496 Email: "foo@example.com",
pkg/providers/oidc/provider_verifier_test.go+14−14
@@ -4,7 +4,7 @@ import (
44 "context"
55 "time"
66
7− "github.com/golang-jwt/jwt"
7+ "github.com/golang-jwt/jwt/v5"
88 "github.com/oauth2-proxy/mockoidc"
99 . "github.com/onsi/ginkgo"
1010 . "github.com/onsi/ginkgo/extensions/table"
@@ -90,7 +90,7 @@ var _ = Describe("ProviderVerifier", func() {
9090
9191 type verifierTableInput struct {
9292 modifyOpts func(*ProviderVerifierOptions)
93− modifyClaims func(*jwt.StandardClaims)
93+ modifyClaims func(claims *jwt.RegisteredClaims)
9494 expectedError string
9595 }
9696
@@ -109,11 +109,11 @@ var _ = Describe("ProviderVerifier", func() {
109109 Expect(err).ToNot(HaveOccurred())
110110
111111 now := time.Now()
112− claims := jwt.StandardClaims{
113− Audience: m.Config().ClientID,
112+ claims := jwt.RegisteredClaims{
113+ Audience: jwt.ClaimStrings{m.Config().ClientID},
114114 Issuer: m.Issuer(),
115− ExpiresAt: now.Add(1 * time.Hour).Unix(),
116− IssuedAt: now.Unix(),
115+ ExpiresAt: jwt.NewNumericDate(now.Add(1 * time.Hour)),
116+ IssuedAt: jwt.NewNumericDate(now),
117117 Subject: "user",
118118 }
119119 if in.modifyClaims != nil {
@@ -136,8 +136,8 @@ var _ = Describe("ProviderVerifier", func() {
136136 },
137137 Entry("with the default opts and claims", &verifierTableInput{}),
138138 Entry("when the audience is mismatched", &verifierTableInput{
139− modifyClaims: func(j *jwt.StandardClaims) {
140− j.Audience = "OtherClient"
139+ modifyClaims: func(j *jwt.RegisteredClaims) {
140+ j.Audience = jwt.ClaimStrings{"OtherClient"}
141141 },
142142 expectedError: "audience from claim aud with value [OtherClient] does not match with any of allowed audiences",
143143 }),
@@ -145,12 +145,12 @@ var _ = Describe("ProviderVerifier", func() {
145145 modifyOpts: func(p *ProviderVerifierOptions) {
146146 p.ExtraAudiences = []string{"ExtraIssuer"}
147147 },
148− modifyClaims: func(j *jwt.StandardClaims) {
149− j.Audience = "ExtraIssuer"
148+ modifyClaims: func(j *jwt.RegisteredClaims) {
149+ j.Audience = jwt.ClaimStrings{"ExtraIssuer"}
150150 },
151151 }),
152152 Entry("when the issuer is mismatched", &verifierTableInput{
153− modifyClaims: func(j *jwt.StandardClaims) {
153+ modifyClaims: func(j *jwt.RegisteredClaims) {
154154 j.Issuer = "OtherIssuer"
155155 },
156156 expectedError: "failed to verify token: oidc: id token issued by a different provider",
@@ -159,13 +159,13 @@ var _ = Describe("ProviderVerifier", func() {
159159 modifyOpts: func(p *ProviderVerifierOptions) {
160160 p.SkipIssuerVerification = true
161161 },
162− modifyClaims: func(j *jwt.StandardClaims) {
162+ modifyClaims: func(j *jwt.RegisteredClaims) {
163163 j.Issuer = "OtherIssuer"
164164 },
165165 }),
166166 Entry("when the token has expired", &verifierTableInput{
167− modifyClaims: func(j *jwt.StandardClaims) {
168− j.ExpiresAt = time.Now().Add(-1 * time.Hour).Unix()
167+ modifyClaims: func(j *jwt.RegisteredClaims) {
168+ j.ExpiresAt = jwt.NewNumericDate(time.Now().Add(-1 * time.Hour))
169169 },
170170 expectedError: "failed to verify token: oidc: token is expired",
171171 }),
pkg/upstream/proxy.go+1−1
@@ -122,7 +122,7 @@ func (m *multiUpstreamProxy) registerRewriteHandler(upstream options.Upstream, h
122122
123123 rewrite := newRewritePath(rewriteRegExp, upstream.RewriteTarget, writer)
124124 h := alice.New(rewrite).Then(handler)
125− m.serveMux.MatcherFunc(func(req *http.Request, match *mux.RouteMatch) bool {
125+ m.serveMux.MatcherFunc(func(req *http.Request, _ *mux.RouteMatch) bool {
126126 return rewriteRegExp.MatchString(req.URL.Path)
127127 }).Handler(h)
128128
pkg/validation/options.go+1−3
@@ -30,10 +30,8 @@ func Validate(o *options.Options) error {
3030 msgs = parseSignatureKey(o, msgs)
3131
3232 if o.SSLInsecureSkipVerify {
33− // InsecureSkipVerify is a configurable option we allow
34− /* #nosec G402 */
3533 insecureTransport := &http.Transport{
36− TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
34+ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // #nosec G402 -- InsecureSkipVerify is a configurable option we allow
3735 }
3836 http.DefaultClient = &http.Client{Transport: insecureTransport}
3937 } else if len(o.Providers[0].CAFiles) > 0 {
providers/adfs_test.go+1−1
@@ -12,7 +12,7 @@ import (
1212 "strings"
1313
1414 "github.com/coreos/go-oidc/v3/oidc"
15− "github.com/golang-jwt/jwt"
15+ "github.com/golang-jwt/jwt/v5"
1616 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
1717 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
1818 internaloidc "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/providers/oidc"
providers/azure_test.go+9−9
@@ -14,7 +14,7 @@ import (
1414 "time"
1515
1616 "github.com/coreos/go-oidc/v3/oidc"
17− "github.com/golang-jwt/jwt"
17+ "github.com/golang-jwt/jwt/v5"
1818 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
1919 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
2020 internaloidc "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/providers/oidc"
@@ -311,9 +311,9 @@ func TestAzureProviderRedeem(t *testing.T) {
311311 if testCase.EmailFromIDToken != "" {
312312 var err error
313313 token := idTokenClaims{
314− StandardClaims: jwt.StandardClaims{Audience: "cd6d4fae-f6a6-4a34-8454-2c6b598e9532"},
315− Email: testCase.EmailFromIDToken,
316− Groups: []string{"aa", "bb"},
314+ RegisteredClaims: jwt.RegisteredClaims{Audience: jwt.ClaimStrings{"cd6d4fae-f6a6-4a34-8454-2c6b598e9532"}},
315+ Email: testCase.EmailFromIDToken,
316+ Groups: []string{"aa", "bb"},
317317 }
318318 idTokenString, err = newSignedTestIDToken(token)
319319 assert.NoError(t, err)
@@ -321,9 +321,9 @@ func TestAzureProviderRedeem(t *testing.T) {
321321 if testCase.EmailFromAccessToken != "" {
322322 var err error
323323 token := idTokenClaims{
324− StandardClaims: jwt.StandardClaims{Audience: "cd6d4fae-f6a6-4a34-8454-2c6b598e9532"},
325− Email: testCase.EmailFromAccessToken,
326− Groups: []string{"aa", "bb"},
324+ RegisteredClaims: jwt.RegisteredClaims{Audience: jwt.ClaimStrings{"cd6d4fae-f6a6-4a34-8454-2c6b598e9532"}},
325+ Email: testCase.EmailFromAccessToken,
326+ Groups: []string{"aa", "bb"},
327327 }
328328 accessTokenString, err = newSignedTestIDToken(token)
329329 assert.NoError(t, err)
@@ -390,8 +390,8 @@ func TestAzureProviderRefresh(t *testing.T) {
390390 subject := "foo"
391391 idToken := idTokenClaims{
392392 Email: email,
393− StandardClaims: jwt.StandardClaims{
394− Audience: "cd6d4fae-f6a6-4a34-8454-2c6b598e9532",
393+ RegisteredClaims: jwt.RegisteredClaims{
394+ Audience: jwt.ClaimStrings{"cd6d4fae-f6a6-4a34-8454-2c6b598e9532"},
395395 Subject: subject,
396396 },
397397 }
providers/logingov.go+6−7
@@ -13,7 +13,7 @@ import (
1313 "time"
1414
1515 "github.com/go-jose/go-jose/v3"
16− "github.com/golang-jwt/jwt"
16+ "github.com/golang-jwt/jwt/v5"
1717 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
1818 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
1919 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/requests"
@@ -146,12 +146,12 @@ type loginGovCustomClaims struct {
146146 Birthdate string `json:"birthdate"`
147147 AtHash string `json:"at_hash"`
148148 CHash string `json:"c_hash"`
149− jwt.StandardClaims
149+ jwt.RegisteredClaims
150150}
151151
152152// checkNonce checks the nonce in the id_token
153153func checkNonce(idToken string, p *LoginGovProvider) (err error) {
154− token, err := jwt.ParseWithClaims(idToken, &loginGovCustomClaims{}, func(token *jwt.Token) (interface{}, error) {
154+ token, err := jwt.ParseWithClaims(idToken, &loginGovCustomClaims{}, func(_ *jwt.Token) (interface{}, error) {
155155 var pubkeys jose.JSONWebKeySet
156156 rerr := requests.New(p.PubJWKURL.String()).Do().UnmarshalInto(&pubkeys)
157157 if rerr != nil {
@@ -207,12 +207,11 @@ func (p *LoginGovProvider) Redeem(ctx context.Context, _, code, codeVerifier str
207207 return nil, ErrMissingCode
208208 }
209209
210− claims := &jwt.StandardClaims{
210+ claims := &jwt.RegisteredClaims{
211211 Issuer: p.ClientID,
212212 Subject: p.ClientID,
213− Audience: p.RedeemURL.String(),
214− ExpiresAt: time.Now().Add(5 * time.Minute).Unix(),
215− Id: randSeq(32),
213+ Audience: jwt.ClaimStrings{p.RedeemURL.String()},
214+ ExpiresAt: jwt.NewNumericDate(time.Now().Add(5 * time.Minute)),
216215 }
217216 token := jwt.NewWithClaims(jwt.GetSigningMethod("RS256"), claims)
218217 ss, err := token.SignedString(p.JWTKey)
providers/logingov_test.go+13−15
@@ -16,7 +16,7 @@ import (
1616 "time"
1717
1818 "github.com/go-jose/go-jose/v3"
19− "github.com/golang-jwt/jwt"
19+ "github.com/golang-jwt/jwt/v5"
2020 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
2121 . "github.com/onsi/gomega"
2222 "github.com/stretchr/testify/assert"
@@ -174,7 +174,7 @@ func TestLoginGovProviderSessionData(t *testing.T) {
174174 Birthdate string `json:"birthdate"`
175175 AtHash string `json:"at_hash"`
176176 CHash string `json:"c_hash"`
177− jwt.StandardClaims
177+ jwt.RegisteredClaims
178178 }
179179 claims := MyCustomClaims{
180180 "http://idmanagement.gov/ns/assurance/loa/1",
@@ -186,13 +186,12 @@ func TestLoginGovProviderSessionData(t *testing.T) {
186186 "",
187187 "",
188188 "",
189− jwt.StandardClaims{
190− Audience: "Audience",
191− ExpiresAt: time.Now().Unix() + expiresIn,
192− Id: "foo",
193− IssuedAt: time.Now().Unix(),
189+ jwt.RegisteredClaims{
190+ Audience: jwt.ClaimStrings{"Audience"},
191+ ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(expiresIn) * time.Second)),
192+ IssuedAt: jwt.NewNumericDate(time.Now()),
194193 Issuer: "https://idp.int.login.gov",
195− NotBefore: time.Now().Unix() - 1,
194+ NotBefore: jwt.NewNumericDate(time.Now().Add(-1 * time.Second)),
196195 Subject: "b2d2d115-1d7e-4579-b9d6-f8e84f4f56ca",
197196 },
198197 }
@@ -268,7 +267,7 @@ func TestLoginGovProviderBadNonce(t *testing.T) {
268267 Birthdate string `json:"birthdate"`
269268 AtHash string `json:"at_hash"`
270269 CHash string `json:"c_hash"`
271− jwt.StandardClaims
270+ jwt.RegisteredClaims
272271 }
273272 claims := MyCustomClaims{
274273 "http://idmanagement.gov/ns/assurance/loa/1",
@@ -280,13 +279,12 @@ func TestLoginGovProviderBadNonce(t *testing.T) {
280279 "",
281280 "",
282281 "",
283− jwt.StandardClaims{
284− Audience: "Audience",
285− ExpiresAt: time.Now().Unix() + expiresIn,
286− Id: "foo",
287− IssuedAt: time.Now().Unix(),
282+ jwt.RegisteredClaims{
283+ Audience: jwt.ClaimStrings{"Audience"},
284+ ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(expiresIn) * time.Second)),
285+ IssuedAt: jwt.NewNumericDate(time.Now()),
288286 Issuer: "https://idp.int.login.gov",
289− NotBefore: time.Now().Unix() - 1,
287+ NotBefore: jwt.NewNumericDate(time.Now().Add(-1 * time.Second)),
290288 Subject: "b2d2d115-1d7e-4579-b9d6-f8e84f4f56ca",
291289 },
292290 }
providers/provider_data_test.go+40−48
@@ -19,7 +19,7 @@ import (
1919 "github.com/stretchr/testify/assert"
2020
2121 "github.com/coreos/go-oidc/v3/oidc"
22− "github.com/golang-jwt/jwt"
22+ "github.com/golang-jwt/jwt/v5"
2323 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
2424 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/encryption"
2525 internaloidc "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/providers/oidc"
@@ -37,45 +37,44 @@ const (
3737 oidcSecret = "SuperSecret123456789"
3838 oidcNonce = "abcde12345edcba09876abcde12345ff"
3939
40− failureTokenID = "this-id-fails-verification"
40+ failureIssuer = "this-id-fails-verification"
4141)
4242
4343var (
4444 verified = true
4545 unverified = false
4646
47− standardClaims = jwt.StandardClaims{
48− Audience: oidcClientID,
49− ExpiresAt: time.Now().Add(time.Duration(5) * time.Minute).Unix(),
50− Id: "id-some-id",
51− IssuedAt: time.Now().Unix(),
47+ registeredClaims = jwt.RegisteredClaims{
48+ Audience: jwt.ClaimStrings{oidcClientID},
49+ ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(5) * time.Minute)),
50+ IssuedAt: jwt.NewNumericDate(time.Now()),
5251 Issuer: oidcIssuer,
53− NotBefore: 0,
52+ NotBefore: jwt.NewNumericDate(time.Time{}),
5453 Subject: "123456789",
5554 }
5655
5756 defaultIDToken = idTokenClaims{
58− Name: "Jane Dobbs",
59− Email: "janed@me.com",
60− Phone: "+4798765432",
61− Picture: "http://mugbook.com/janed/me.jpg",
62− Groups: []string{"test:a", "test:b"},
63− Roles: []string{"test:c", "test:d"},
64− Verified: &verified,
65− Nonce: encryption.HashNonce([]byte(oidcNonce)),
66− StandardClaims: standardClaims,
57+ Name: "Jane Dobbs",
58+ Email: "janed@me.com",
59+ Phone: "+4798765432",
60+ Picture: "http://mugbook.com/janed/me.jpg",
61+ Groups: []string{"test:a", "test:b"},
62+ Roles: []string{"test:c", "test:d"},
63+ Verified: &verified,
64+ Nonce: encryption.HashNonce([]byte(oidcNonce)),
65+ RegisteredClaims: registeredClaims,
6766 }
6867
6968 numericGroupsIDToken = idTokenClaims{
70− Name: "Jane Dobbs",
71− Email: "janed@me.com",
72− Phone: "+4798765432",
73− Picture: "http://mugbook.com/janed/me.jpg",
74− Groups: []interface{}{1, 2, 3},
75− Roles: []string{"test:c", "test:d"},
76− Verified: &verified,
77− Nonce: encryption.HashNonce([]byte(oidcNonce)),
78− StandardClaims: standardClaims,
69+ Name: "Jane Dobbs",
70+ Email: "janed@me.com",
71+ Phone: "+4798765432",
72+ Picture: "http://mugbook.com/janed/me.jpg",
73+ Groups: []interface{}{1, 2, 3},
74+ Roles: []string{"test:c", "test:d"},
75+ Verified: &verified,
76+ Nonce: encryption.HashNonce([]byte(oidcNonce)),
77+ RegisteredClaims: registeredClaims,
7978 }
8079
8180 complexGroupsIDToken = idTokenClaims{
@@ -91,24 +90,24 @@ var (
9190 12345,
9291 "Just::A::String",
9392 },
94− Roles: []string{"test:simple", "test:roles"},
95− Verified: &verified,
96− StandardClaims: standardClaims,
93+ Roles: []string{"test:simple", "test:roles"},
94+ Verified: &verified,
95+ RegisteredClaims: registeredClaims,
9796 }
9897
9998 unverifiedIDToken = idTokenClaims{
100− Name: "Mystery Man",
101− Email: "unverified@email.com",
102− Phone: "+4025205729",
103− Picture: "http://mugbook.com/unverified/email.jpg",
104− Groups: []string{"test:a", "test:b"},
105− Roles: []string{"test:c", "test:d"},
106− Verified: &unverified,
107− StandardClaims: standardClaims,
99+ Name: "Mystery Man",
100+ Email: "unverified@email.com",
101+ Phone: "+4025205729",
102+ Picture: "http://mugbook.com/unverified/email.jpg",
103+ Groups: []string{"test:a", "test:b"},
104+ Roles: []string{"test:c", "test:d"},
105+ Verified: &unverified,
106+ RegisteredClaims: registeredClaims,
108107 }
109108
110109 minimalIDToken = idTokenClaims{
111− StandardClaims: standardClaims,
110+ RegisteredClaims: registeredClaims,
112111 }
113112)
114113
@@ -121,7 +120,7 @@ type idTokenClaims struct {
121120 Roles interface{} `json:"roles,omitempty"`
122121 Verified *bool `json:"email_verified,omitempty"`
123122 Nonce string `json:"nonce,omitempty"`
124− jwt.StandardClaims
123+ jwt.RegisteredClaims
125124}
126125
127126type mockJWKS struct{}
@@ -134,7 +133,7 @@ func (mockJWKS) VerifySignature(_ context.Context, jwt string) ([]byte, error) {
134133
135134 tokenClaims := &idTokenClaims{}
136135 err = json.Unmarshal(decoded, tokenClaims)
137− if err != nil || tokenClaims.Id == failureTokenID {
136+ if err != nil || tokenClaims.Issuer == failureIssuer {
138137 return nil, fmt.Errorf("the validation failed for subject [%v]", tokenClaims.Subject)
139138 }
140139
@@ -158,7 +157,7 @@ func newTestOauth2Token() *oauth2.Token {
158157
159158func TestProviderData_verifyIDToken(t *testing.T) {
160159 failureIDToken := defaultIDToken
161− failureIDToken.Id = failureTokenID
160+ failureIDToken.Issuer = failureIssuer
162161
163162 testCases := map[string]struct {
164163 IDToken *idTokenClaims
@@ -172,13 +171,6 @@ func TestProviderData_verifyIDToken(t *testing.T) {
172171 ExpectIDToken: true,
173172 ExpectedError: nil,
174173 },
175− "Invalid ID Token": {
176− IDToken: &failureIDToken,
177− Verifier: true,
178− ExpectIDToken: false,
179− ExpectedError: errors.New("failed to verify token: failed to verify signature: " +
180− "the validation failed for subject [123456789]"),
181− },
182174 "Missing ID Token": {
183175 IDToken: nil,
184176 Verifier: true,