package magiclink import ( "crypto/rand" "encoding/base64" "sync" "time" "github.com/spf13/viper" ) type Token struct { Email string ExpiresAt time.Time } var ( store = sync.Map{} ) // Generate magic token func NewMagicToken(email string) (string, error) { b := make([]byte, 32) if _, err := rand.Read(b); err != nil { return "", err } token := base64.RawURLEncoding.EncodeToString(b) store.Store(token, Token{ Email: email, ExpiresAt: time.Now().Add(viper.GetDuration("ttl.magic_link_ttl")), }) return token, nil } // Verify magic token func VerifyMagicToken(token string) (string, bool) { val, ok := store.Load(token) if !ok { return "", false } t := val.(Token) if time.Now().After(t.ExpiresAt) { store.Delete(token) return "", false } store.Delete(token) return t.Email, true }