diff --git a/go.mod b/go.mod index 2cb1e65a..6c469d15 100644 --- a/go.mod +++ b/go.mod @@ -16,11 +16,11 @@ require ( github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.67 github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.14.11 github.com/aws/aws-sdk-go-v2/service/s3 v1.33.1 - github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.19.7 + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.19.8 github.com/aws/aws-sdk-go-v2/service/sts v1.19.0 github.com/bmatcuk/doublestar/v4 v4.6.0 github.com/cockroachdb/cockroach-go/v2 v2.3.3 - github.com/coreos/go-oidc/v3 v3.5.0 + github.com/coreos/go-oidc/v3 v3.6.0 github.com/drakkan/webdav v0.0.0-20230227175313-32996838bcd8 github.com/eikenb/pipeat v0.0.0-20210730190139-06b3e6902001 github.com/fclairamb/ftpserverlib v0.21.0 @@ -80,7 +80,7 @@ require ( require ( cloud.google.com/go v0.110.2 // indirect - cloud.google.com/go/compute v1.19.2 // indirect + cloud.google.com/go/compute v1.19.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v1.0.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect diff --git a/go.sum b/go.sum index b2a19b0f..f371093b 100644 --- a/go.sum +++ b/go.sum @@ -124,8 +124,8 @@ cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARy cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= -cloud.google.com/go/compute v1.19.2 h1:GbJtPo8OKVHbVep8jvM57KidbYHxeE68LOVqouNLrDY= -cloud.google.com/go/compute v1.19.2/go.mod h1:5f5a+iC1IriXYauaQ0EyQmEAEq9CGRnV5xJSQSlTV08= +cloud.google.com/go/compute v1.19.3 h1:DcTwsFgGev/wV5+q8o2fzgcHOaac+DKGC91ZlvpsQds= +cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= @@ -607,8 +607,8 @@ github.com/aws/aws-sdk-go-v2/service/s3 v1.30.2/go.mod h1:SXDHd6fI2RhqB7vmAzyYQC github.com/aws/aws-sdk-go-v2/service/s3 v1.33.1 h1:O+9nAy9Bb6bJFTpeNFtd9UfHbgxO1o4ZDAM9rQp5NsY= github.com/aws/aws-sdk-go-v2/service/s3 v1.33.1/go.mod h1:J9kLNzEiHSeGMyN7238EjJmBpCniVzFda75Gxl/NqB8= github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.18.3/go.mod h1:hqPcyOuLU6yWIbLy3qMnQnmidgKuIEwqIlW6+chYnog= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.19.7 h1:W88E2kZGo+NHOsyvQbsOZYqxXJdLIqRzKadeVlv5J7k= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.19.7/go.mod h1:3ARttS6G6U3auEdKfaN4GlnfS9UxYE9nqub1+0YGycA= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.19.8 h1:eB91eEYUlh8+O2dXr189W8GJJd+/T8N/c5HocH2KzVo= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.19.8/go.mod h1:3ARttS6G6U3auEdKfaN4GlnfS9UxYE9nqub1+0YGycA= github.com/aws/aws-sdk-go-v2/service/sns v1.20.2/go.mod h1:VN2n9SOMS1lNbh5YD7o+ho0/rgfifSrK//YYNiVVF5E= github.com/aws/aws-sdk-go-v2/service/sqs v1.20.2/go.mod h1:1ttxGjUHZliCQMpPss1sU5+Ph/5NvdMFRzr96bv8gm0= github.com/aws/aws-sdk-go-v2/service/ssm v1.35.2/go.mod h1:VLSz2SHUKYFSOlXB/GlXoLU6KPYQJAbw7I20TDJdyws= @@ -807,8 +807,8 @@ github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmeka github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-oidc/v3 v3.5.0 h1:VxKtbccHZxs8juq7RdJntSqtXFtde9YpNpGn0yqgEHw= -github.com/coreos/go-oidc/v3 v3.5.0/go.mod h1:ecXRtV4romGPeO6ieExAsUK9cb/3fp9hXNz1tlv8PIM= +github.com/coreos/go-oidc/v3 v3.6.0 h1:AKVxfYw1Gmkn/w96z0DbT/B/xFnzTd3MkZvWLjF4n/o= +github.com/coreos/go-oidc/v3 v3.6.0/go.mod h1:ZpHUsHBucTUj6WOkrP4E20UPynbLZzhTQ1XKCXkxyPc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= diff --git a/internal/httpd/oidc.go b/internal/httpd/oidc.go index 1110e419..fb31b973 100644 --- a/internal/httpd/oidc.go +++ b/internal/httpd/oidc.go @@ -163,10 +163,7 @@ func (o *OIDC) initialize() error { } } o.provider = provider - o.verifier = provider.Verifier(&oidc.Config{ - ClientID: o.ClientID, - InsecureSkipSignatureCheck: o.InsecureSkipSignatureCheck, - }) + o.verifier = nil o.oauth2Config = &oauth2.Config{ ClientID: o.ClientID, ClientSecret: o.ClientSecret, @@ -178,6 +175,16 @@ func (o *OIDC) initialize() error { return nil } +func (o *OIDC) getVerifier(ctx context.Context) OIDCTokenVerifier { + if o.verifier != nil { + return o.verifier + } + return o.provider.VerifierContext(ctx, &oidc.Config{ + ClientID: o.ClientID, + InsecureSkipSignatureCheck: o.InsecureSkipSignatureCheck, + }) +} + type oidcPendingAuth struct { State string `json:"state"` Nonce string `json:"nonce"` @@ -291,7 +298,7 @@ func (t *oidcToken) isExpired() bool { return t.ExpiresAt < util.GetTimeAsMsSinceEpoch(time.Now()) } -func (t *oidcToken) refresh(config OAuth2Config, verifier OIDCTokenVerifier, r *http.Request) error { +func (t *oidcToken) refresh(ctx context.Context, config OAuth2Config, verifier OIDCTokenVerifier, r *http.Request) error { if t.RefreshToken == "" { logger.Debug(logSender, "", "refresh token not set, unable to refresh cookie %q", t.Cookie) return errors.New("refresh token not set") @@ -304,8 +311,6 @@ func (t *oidcToken) refresh(config OAuth2Config, verifier OIDCTokenVerifier, r * if t.ExpiresAt > 0 { oauth2Token.Expiry = util.GetTimeFromMsecSinceEpoch(t.ExpiresAt) } - ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) - defer cancel() newToken, err := config.TokenSource(ctx, &oauth2Token).Token() if err != nil { @@ -480,7 +485,10 @@ func (s *httpdServer) validateOIDCToken(w http.ResponseWriter, r *http.Request, } if token.isExpired() { logger.Debug(logSender, "", "oidc token associated with cookie %q is expired", token.Cookie) - if err = token.refresh(s.binding.OIDC.oauth2Config, s.binding.OIDC.verifier, r); err != nil { + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) + defer cancel() + + if err = token.refresh(ctx, s.binding.OIDC.oauth2Config, s.binding.OIDC.getVerifier(ctx), r); err != nil { setFlashMessage(w, r, "Your OpenID token is expired, please log-in again") doRedirect() return oidcToken{}, errInvalidToken @@ -606,7 +614,7 @@ func (s *httpdServer) handleOIDCRedirect(w http.ResponseWriter, r *http.Request) return } s.debugTokenClaims(nil, rawIDToken) - idToken, err := s.binding.OIDC.verifier.Verify(ctx, rawIDToken) + idToken, err := s.binding.OIDC.getVerifier(ctx).Verify(ctx, rawIDToken) if err != nil { logger.Debug(logSender, "", "failed to verify oidc token: %v", err) setFlashMessage(w, r, "Failed to verify OpenID token") diff --git a/internal/httpd/oidc_test.go b/internal/httpd/oidc_test.go index 4d699f9d..205f362b 100644 --- a/internal/httpd/oidc_test.go +++ b/internal/httpd/oidc_test.go @@ -566,12 +566,12 @@ func TestOIDCRefreshToken(t *testing.T) { verifier := mockOIDCVerifier{ err: common.ErrGenericFailure, } - err = token.refresh(&config, &verifier, r) + err = token.refresh(context.Background(), &config, &verifier, r) if assert.Error(t, err) { assert.Contains(t, err.Error(), "refresh token not set") } token.RefreshToken = xid.New().String() - err = token.refresh(&config, &verifier, r) + err = token.refresh(context.Background(), &config, &verifier, r) assert.ErrorIs(t, err, common.ErrGenericFailure) newToken := &oauth2.Token{ @@ -587,7 +587,7 @@ func TestOIDCRefreshToken(t *testing.T) { verifier = mockOIDCVerifier{ token: &oidc.IDToken{}, } - err = token.refresh(&config, &verifier, r) + err = token.refresh(context.Background(), &config, &verifier, r) if assert.Error(t, err) { assert.Contains(t, err.Error(), "the refreshed token has no id token") } @@ -603,7 +603,7 @@ func TestOIDCRefreshToken(t *testing.T) { verifier = mockOIDCVerifier{ err: common.ErrGenericFailure, } - err = token.refresh(&config, &verifier, r) + err = token.refresh(context.Background(), &config, &verifier, r) assert.ErrorIs(t, err, common.ErrGenericFailure) newToken = newToken.WithExtra(map[string]any{ @@ -618,7 +618,7 @@ func TestOIDCRefreshToken(t *testing.T) { verifier = mockOIDCVerifier{ token: &oidc.IDToken{}, } - err = token.refresh(&config, &verifier, r) + err = token.refresh(context.Background(), &config, &verifier, r) if assert.Error(t, err) { assert.Contains(t, err.Error(), "the refreshed token nonce mismatch") } @@ -627,7 +627,7 @@ func TestOIDCRefreshToken(t *testing.T) { Nonce: token.Nonce, }, } - err = token.refresh(&config, &verifier, r) + err = token.refresh(context.Background(), &config, &verifier, r) if assert.Error(t, err) { assert.Contains(t, err.Error(), "oidc: claims not set") } @@ -638,12 +638,12 @@ func TestOIDCRefreshToken(t *testing.T) { verifier = mockOIDCVerifier{ token: idToken, } - err = token.refresh(&config, &verifier, r) + err = token.refresh(context.Background(), &config, &verifier, r) assert.NoError(t, err) assert.Len(t, token.Permissions, 1) token.Role = nil // user does not exist - err = token.refresh(&config, &verifier, r) + err = token.refresh(context.Background(), &config, &verifier, r) assert.Error(t, err) require.Len(t, oidcMgr.tokens, 1) oidcMgr.removeToken(token.Cookie) diff --git a/templates/common/forgot-password.html b/templates/common/forgot-password.html index e3344e4e..438d7b5c 100644 --- a/templates/common/forgot-password.html +++ b/templates/common/forgot-password.html @@ -57,7 +57,7 @@ along with this program. If not, see .

Forgot Your Password?

-

If you have added an email address to your account, we'll email you a code to reset your password. Enter your account username below

+

Enter your account username below, you will receive a password reset code by email.

{{if .Error}}