MCPcopy
hub / github.com/supabase/auth / sendMagicLink

Method sendMagicLink

internal/api/mail.go:479–520  ·  view source on GitHub ↗
(r *http.Request, tx *storage.Connection, u *models.User, flowType models.FlowType)

Source from the content-addressed store, hash-verified

477}
478
479func (a *API) sendMagicLink(r *http.Request, tx *storage.Connection, u *models.User, flowType models.FlowType) error {
480 var err error
481 config := a.config
482 otpLength := config.Mailer.OtpLength
483
484 // since Magic Link is just a recovery with a different template and behaviour
485 // around new users we will reuse the recovery db timer to prevent potential abuse
486 if err := validateSentWithinFrequencyLimit(u.RecoverySentAt, config.SMTP.MaxFrequency); err != nil {
487 return err
488 }
489
490 oldToken := u.RecoveryToken
491 otp := crypto.GenerateOtp(otpLength)
492
493 token := crypto.GenerateTokenHash(u.GetEmail(), otp)
494 u.RecoveryToken = addFlowPrefixToToken(token, flowType)
495
496 now := time.Now()
497 if err = a.sendEmail(r, tx, u, sendEmailParams{
498 emailActionType: mail.MagicLinkVerification,
499 otp: otp,
500 tokenHashWithPrefix: u.RecoveryToken,
501 }); err != nil {
502 u.RecoveryToken = oldToken
503 if errors.Is(err, EmailRateLimitExceeded) {
504 return apierrors.NewTooManyRequestsError(apierrors.ErrorCodeOverEmailSendRateLimit, "%s", EmailRateLimitExceeded.Error())
505 } else if herr, ok := err.(*HTTPError); ok {
506 return herr
507 }
508 return apierrors.NewInternalServerError("Error sending magic link email").WithInternalError(err)
509 }
510 u.RecoverySentAt = &now
511 if err := tx.UpdateOnly(u, "recovery_token", "recovery_sent_at"); err != nil {
512 return apierrors.NewInternalServerError("Error sending magic link email").WithInternalError(errors.Wrap(err, "Database error updating user for recovery"))
513 }
514
515 if err := models.CreateOneTimeToken(tx, u.ID, u.GetEmail(), u.RecoveryToken, models.RecoveryToken); err != nil {
516 return apierrors.NewInternalServerError("Error sending magic link email").WithInternalError(errors.Wrap(err, "Database error creating recovery token"))
517 }
518
519 return nil
520}
521
522// sendEmailChange sends out an email change token to the new email.
523func (a *API) sendEmailChange(r *http.Request, tx *storage.Connection, u *models.User, email string, flowType models.FlowType) error {

Callers 1

MagicLinkMethod · 0.95

Calls 14

sendEmailMethod · 0.95
GenerateOtpFunction · 0.92
GenerateTokenHashFunction · 0.92
NewTooManyRequestsErrorFunction · 0.92
NewInternalServerErrorFunction · 0.92
CreateOneTimeTokenFunction · 0.92
addFlowPrefixToTokenFunction · 0.85
NowMethod · 0.80
UpdateOnlyMethod · 0.80
GetEmailMethod · 0.45
IsMethod · 0.45

Tested by

no test coverage detected