GitHub user Neilk1021 created a discussion: Email verification (Flag)

https://github.com/user-attachments/assets/4a5cb381-a4bc-459a-a214-d0ddddd3a581

### Problem
Currently anyone can claim any email when registering, there is nothing 
stopping me from taking `[email protected]`, I have to give 0 evidence I own that 
account. This is made worse by the fact that email is identity for much of 
Texera. Besides the obvious security issues and annoyances this presents, 
theres also the issue of the user mistakingly mistyping their email and not 
being aware of it. 

### Proposed solution. 
When someone registers, the backend derives a one-time code, emails it to the 
address they typed, and creates nothing. The sign-up form then asks for that 
code and re-submits it along with the same fields. The backend re-derives the 
code and compares: if they match, the address is proven and the account is 
created (as `INACTIVE`, pending admin approval, exactly as before).             
                                                                               

The code is *derived*, not stored. There is no pending-registration table, no 
cleanup job, and nothing about an unfinished signup is written down anywhere.   
                     

### How it works 

1. `POST /auth/register` validates the fields, pre-checks that the handle and 
address are free, mails a code, and returns `{ accessToken: null, 
verificationRequired: true }`. Nothing is written.                              
                                             
2. The form re-submits the same fields plus the code to `POST 
/auth/register/verify`.                                                         
                            
3. The code is a truncated HMAC-SHA256 over `purpose | scope | address | 
time-step`, keyed by a value derived from the JWT secret (RFC 4226-style 
dynamic truncation, as TOTP does). Checking means re-deriving it for the 
current and previous step and comparing in constant time.                       
                                                                
4. On a match, the account is created inside the transaction that runs the 
authoritative uniqueness checks; the pre-checks in step 1 are a courtesy, not 
the guard.                                                                      
                                 
                                                                                
                                                                                
            
The password travels again in step 2 rather than being held server-side. That 
is what makes the flow stateless, and it means no password or hash is ever 
stored, mailed, or parked in the browser while a signup is pending.             
                                                                                
                                      

Where the flag is off, `register` behaves exactly as it does today: one call, 
account created, token issued.               

### Questions / Considerations
1. Is the stateless verification a good fit? I proposed it because after the 
immediate period in which they're used they effectively become junk data. This 
solution has no table, no cleanup, and survives across restarts, however, we 
can't implement single use invalidation or a proper audit trail. Is that 
tradeoff acceptable?

2. Should this feature flag be enabled or disabled by default? 
This feature doesn't work without setting up `USER_SYS_GOOGLE_SMTP_`, which 
will vary from deployment to deployment. Therefore if this is enabled by 
default theres a high probability people improperly set up the deployment and 
don't provide this field breaking verification.

GitHub link: https://github.com/apache/texera/discussions/7818

----
This is an automatically sent email for [email protected].
To unsubscribe, please send an email to: [email protected]

Reply via email to