From 609fea00027901dfde549e9db1e40dedb32e6f80 Mon Sep 17 00:00:00 2001 From: Allan Guwatudde Date: Mon, 18 Oct 2021 09:34:10 +0300 Subject: [PATCH] [MM-39205] Check that emails match during sign-up (#18635) --- app/user.go | 5 +++++ app/user_test.go | 33 ++++++++++++++++++++++++--------- i18n/en.json | 4 ++++ 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/app/user.go b/app/user.go index 8e9f63f34e..0547da1782 100644 --- a/app/user.go +++ b/app/user.go @@ -72,6 +72,11 @@ func (a *App) CreateUserWithToken(c *request.Context, user *model.User, token *m return nil, model.NewAppError("CreateUserWithToken", "app.channel.get_channels_by_ids.app_error", nil, nErr.Error(), http.StatusInternalServerError) } + emailFromToken := tokenData["email"] + if emailFromToken != user.Email { + return nil, model.NewAppError("CreateUserWithToken", "api.user.create_user.bad_token_email_data.app_error", nil, "", http.StatusBadRequest) + } + user.Email = tokenData["email"] user.EmailVerified = true diff --git a/app/user_test.go b/app/user_test.go index acc51c6c94..b81a793fb9 100644 --- a/app/user_test.go +++ b/app/user_test.go @@ -743,6 +743,18 @@ func TestCreateUserWithToken(t *testing.T) { require.NotNil(t, err, "Should fail on bad token type") }) + t.Run("token extra email does not match provided user data email", func(t *testing.T) { + invitationEmail := "attacker@test.com" + token := model.NewToken( + TokenTypeTeamInvitation, + model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "email": invitationEmail}), + ) + + require.NoError(t, th.App.Srv().Store.Token().Save(token)) + _, err := th.App.CreateUserWithToken(th.Context, &user, token) + require.NotNil(t, err) + }) + t.Run("expired token", func(t *testing.T) { token := model.NewToken( TokenTypeTeamInvitation, @@ -767,13 +779,14 @@ func TestCreateUserWithToken(t *testing.T) { }) t.Run("valid regular user request", func(t *testing.T) { - invitationEmail := model.NewId() + "other-email@test.com" + invitationEmail := strings.ToLower(model.NewId()) + "other-email@test.com" + u := model.User{Email: invitationEmail, Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} token := model.NewToken( TokenTypeTeamInvitation, model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "email": invitationEmail}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) - newUser, err := th.App.CreateUserWithToken(th.Context, &user, token) + newUser, err := th.App.CreateUserWithToken(th.Context, &u, token) require.Nil(t, err, "Should add user to the team. err=%v", err) assert.False(t, newUser.IsGuest()) require.Equal(t, invitationEmail, newUser.Email, "The user email must be the invitation one") @@ -787,13 +800,14 @@ func TestCreateUserWithToken(t *testing.T) { }) t.Run("valid guest request", func(t *testing.T) { - invitationEmail := model.NewId() + "other-email@test.com" + invitationEmail := strings.ToLower(model.NewId()) + "other-email@test.com" token := model.NewToken( TokenTypeGuestInvitation, model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "email": invitationEmail, "channels": th.BasicChannel.Id}), ) + require.NoError(t, th.App.Srv().Store.Token().Save(token)) - guest := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} + guest := model.User{Email: invitationEmail, Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} newGuest, err := th.App.CreateUserWithToken(th.Context, &guest, token) require.Nil(t, err, "Should add user to the team. err=%v", err) @@ -816,8 +830,8 @@ func TestCreateUserWithToken(t *testing.T) { }) }() th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GuestAccountsSettings.RestrictCreationToDomains = "restricted.com" }) - forbiddenInvitationEmail := model.NewId() + "other-email@test.com" - grantedInvitationEmail := model.NewId() + "other-email@restricted.com" + forbiddenInvitationEmail := strings.ToLower(model.NewId()) + "other-email@test.com" + grantedInvitationEmail := strings.ToLower(model.NewId()) + "other-email@restricted.com" forbiddenDomainToken := model.NewToken( TokenTypeGuestInvitation, model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "email": forbiddenInvitationEmail, "channels": th.BasicChannel.Id}), @@ -829,7 +843,7 @@ func TestCreateUserWithToken(t *testing.T) { require.NoError(t, th.App.Srv().Store.Token().Save(forbiddenDomainToken)) require.NoError(t, th.App.Srv().Store.Token().Save(grantedDomainToken)) guest := model.User{ - Email: strings.ToLower(model.NewId()) + "+test@example.com", + Email: forbiddenInvitationEmail, Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", @@ -840,6 +854,7 @@ func TestCreateUserWithToken(t *testing.T) { require.Nil(t, newGuest) assert.Equal(t, "api.user.create_user.accepted_domain.app_error", err.Id) + guest.Email = grantedInvitationEmail newGuest, err = th.App.CreateUserWithToken(th.Context, &guest, grantedDomainToken) require.Nil(t, err) assert.True(t, newGuest.IsGuest()) @@ -864,14 +879,14 @@ func TestCreateUserWithToken(t *testing.T) { }) }() th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.RestrictCreationToDomains = "restricted.com" }) - invitationEmail := model.NewId() + "other-email@test.com" + invitationEmail := strings.ToLower(model.NewId()) + "other-email@test.com" token := model.NewToken( TokenTypeGuestInvitation, model.MapToJSON(map[string]string{"teamId": th.BasicTeam.Id, "email": invitationEmail, "channels": th.BasicChannel.Id}), ) require.NoError(t, th.App.Srv().Store.Token().Save(token)) guest := model.User{ - Email: strings.ToLower(model.NewId()) + "+test@example.com", + Email: invitationEmail, Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", diff --git a/i18n/en.json b/i18n/en.json index e747212b13..3f36bd6a2c 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -3871,6 +3871,10 @@ "id": "api.user.create_user.accepted_domain.app_error", "translation": "The email you provided does not belong to an accepted domain. Please contact your administrator or sign up with a different email." }, + { + "id": "api.user.create_user.bad_token_email_data.app_error", + "translation": "The email address in the token does not match the one in the user data." + }, { "id": "api.user.create_user.disabled.app_error", "translation": "User creation is disabled."