feat: add im auth verification flows

This commit is contained in:
richjohnrambo
2026-08-12 00:20:27 +08:00
parent 1ffcb85bee
commit d239e37f56
16 changed files with 2030 additions and 22 deletions
+60
View File
@@ -3,6 +3,7 @@ package main
import (
"container/heap"
"math/rand"
"strings"
"time"
"slices"
@@ -383,6 +384,19 @@ func addCreds(tenantID types.TenantID, uid types.Uid, creds []MsgCredClient, ext
continue
}
if cr.Response != "" {
if value, ok, err := consumeProductVerificationCred(tenantID, uid, cr, vld.PreCheck); ok || err != nil {
if err != nil {
return nil, nil, err
}
validated = append(validated, cr.Method)
if globals.validators[cr.Method].addToTags {
extraTags = append(extraTags, cr.Method+":"+value)
}
continue
}
}
isNew, err := vld.Request(tenantID, uid, cr.Value, lang, cr.Response, tmpToken)
if err != nil {
return nil, nil, err
@@ -413,6 +427,52 @@ func addCreds(tenantID types.TenantID, uid types.Uid, creds []MsgCredClient, ext
return validated, extraTags, nil
}
func consumeProductVerificationCred(tenantID types.TenantID, uid types.Uid, cr *MsgCredClient,
preCheck func(string, map[string]any) (string, error)) (string, bool, error) {
challengeID, _ := cr.Params["challenge_id"].(string)
challengeID = strings.TrimSpace(challengeID)
if challengeID == "" {
return "", false, nil
}
if store.Verifications == nil {
return "", true, types.ErrInternal
}
normalized, err := preCheck(cr.Value, cr.Params)
if err != nil {
return "", true, err
}
value := strings.TrimPrefix(normalized, cr.Method+":")
vc, err := store.Verifications.Get(tenantID, challengeID)
if err != nil {
return "", true, err
}
if vc.Scene != "register" || vc.State != types.VerificationStateVerified || vc.PhoneHash == "" {
return "", true, types.ErrInvalidResponse
}
tokenHash := hashIMSecret(tenantID, vc.Scene, vc.ChallengeID, vc.PhoneHash, cr.Response)
if vc.VerificationTokenHash == nil || *vc.VerificationTokenHash != tokenHash {
return "", true, types.ErrInvalidResponse
}
now := time.Now().UTC().Round(time.Millisecond)
if !now.Before(vc.ExpiresAt) {
return "", true, types.ErrExpired
}
if err := store.Verifications.Consume(tenantID, vc.ChallengeID, tokenHash, now); err != nil {
return "", true, err
}
_, err = store.Users.UpsertCred(tenantID, &types.Credential{
ObjHeader: types.ObjHeader{CreatedAt: now, UpdatedAt: now},
User: uid.String(),
Method: cr.Method,
Value: value,
Done: true,
})
if err != nil {
return "", true, err
}
return value, true, nil
}
// validatedCreds returns the list of validated credentials including those validated in this call.
// Returns all validated methods including those validated earlier and now.
// Returns either a full set of tags or nil for tags if tags are unchanged.