fix: use fixed code for registration verification

This commit is contained in:
richjohnrambo
2026-08-19 16:52:20 +08:00
parent 219ecadf4c
commit 405dad2eef
2 changed files with 20 additions and 15 deletions
+8 -5
View File
@@ -664,12 +664,15 @@ func serveIMVerificationCodes(wrt http.ResponseWriter, req *http.Request) {
writeIMError(wrt, req, http.StatusInternalServerError, 90000, imReasonInternal, "internal error", nil) writeIMError(wrt, req, http.StatusInternalServerError, 90000, imReasonInternal, "internal error", nil)
return return
} }
code, err := randomIMNumericCode(imVerificationCodeLength) code := "123456"
if err != nil { if scene != "register" {
writeIMError(wrt, req, http.StatusInternalServerError, 90000, imReasonInternal, "internal error", nil) code, err = randomIMNumericCode(imVerificationCodeLength)
return if err != nil {
writeIMError(wrt, req, http.StatusInternalServerError, 90000, imReasonInternal, "internal error", nil)
return
}
} }
deliveryEnabled := scene != "register" || registrationSMSEnabled(now) deliveryEnabled := scene != "register" && registrationSMSEnabled(now)
vc := &types.VerificationCode{ vc := &types.VerificationCode{
TenantID: tenant.ID, TenantID: tenant.ID,
ChallengeID: challengeID, ChallengeID: challengeID,
+12 -10
View File
@@ -1251,12 +1251,8 @@ func TestServeIMVerificationCodesCreatesChallenge(t *testing.T) {
verifications := &testVerificationStore{} verifications := &testVerificationStore{}
store.Verifications = verifications store.Verifications = verifications
setRegistrationSMSConfigForTest(true) setRegistrationSMSConfigForTest(true)
var deliveredCode string
sendIMVerificationCode = func(_ types.TenantID, recipient, _, scene, code string) error { sendIMVerificationCode = func(_ types.TenantID, recipient, _, scene, code string) error {
if recipient != "+8613800138000" || scene != "register" { t.Fatalf("registration SMS sender must not be called before SMS integration: recipient=%q scene=%q code=%q", recipient, scene, code)
t.Fatalf("unexpected delivery: recipient=%q scene=%q", recipient, scene)
}
deliveredCode = code
return nil return nil
} }
defer func() { defer func() {
@@ -1286,10 +1282,9 @@ func TestServeIMVerificationCodesCreatesChallenge(t *testing.T) {
if verifications.created.CodeHash == "" || strings.Contains(rec.Body.String(), verifications.created.CodeHash) { if verifications.created.CodeHash == "" || strings.Contains(rec.Body.String(), verifications.created.CodeHash) {
t.Fatalf("code hash missing or leaked: %#v body=%s", verifications.created, rec.Body.String()) t.Fatalf("code hash missing or leaked: %#v body=%s", verifications.created, rec.Body.String())
} }
if len(deliveredCode) != imVerificationCodeLength || if verifications.created.CodeHash != hashIMSecret(7, "register", verifications.created.ChallengeID,
verifications.created.CodeHash != hashIMSecret(7, "register", verifications.created.ChallengeID, verifications.created.PhoneHash, "123456") {
verifications.created.PhoneHash, deliveredCode) { t.Fatalf("stored challenge does not match fixed registration code")
t.Fatalf("stored challenge does not match delivered code %q", deliveredCode)
} }
resp := decodeIMHTTPResponse(t, rec) resp := decodeIMHTTPResponse(t, rec)
data := resp.Data.(map[string]any) data := resp.Data.(map[string]any)
@@ -1376,21 +1371,28 @@ func TestServeIMPasswordResetCodeFindsPhoneWithoutTelCredential(t *testing.T) {
func TestServeIMVerificationCodesExpiresChallengeOnDeliveryFailure(t *testing.T) { func TestServeIMVerificationCodesExpiresChallengeOnDeliveryFailure(t *testing.T) {
oldTenants := store.Tenants oldTenants := store.Tenants
oldVerifications := store.Verifications oldVerifications := store.Verifications
oldUsers := store.Users
oldSender := sendIMVerificationCode oldSender := sendIMVerificationCode
store.Tenants = testTenantStore{tenant: &types.Tenant{ID: 7, Code: "acme", State: types.TenantStateActive}} store.Tenants = testTenantStore{tenant: &types.Tenant{ID: 7, Code: "acme", State: types.TenantStateActive}}
verifications := &testVerificationStore{} verifications := &testVerificationStore{}
store.Verifications = verifications store.Verifications = verifications
setRegistrationSMSConfigForTest(true) setRegistrationSMSConfigForTest(true)
ctrl := gomock.NewController(t)
defer ctrl.Finish()
users := mock_store.NewMockUsersPersistenceInterface(ctrl)
users.EXPECT().GetByPhone(types.TenantID(7), "+8613800138000").Return(types.Uid(42), nil)
store.Users = users
sendIMVerificationCode = func(_ types.TenantID, _, _, _, _ string) error { return types.ErrInternal } sendIMVerificationCode = func(_ types.TenantID, _, _, _, _ string) error { return types.ErrInternal }
defer func() { defer func() {
store.Tenants = oldTenants store.Tenants = oldTenants
store.Verifications = oldVerifications store.Verifications = oldVerifications
store.Users = oldUsers
sendIMVerificationCode = oldSender sendIMVerificationCode = oldSender
resetRegistrationSMSConfigForTest() resetRegistrationSMSConfigForTest()
}() }()
req := httptest.NewRequest(http.MethodPost, "/v1/im/auth/verification-codes", req := httptest.NewRequest(http.MethodPost, "/v1/im/auth/verification-codes",
bytes.NewBufferString(`{"scene":"register","phone":"+8613800138000"}`)) bytes.NewBufferString(`{"scene":"reset_password","phone":"+8613800138000"}`))
req.Header.Set("X-Tinode-APIKey", makeTestAPIKey(t)) req.Header.Set("X-Tinode-APIKey", makeTestAPIKey(t))
req.Header.Set("X-Tenant-Code", "acme") req.Header.Set("X-Tenant-Code", "acme")
rec := httptest.NewRecorder() rec := httptest.NewRecorder()