Browse Source

update pwd reset template. Update deps and use new features from the OIDC library

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
Nicola Murino 2 years ago
parent
commit
52ec36dbd6
5 changed files with 35 additions and 27 deletions
  1. 3 3
      go.mod
  2. 6 6
      go.sum
  3. 17 9
      internal/httpd/oidc.go
  4. 8 8
      internal/httpd/oidc_test.go
  5. 1 1
      templates/common/forgot-password.html

+ 3 - 3
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/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/marketplacemetering v1.14.11
 	github.com/aws/aws-sdk-go-v2/service/s3 v1.33.1
 	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/aws/aws-sdk-go-v2/service/sts v1.19.0
 	github.com/bmatcuk/doublestar/v4 v4.6.0
 	github.com/bmatcuk/doublestar/v4 v4.6.0
 	github.com/cockroachdb/cockroach-go/v2 v2.3.3
 	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/drakkan/webdav v0.0.0-20230227175313-32996838bcd8
 	github.com/eikenb/pipeat v0.0.0-20210730190139-06b3e6902001
 	github.com/eikenb/pipeat v0.0.0-20210730190139-06b3e6902001
 	github.com/fclairamb/ftpserverlib v0.21.0
 	github.com/fclairamb/ftpserverlib v0.21.0
@@ -80,7 +80,7 @@ require (
 
 
 require (
 require (
 	cloud.google.com/go v0.110.2 // indirect
 	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/compute/metadata v0.2.3 // indirect
 	cloud.google.com/go/iam v1.0.1 // indirect
 	cloud.google.com/go/iam v1.0.1 // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect

+ 6 - 6
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.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.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.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.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.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
 cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
 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 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/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.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/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/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=
 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.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
 github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
 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 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.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-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=
 github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=

+ 17 - 9
internal/httpd/oidc.go

@@ -163,10 +163,7 @@ func (o *OIDC) initialize() error {
 		}
 		}
 	}
 	}
 	o.provider = provider
 	o.provider = provider
