From 69c487fa7a058a659f0eeb587ce2947eb42b3567 Mon Sep 17 00:00:00 2001 From: Kang Ming Date: Wed, 11 Dec 2024 17:10:33 +0800 Subject: [PATCH 1/3] fix: update email_verified on signup --- internal/api/verify.go | 13 +++++++++++++ internal/models/user.go | 6 ++++++ 2 files changed, 19 insertions(+) diff --git a/internal/api/verify.go b/internal/api/verify.go index c4e8fa2523..c9d7ebf6f9 100644 --- a/internal/api/verify.go +++ b/internal/api/verify.go @@ -328,6 +328,19 @@ func (a *API) signupVerify(r *http.Request, ctx context.Context, conn *storage.C if terr = user.Confirm(tx); terr != nil { return internalServerError("Error confirming user").WithInternalError(terr) } + + // on signupVerify, the user will always only have an email identity + // so we can safely assume that the first identity is the email identity + // + // we still check for the length of the identities slice to be safe. + if len(user.Identities) != 0 { + emailIdentity := user.Identities[0] + if terr = emailIdentity.UpdateIdentityData(tx, map[string]interface{}{ + "email_verified": true, + }); terr != nil { + return internalServerError("Error updating email identity").WithInternalError(terr) + } + } return nil }) if err != nil { diff --git a/internal/models/user.go b/internal/models/user.go index 228e6e962e..3b16a54f90 100644 --- a/internal/models/user.go +++ b/internal/models/user.go @@ -449,6 +449,12 @@ func (u *User) Confirm(tx *storage.Connection) error { return err } + if err := u.UpdateUserMetaData(tx, map[string]interface{}{ + "email_verified": true, + }); err != nil { + return err + } + if err := ClearAllOneTimeTokensForUser(tx, u.ID); err != nil { return err } From be64d0a270b408abc684a1b5be7428647a7cc4dc Mon Sep 17 00:00:00 2001 From: Kang Ming Date: Wed, 11 Dec 2024 17:18:08 +0800 Subject: [PATCH 2/3] chore: update verify test --- internal/api/verify_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/internal/api/verify_test.go b/internal/api/verify_test.go index 59111ef068..c5fe965eb2 100644 --- a/internal/api/verify_test.go +++ b/internal/api/verify_test.go @@ -48,6 +48,14 @@ func (ts *VerifyTestSuite) SetupTest() { u, err := models.NewUser("12345678", "test@example.com", "password", ts.Config.JWT.Aud, nil) require.NoError(ts.T(), err, "Error creating test user model") require.NoError(ts.T(), ts.API.db.Create(u), "Error saving new test user") + + // Create identity + i, err := models.NewIdentity(u, "email", map[string]interface{}{ + "sub": u.ID.String(), + "email_verified": false, + }) + require.NoError(ts.T(), err, "Error creating test identity model") + require.NoError(ts.T(), ts.API.db.Create(i), "Error saving new test identity") } func (ts *VerifyTestSuite) TestVerifyPasswordRecovery() { @@ -673,6 +681,8 @@ func (ts *VerifyTestSuite) TestVerifySignupWithRedirectURLContainedPath() { u, err = models.FindUserByEmailAndAudience(ts.API.db, "test@example.com", ts.Config.JWT.Aud) require.NoError(ts.T(), err) assert.True(ts.T(), u.IsConfirmed()) + assert.True(ts.T(), u.UserMetaData["email_verified"].(bool)) + assert.True(ts.T(), u.Identities[0].IdentityData["email_verified"].(bool)) }) } } From 601f9986f0a7454d6e94554c9ff2cdd8440241fe Mon Sep 17 00:00:00 2001 From: Kang Ming Date: Thu, 12 Dec 2024 12:16:58 +0800 Subject: [PATCH 3/3] fix: add checks for cases where more than 1 identity is returned --- internal/api/verify.go | 6 ++++++ internal/api/verify_test.go | 25 +++++++++++++------------ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/internal/api/verify.go b/internal/api/verify.go index c9d7ebf6f9..b48716a874 100644 --- a/internal/api/verify.go +++ b/internal/api/verify.go @@ -334,7 +334,13 @@ func (a *API) signupVerify(r *http.Request, ctx context.Context, conn *storage.C // // we still check for the length of the identities slice to be safe. if len(user.Identities) != 0 { + if len(user.Identities) > 1 { + return internalServerError("User has more than one identity on signup") + } emailIdentity := user.Identities[0] + if emailIdentity.Email != user.Email { + return internalServerError("User email identity does not match user email") + } if terr = emailIdentity.UpdateIdentityData(tx, map[string]interface{}{ "email_verified": true, }); terr != nil { diff --git a/internal/api/verify_test.go b/internal/api/verify_test.go index c5fe965eb2..7c97d69eab 100644 --- a/internal/api/verify_test.go +++ b/internal/api/verify_test.go @@ -52,6 +52,7 @@ func (ts *VerifyTestSuite) SetupTest() { // Create identity i, err := models.NewIdentity(u, "email", map[string]interface{}{ "sub": u.ID.String(), + "email": "test@example.com", "email_verified": false, }) require.NoError(ts.T(), err, "Error creating test identity model") @@ -885,6 +886,18 @@ func (ts *VerifyTestSuite) TestVerifyValidOtp() { tokenHash: crypto.GenerateTokenHash(u.GetEmail(), "123456"), }, }, + { + desc: "Valid Signup Token Hash", + sentTime: time.Now(), + body: map[string]interface{}{ + "type": mail.SignupVerification, + "token_hash": crypto.GenerateTokenHash(u.GetEmail(), "123456"), + }, + expected: expected{ + code: http.StatusOK, + tokenHash: crypto.GenerateTokenHash(u.GetEmail(), "123456"), + }, + }, { desc: "Valid Recovery OTP", sentTime: time.Now(), @@ -950,18 +963,6 @@ func (ts *VerifyTestSuite) TestVerifyValidOtp() { tokenHash: crypto.GenerateTokenHash(u.PhoneChange, "123456"), }, }, - { - desc: "Valid Signup Token Hash", - sentTime: time.Now(), - body: map[string]interface{}{ - "type": mail.SignupVerification, - "token_hash": crypto.GenerateTokenHash(u.GetEmail(), "123456"), - }, - expected: expected{ - code: http.StatusOK, - tokenHash: crypto.GenerateTokenHash(u.GetEmail(), "123456"), - }, - }, { desc: "Valid Email Change Token Hash", sentTime: time.Now(),