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

Method MagicLink

internal/api/magic_link.go:41–149  ·  view source on GitHub ↗

MagicLink sends a recovery email

(w http.ResponseWriter, r *http.Request)

Source from the content-addressed store, hash-verified

39
40// MagicLink sends a recovery email
41func (a *API) MagicLink(w http.ResponseWriter, r *http.Request) error {
42 ctx := r.Context()
43 db := a.db.WithContext(ctx)
44 config := a.config
45
46 if !config.External.Email.Enabled {
47 return apierrors.NewUnprocessableEntityError(apierrors.ErrorCodeEmailProviderDisabled, "Email logins are disabled")
48 }
49
50 if !config.External.Email.MagicLinkEnabled {
51 return apierrors.NewUnprocessableEntityError(apierrors.ErrorCodeEmailProviderDisabled, "Login with magic link is disabled")
52 }
53
54 params := &MagicLinkParams{}
55 jsonDecoder := json.NewDecoder(r.Body)
56 err := jsonDecoder.Decode(params)
57 if err != nil {
58 return apierrors.NewBadRequestError(apierrors.ErrorCodeBadJSON, "Could not read verification params: %v", err).WithInternalError(err)
59 }
60
61 if err := params.Validate(a); err != nil {
62 return err
63 }
64
65 if params.Data == nil {
66 params.Data = make(map[string]interface{})
67 }
68
69 flowType := getFlowFromChallenge(params.CodeChallenge)
70
71 var isNewUser bool
72 aud := a.requestAud(ctx, r)
73 user, err := models.FindUserByEmailAndAudience(db, params.Email, aud)
74 if err != nil {
75 if models.IsNotFoundError(err) {
76 isNewUser = true
77 } else {
78 return apierrors.NewInternalServerError("Database error finding user").WithInternalError(err)
79 }
80 }
81 if user != nil {
82 isNewUser = !user.IsConfirmed()
83 }
84 if isNewUser {
85 // User either doesn't exist or hasn't completed the signup process.
86 // Sign them up with temporary password.
87 password := crypto.GeneratePassword(config.Password.RequiredCharacters, 33)
88
89 signUpParams := &SignupParams{
90 Email: params.Email,
91 Password: password,
92 Data: params.Data,
93 CodeChallengeMethod: params.CodeChallengeMethod,
94 CodeChallenge: params.CodeChallenge,
95 }
96 newBodyContent, err := json.Marshal(signUpParams)
97 if err != nil {
98 // SignupParams must always be marshallable

Callers 1

OtpMethod · 0.95

Calls 15

ValidateMethod · 0.95
requestAudMethod · 0.95
SignupMethod · 0.95
sendMagicLinkMethod · 0.95
NewBadRequestErrorFunction · 0.92
IsNotFoundErrorFunction · 0.92
NewInternalServerErrorFunction · 0.92
GeneratePasswordFunction · 0.92
NewAuditLogEntryFunction · 0.92
getFlowFromChallengeFunction · 0.85

Tested by

no test coverage detected