-	o.verifier = provider.Verifier(&oidc.Config{
-		ClientID:                   o.ClientID,
-		InsecureSkipSignatureCheck: o.InsecureSkipSignatureCheck,
-	})
+	o.verifier = nil
 	o.oauth2Config = &oauth2.Config{
 	o.oauth2Config = &oauth2.Config{
 		ClientID:     o.ClientID,
 		ClientID:     o.ClientID,
 		ClientSecret: o.ClientSecret,
 		ClientSecret: o.ClientSecret,
@@ -178,6 +175,16 @@ func (o *OIDC) initialize() error {
 	return nil
 	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 {
 type oidcPendingAuth struct {
 	State    string        `json:"state"`
 	State    string        `json:"state"`
 	Nonce    string        `json:"nonce"`
 	Nonce    string        `json:"nonce"`
@@ -291,7 +298,7 @@ func (t *oidcToken) isExpired() bool {
 	return t.ExpiresAt < util.GetTimeAsMsSinceEpoch(time.Now())
 	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 == "" {
 	if t.RefreshToken == "" {
 		logger.Debug(logSender, "", "refresh token not set, unable to refresh cookie %q", t.Cookie)
 		logger.Debug(logSender, "", "refresh token not set, unable to refresh cookie %q", t.Cookie)
 		return errors.New("refresh token not set")
 		return errors.New("refresh token not set")
@@ -304,8 +311,6 @@ func (t *oidcToken) refresh(config OAuth2Config, verifier OIDCTokenVerifier, r *
 	if t.ExpiresAt > 0 {
 	if t.ExpiresAt > 0 {
 		oauth2Token.Expiry = util.GetTimeFromMsecSinceEpoch(t.ExpiresAt)
 		oauth2Token.Expiry = util.GetTimeFromMsecSinceEpoch(t.ExpiresAt)
 	}
 	}
-	ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
-	defer cancel()
 
 
 	newToken, err := config.TokenSource(ctx, &oauth2Token).Token()
 	newToken, err := config.TokenSource(ctx, &oauth2Token).Token()
 	if err != nil {
 	if err != nil {
@@ -480,7 +485,10 @@ func (s *httpdServer) validateOIDCToken(w http.ResponseWriter, r *http.Request,
 	}
 	}
 	if token.isExpired() {
 	if token.isExpired() {
 		logger.Debug(logSender, "", "oidc token associated with cookie %q is expired", token.Cookie)
 		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")
 			setFlashMessage(w, r, "Your OpenID token is expired, please log-in again")
 			doRedirect()
 			doRedirect()
 			return oidcToken{}, errInvalidToken
 			return oidcToken{}, errInvalidToken
@@ -606,7 +614,7 @@ func (s *httpdServer) handleOIDCRedirect(w http.ResponseWriter, r *http.Request)
 		return
 		return
 	}
 	}
 	s.debugTokenClaims(nil, rawIDToken)
 	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 {
 	if err != nil {
 		logger.Debug(logSender, "", "failed to verify oidc token: %v", err)
 		logger.Debug(logSender, "", "failed to verify oidc token: %v", err)
 		setFlashMessage(w, r, "Failed to verify OpenID token")
 		setFlashMessage(w, r, "Failed to verify OpenID token")

+ 8 - 8
internal/httpd/oidc_test.go

@@ -566,12 +566,12 @@ func TestOIDCRefreshToken(t *testing.T) {
 	verifier := mockOIDCVerifier{
 	verifier := mockOIDCVerifier{
 		err: common.ErrGenericFailure,
 		err: common.ErrGenericFailure,
 	}
 	}
-	err = token.refresh(&config, &verifier, r)
+	err = token.refresh(context.Background(), &config, &verifier, r)
 	if assert.Error(t, err) {
 	if assert.Error(t, err) {
 		assert.Contains(t, err.Error(), "refresh token not set")
 		assert.Contains(t, err.Error(), "refresh token not set")
 	}
 	}
 	token.RefreshToken = xid.New().String()
 	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)
 	assert.ErrorIs(t, err, common.ErrGenericFailure)
 
 
 	newToken := &oauth2.Token{
 	newToken := &oauth2.Token{
@@ -587,7 +587,7 @@ func TestOIDCRefreshToken(t *testing.T) {
 	verifier = mockOIDCVerifier{
 	verifier = mockOIDCVerifier{
 		token: &oidc.IDToken{},
 		token: &oidc.IDToken{},
 	}
 	}
-	err = token.refresh(&config, &verifier, r)
+	err = token.refresh(context.Background(), &config, &verifier, r)
 	if assert.Error(t, err) {
 	if assert.Error(t, err) {
 		assert.Contains(t, err.Error(), "the refreshed token has no id token")
 		assert.Contains(t, err.Error(), "the refreshed token has no id token")
 	}
 	}
@@ -603,7 +603,7 @@ func TestOIDCRefreshToken(t *testing.T) {
 	verifier = mockOIDCVerifier{
 	verifier = mockOIDCVerifier{
 		err: common.ErrGenericFailure,
 		err: common.ErrGenericFailure,
 	}
 	}
-	err = token.refresh(&config, &verifier, r)
+	err = token.refresh(context.Background(), &config, &verifier, r)
 	assert.ErrorIs(t, err, common.ErrGenericFailure)
 	assert.ErrorIs(t, err, common.ErrGenericFailure)
 
 
 	newToken = newToken.WithExtra(map[string]any{
 	newToken = newToken.WithExtra(map[string]any{
@@ -618,7 +618,7 @@ func TestOIDCRefreshToken(t *testing.T) {
 	verifier = mockOIDCVerifier{
 	verifier = mockOIDCVerifier{
 		token: &oidc.IDToken{},
 		token: &oidc.IDToken{},
 	}
 	}
-	err = token.refresh(&config, &verifier, r)
+	err = token.refresh(context.Background(), &config, &verifier, r)
 	if assert.Error(t, err) {
 	if assert.Error(t, err) {
 		assert.Contains(t, err.Error(), "the refreshed token nonce mismatch")
 		assert.Contains(t, err.Error(), "the refreshed token nonce mismatch")
 	}
 	}
@@ -627,7 +627,7 @@ func TestOIDCRefreshToken(t *testing.T) {
 			Nonce: token.Nonce,
 			Nonce: token.Nonce,
 		},
 		},
 	}
 	}
-	err = token.refresh(&config, &verifier, r)
+	err = token.refresh(context.Background(), &config, &verifier, r)
 	if assert.Error(t, err) {
 	if assert.Error(t, err) {
 		assert.Contains(t, err.Error(), "oidc: claims not set")
 		assert.Contains(t, err.Error(), "oidc: claims not set")
 	}
 	}
@@ -638,12 +638,12 @@ func TestOIDCRefreshToken(t *testing.T) {
 	verifier = mockOIDCVerifier{
 	verifier = mockOIDCVerifier{
 		token: idToken,
 		token: idToken,
 	}
 	}
-	err = token.refresh(&config, &verifier, r)
+	err = token.refresh(context.Background(), &config, &verifier, r)
 	assert.NoError(t, err)
 	assert.NoError(t, err)
 	assert.Len(t, token.Permissions, 1)
 	assert.Len(t, token.Permissions, 1)
 	token.Role = nil
 	token.Role = nil
 	// user does not exist
 	// user does not exist
-	err = token.refresh(&config, &verifier, r)
+	err = token.refresh(context.Background(), &config, &verifier, r)
 	assert.Error(t, err)
 	assert.Error(t, err)
 	require.Len(t, oidcMgr.tokens, 1)
 	require.Len(t, oidcMgr.tokens, 1)
 	oidcMgr.removeToken(token.Cookie)
 	oidcMgr.removeToken(token.Cookie)

+ 1 - 1
templates/common/forgot-password.html

@@ -57,7 +57,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
                                 <div class="p-5">
                                 <div class="p-5">
                                     <div class="text-center">
                                     <div class="text-center">
                                         <h1 class="h4 text-gray-900 mb-4">Forgot Your Password?</h1>
                                         <h1 class="h4 text-gray-900 mb-4">Forgot Your Password?</h1>
-                                        <p class="mb-4">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</p>
+                                        <p class="mb-4">Enter your account username below, you will receive a password reset code by email.</p>
                                     </div>
                                     </div>
                                     {{if .Error}}
                                     {{if .Error}}
                                     <div class="alert alert-warning alert-dismissible fade show" role="alert">
                                     <div class="alert alert-warning alert-dismissible fade show" role="alert">