From 4a205bbda7d27e818c16116311f8994e3bdbb422 Mon Sep 17 00:00:00 2001 From: Daniel Krol Date: Sat, 30 Jul 2022 15:06:27 -0400 Subject: [PATCH] GetUserId - Return error if account unverified --- store/account_test.go | 17 +++++++++++++++-- store/auth_test.go | 12 ++++++------ store/password_test.go | 8 ++++---- store/store.go | 10 ++++++++-- store/store_test.go | 10 ++++++++-- store/wallet_test.go | 10 +++++----- 6 files changed, 46 insertions(+), 21 deletions(-) diff --git a/store/account_test.go b/store/account_test.go index d623089..06ab7c9 100644 --- a/store/account_test.go +++ b/store/account_test.go @@ -167,7 +167,7 @@ func TestStoreGetUserIdAccountExists(t *testing.T) { s, sqliteTmpFile := StoreTestInit(t) defer StoreTestCleanup(sqliteTmpFile) - createdUserId, email, password, _ := makeTestUser(t, &s) + createdUserId, email, password, _ := makeTestUser(t, &s, "", nil) // Check that the userId is correct for the email, irrespective of the case of // the characters in the email. @@ -190,6 +190,19 @@ func TestStoreGetUserIdAccountExists(t *testing.T) { } } +// Test GetUserId for existing but unverified account +func TestStoreGetUserIdAccountUnverified(t *testing.T) { + s, sqliteTmpFile := StoreTestInit(t) + defer StoreTestCleanup(sqliteTmpFile) + + _, email, password, _ := makeTestUser(t, &s, "abcd1234abcd1234abcd1234abcd1234", &time.Time{}) + + // Check that it won't return if the account is unverified + if userId, err := s.GetUserId(email, password); err != ErrNotVerified || userId != 0 { + t.Fatalf(`GetUserId error for unverified account: wanted "%+v", got "%+v. userId: %v"`, ErrNotVerified, err, userId) + } +} + func TestStoreAccountEmptyFields(t *testing.T) { // Make sure expiration doesn't get set if sanitization fails tt := []struct { @@ -237,7 +250,7 @@ func TestStoreGetClientSaltSeedAccountSuccess(t *testing.T) { s, sqliteTmpFile := StoreTestInit(t) defer StoreTestCleanup(sqliteTmpFile) - _, email, _, createdSeed := makeTestUser(t, &s) + _, email, _, createdSeed := makeTestUser(t, &s, "", nil) // Check that the seed is correct for the email, irrespective of the case of // the characters in the email. diff --git a/store/auth_test.go b/store/auth_test.go index 9210c01..3686d16 100644 --- a/store/auth_test.go +++ b/store/auth_test.go @@ -77,7 +77,7 @@ func TestStoreInsertToken(t *testing.T) { s, sqliteTmpFile := StoreTestInit(t) defer StoreTestCleanup(sqliteTmpFile) - userId, _, _, _ := makeTestUser(t, &s) + userId, _, _, _ := makeTestUser(t, &s, "", nil) // created for addition to the DB (no expiration attached) authToken1 := auth.AuthToken{ @@ -123,7 +123,7 @@ func TestStoreUpdateToken(t *testing.T) { s, sqliteTmpFile := StoreTestInit(t) defer StoreTestCleanup(sqliteTmpFile) - userId, _, _, _ := makeTestUser(t, &s) + userId, _, _, _ := makeTestUser(t, &s, "", nil) // created for addition to the DB (no expiration attached) authTokenUpdate := auth.AuthToken{ @@ -181,7 +181,7 @@ func TestStoreSaveToken(t *testing.T) { s, sqliteTmpFile := StoreTestInit(t) defer StoreTestCleanup(sqliteTmpFile) - userId, _, _, _ := makeTestUser(t, &s) + userId, _, _, _ := makeTestUser(t, &s, "", nil) // Version 1 of the token for both devices // created for addition to the DB (no expiration attached) @@ -274,7 +274,7 @@ func TestStoreGetToken(t *testing.T) { s, sqliteTmpFile := StoreTestInit(t) defer StoreTestCleanup(sqliteTmpFile) - userId, _, _, _ := makeTestUser(t, &s) + userId, _, _, _ := makeTestUser(t, &s, "", nil) // created for addition to the DB (no expiration attached) authToken := auth.AuthToken{ @@ -327,7 +327,7 @@ func TestStoreTokenUTC(t *testing.T) { s, sqliteTmpFile := StoreTestInit(t) defer StoreTestCleanup(sqliteTmpFile) - userId, _, _, _ := makeTestUser(t, &s) + userId, _, _, _ := makeTestUser(t, &s, "", nil) authToken := auth.AuthToken{ Token: "seekrit-1", @@ -394,7 +394,7 @@ func TestStoreTokenEmptyFields(t *testing.T) { s, sqliteTmpFile := StoreTestInit(t) defer StoreTestCleanup(sqliteTmpFile) - tc.authToken.UserId, _, _, _ = makeTestUser(t, &s) + tc.authToken.UserId, _, _, _ = makeTestUser(t, &s, "", nil) var sqliteErr sqlite3.Error diff --git a/store/password_test.go b/store/password_test.go index 8a66abd..0c858a9 100644 --- a/store/password_test.go +++ b/store/password_test.go @@ -16,7 +16,7 @@ func TestStoreChangePasswordSuccess(t *testing.T) { s, sqliteTmpFile := StoreTestInit(t) defer StoreTestCleanup(sqliteTmpFile) - userId, email, oldPassword, _ := makeTestUser(t, &s) + userId, email, oldPassword, _ := makeTestUser(t, &s, "", nil) token := auth.AuthTokenString("my-token") _, err := s.db.Exec( @@ -114,7 +114,7 @@ func TestStoreChangePasswordErrors(t *testing.T) { s, sqliteTmpFile := StoreTestInit(t) defer StoreTestCleanup(sqliteTmpFile) - userId, email, oldPassword, oldSeed := makeTestUser(t, &s) + userId, email, oldPassword, oldSeed := makeTestUser(t, &s, "", nil) expiration := time.Now().UTC().Add(time.Hour * 24 * 14) authToken := auth.AuthToken{ Token: auth.AuthTokenString("my-token"), @@ -176,7 +176,7 @@ func TestStoreChangePasswordNoWalletSuccess(t *testing.T) { s, sqliteTmpFile := StoreTestInit(t) defer StoreTestCleanup(sqliteTmpFile) - userId, email, oldPassword, _ := makeTestUser(t, &s) + userId, email, oldPassword, _ := makeTestUser(t, &s, "", nil) token := auth.AuthTokenString("my-token") _, err := s.db.Exec( @@ -246,7 +246,7 @@ func TestStoreChangePasswordNoWalletErrors(t *testing.T) { s, sqliteTmpFile := StoreTestInit(t) defer StoreTestCleanup(sqliteTmpFile) - userId, email, oldPassword, oldSeed := makeTestUser(t, &s) + userId, email, oldPassword, oldSeed := makeTestUser(t, &s, "", nil) expiration := time.Now().UTC().Add(time.Hour * 24 * 14) authToken := auth.AuthToken{ Token: auth.AuthTokenString("my-token"), diff --git a/store/store.go b/store/store.go index ce20599..981d22d 100644 --- a/store/store.go +++ b/store/store.go @@ -343,10 +343,12 @@ func (s *Store) SetWallet(userId auth.UserId, encryptedWallet wallet.EncryptedWa func (s *Store) GetUserId(email auth.Email, password auth.Password) (userId auth.UserId, err error) { var key auth.KDFKey var salt auth.ServerSalt + var verified bool + err = s.db.QueryRow( - `SELECT user_id, key, server_salt from accounts WHERE normalized_email=?`, + `SELECT user_id, key, server_salt, verify_token="" from accounts WHERE normalized_email=?`, email.Normalize(), - ).Scan(&userId, &key, &salt) + ).Scan(&userId, &key, &salt, &verified) if err == sql.ErrNoRows { err = ErrWrongCredentials } @@ -358,6 +360,10 @@ func (s *Store) GetUserId(email auth.Email, password auth.Password) (userId auth err = ErrWrongCredentials userId = auth.UserId(0) } + if err == nil && !verified { + err = ErrNotVerified + userId = auth.UserId(0) + } return } diff --git a/store/store_test.go b/store/store_test.go index 094b52c..694eda2 100644 --- a/store/store_test.go +++ b/store/store_test.go @@ -4,6 +4,7 @@ import ( "io/ioutil" "os" "testing" + "time" "lbryio/lbry-id/auth" ) @@ -33,7 +34,12 @@ func StoreTestCleanup(tmpFile *os.File) { } } -func makeTestUser(t *testing.T, s *Store) (userId auth.UserId, email auth.Email, password auth.Password, seed auth.ClientSaltSeed) { +func makeTestUser( + t *testing.T, + s *Store, + verifyToken auth.VerifyTokenString, + verifyExpiration *time.Time, +) (userId auth.UserId, email auth.Email, password auth.Password, seed auth.ClientSaltSeed) { // email with caps to trigger possible problems email, password = auth.Email("Abc@Example.Com"), auth.Password("123") normEmail := auth.NormalizedEmail("abc@example.com") @@ -46,7 +52,7 @@ func makeTestUser(t *testing.T, s *Store) (userId auth.UserId, email auth.Email, rows, err := s.db.Query( "INSERT INTO accounts (normalized_email, email, key, server_salt, client_salt_seed, verify_token) values(?,?,?,?,?,?) returning user_id", - normEmail, email, key, salt, seed, "", + normEmail, email, key, salt, seed, verifyToken, verifyExpiration, ) if err != nil { t.Fatalf("Error setting up account: %+v", err) diff --git a/store/wallet_test.go b/store/wallet_test.go index 01d7d77..d9c27cb 100644 --- a/store/wallet_test.go +++ b/store/wallet_test.go @@ -86,7 +86,7 @@ func TestStoreInsertWallet(t *testing.T) { defer StoreTestCleanup(sqliteTmpFile) // Get a valid userId - userId, _, _, _ := makeTestUser(t, &s) + userId, _, _, _ := makeTestUser(t, &s, "", nil) // Get a wallet, come back empty expectWalletNotExists(t, &s, userId) @@ -118,7 +118,7 @@ func TestStoreUpdateWallet(t *testing.T) { defer StoreTestCleanup(sqliteTmpFile) // Get a valid userId - userId, _, _, _ := makeTestUser(t, &s) + userId, _, _, _ := makeTestUser(t, &s, "", nil) // Try to update a wallet, fail for nothing to update if err := s.updateWalletToSequence(userId, wallet.EncryptedWallet("my-enc-wallet-a"), wallet.Sequence(1), wallet.WalletHmac("my-hmac-a")); err != ErrNoWallet { @@ -174,7 +174,7 @@ func TestStoreSetWallet(t *testing.T) { defer StoreTestCleanup(sqliteTmpFile) // Get a valid userId - userId, _, _, _ := makeTestUser(t, &s) + userId, _, _, _ := makeTestUser(t, &s, "", nil) // Sequence 2 - fails - out of sequence (behind the scenes, tries to update but there's nothing there yet) if err := s.SetWallet(userId, wallet.EncryptedWallet("my-enc-wallet-a"), wallet.Sequence(2), wallet.WalletHmac("my-hmac-a")); err != ErrWrongSequence { @@ -221,7 +221,7 @@ func TestStoreGetWallet(t *testing.T) { defer StoreTestCleanup(sqliteTmpFile) // Get a valid userId - userId, _, _, _ := makeTestUser(t, &s) + userId, _, _, _ := makeTestUser(t, &s, "", nil) // GetWallet fails when there's no wallet encryptedWallet, sequence, hmac, err := s.GetWallet(userId) @@ -264,7 +264,7 @@ func TestStoreWalletEmptyFields(t *testing.T) { s, sqliteTmpFile := StoreTestInit(t) defer StoreTestCleanup(sqliteTmpFile) - userId, _, _, _ := makeTestUser(t, &s) + userId, _, _, _ := makeTestUser(t, &s, "", nil) var sqliteErr sqlite3.Error