Skip to content

Commit

Permalink
feat: push referrerURL and externalURL into sending functions
Browse files Browse the repository at this point in the history
  • Loading branch information
J0 committed Mar 25, 2024
1 parent 6e75973 commit abb86f6
Show file tree
Hide file tree
Showing 9 changed files with 25 additions and 40 deletions.
4 changes: 1 addition & 3 deletions internal/api/external.go
Original file line number Diff line number Diff line change
Expand Up @@ -382,9 +382,7 @@ func (a *API) createAccountFromExternalIdentity(tx *storage.Connection, r *http.
} else {
emailConfirmationSent := false
if decision.CandidateEmail.Email != "" {
referrer := utilities.GetReferrer(r, config)
externalURL := getExternalHost(ctx)
if terr = a.sendConfirmation(tx, user, referrer, externalURL, models.ImplicitFlow); terr != nil {
if terr = a.sendConfirmation(ctx, r, tx, user, models.ImplicitFlow); terr != nil {
if errors.Is(terr, MaxFrequencyLimitError) {
return nil, tooManyRequestsError(ErrorCodeOverEmailSendRateLimit, "For security purposes, you can only request this once every minute")
}
Expand Down
5 changes: 1 addition & 4 deletions internal/api/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/supabase/auth/internal/api/provider"
"github.com/supabase/auth/internal/models"
"github.com/supabase/auth/internal/storage"
"github.com/supabase/auth/internal/utilities"
)

func (a *API) DeleteIdentity(w http.ResponseWriter, r *http.Request) error {
Expand Down Expand Up @@ -132,9 +131,7 @@ func (a *API) linkIdentityToUser(r *http.Request, ctx context.Context, tx *stora
return nil, terr
}
if !userData.Metadata.EmailVerified {
referrer := utilities.GetReferrer(r, a.config)
externalURL := getExternalHost(ctx)
if terr := a.sendConfirmation(tx, targetUser, referrer, externalURL, models.ImplicitFlow); terr != nil {
if terr := a.sendConfirmation(ctx, r, tx, targetUser, models.ImplicitFlow); terr != nil {
if errors.Is(terr, MaxFrequencyLimitError) {
return nil, tooManyRequestsError(ErrorCodeOverSMSSendRateLimit, "For security purposes, you can only request this once every minute")
}
Expand Down
6 changes: 1 addition & 5 deletions internal/api/invite.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"github.com/supabase/auth/internal/api/provider"
"github.com/supabase/auth/internal/models"
"github.com/supabase/auth/internal/storage"
"github.com/supabase/auth/internal/utilities"
)

// InviteParams are the parameters the Signup endpoint accepts
Expand All @@ -20,7 +19,6 @@ type InviteParams struct {
func (a *API) Invite(w http.ResponseWriter, r *http.Request) error {
ctx := r.Context()
db := a.db.WithContext(ctx)
config := a.config
adminUser := getAdminUser(ctx)
params := &InviteParams{}
if err := retrieveRequestParams(r, params); err != nil {
Expand Down Expand Up @@ -81,9 +79,7 @@ func (a *API) Invite(w http.ResponseWriter, r *http.Request) error {
return terr
}

referrer := utilities.GetReferrer(r, config)
externalURL := getExternalHost(ctx)
if err := a.sendInvite(tx, user, referrer, externalURL); err != nil {
if err := a.sendInvite(ctx, r, tx, user); err != nil {
return internalServerError("Error inviting user").WithInternalError(err)
}
return nil
Expand Down
5 changes: 1 addition & 4 deletions internal/api/magic_link.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"github.com/sethvargo/go-password/password"
"github.com/supabase/auth/internal/models"
"github.com/supabase/auth/internal/storage"
"github.com/supabase/auth/internal/utilities"
)

// MagicLinkParams holds the parameters for a magic link request
Expand Down Expand Up @@ -139,9 +138,7 @@ func (a *API) MagicLink(w http.ResponseWriter, r *http.Request) error {
if terr := models.NewAuditLogEntry(r, tx, user, models.UserRecoveryRequestedAction, "", nil); terr != nil {
return terr
}
referrer := utilities.GetReferrer(r, config)
externalURL := getExternalHost(ctx)
return a.sendMagicLink(tx, user, referrer, externalURL, flowType)
return a.sendMagicLink(ctx, r, tx, user, flowType)
})
if err != nil {
if errors.Is(err, MaxFrequencyLimitError) {
Expand Down
22 changes: 16 additions & 6 deletions internal/api/mail.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package api

import (
"context"
"net/http"
"net/url"
"strings"
"time"

Expand Down Expand Up @@ -261,11 +261,13 @@ func (a *API) adminGenerateLink(w http.ResponseWriter, r *http.Request) error {
return sendJSON(w, http.StatusOK, resp)
}

func (a *API) sendConfirmation(tx *storage.Connection, u *models.User, referrerURL string, externalURL *url.URL, flowType models.FlowType) error {
func (a *API) sendConfirmation(ctx context.Context, r *http.Request, tx *storage.Connection, u *models.User, flowType models.FlowType) error {
mailer := a.Mailer()
config := a.config
otpLength := config.Mailer.OtpLength
maxFrequency := config.SMTP.MaxFrequency
referrerURL := utilities.GetReferrer(r, config)
externalURL := getExternalHost(ctx)
var err error
if err := validateSentWithinFrequencyLimit(u.ConfirmationSentAt, maxFrequency); err != nil {
return err
Expand All @@ -292,10 +294,12 @@ func (a *API) sendConfirmation(tx *storage.Connection, u *models.User, referrerU
return nil
}

func (a *API) sendInvite(tx *storage.Connection, u *models.User, referrerURL string, externalURL *url.URL) error {
func (a *API) sendInvite(ctx context.Context, r *http.Request, tx *storage.Connection, u *models.User) error {
mailer := a.Mailer()
config := a.config
otpLength := config.Mailer.OtpLength
referrerURL := utilities.GetReferrer(r, config)
externalURL := getExternalHost(ctx)
var err error
oldToken := u.ConfirmationToken
otp, err := crypto.GenerateOtp(otpLength)
Expand All @@ -319,10 +323,12 @@ func (a *API) sendInvite(tx *storage.Connection, u *models.User, referrerURL str
return nil
}

func (a *API) sendPasswordRecovery(tx *storage.Connection, u *models.User, referrerURL string, externalURL *url.URL, flowType models.FlowType) error {
func (a *API) sendPasswordRecovery(ctx context.Context, r *http.Request, tx *storage.Connection, u *models.User, flowType models.FlowType) error {
config := a.config
maxFrequency := config.SMTP.MaxFrequency
otpLength := config.Mailer.OtpLength
referrerURL := utilities.GetReferrer(r, config)
externalURL := getExternalHost(ctx)
mailer := a.Mailer()
var err error
if err := validateSentWithinFrequencyLimit(u.RecoverySentAt, maxFrequency); err != nil {
Expand Down Expand Up @@ -383,11 +389,13 @@ func (a *API) sendReauthenticationOtp(tx *storage.Connection, u *models.User) er
return nil
}

func (a *API) sendMagicLink(tx *storage.Connection, u *models.User, referrerURL string, externalURL *url.URL, flowType models.FlowType) error {
func (a *API) sendMagicLink(ctx context.Context, r *http.Request, tx *storage.Connection, u *models.User, flowType models.FlowType) error {
mailer := a.Mailer()
config := a.config
otpLength := config.Mailer.OtpLength
maxFrequency := config.SMTP.MaxFrequency
referrerURL := utilities.GetReferrer(r, config)
externalURL := getExternalHost(ctx)
var err error
// since Magic Link is just a recovery with a different template and behaviour
// around new users we will reuse the recovery db timer to prevent potential abuse
Expand Down Expand Up @@ -419,14 +427,16 @@ func (a *API) sendMagicLink(tx *storage.Connection, u *models.User, referrerURL
}

// sendEmailChange sends out an email change token to the new email.
func (a *API) sendEmailChange(tx *storage.Connection, u *models.User, email, referrerURL string, externalURL *url.URL, flowType models.FlowType) error {
func (a *API) sendEmailChange(ctx context.Context, r *http.Request, tx *storage.Connection, u *models.User, email string, flowType models.FlowType) error {
config := a.config
otpLength := config.Mailer.OtpLength
var err error
mailer := a.Mailer()
if err := validateSentWithinFrequencyLimit(u.EmailChangeSentAt, config.SMTP.MaxFrequency); err != nil {
return err
}
referrerURL := utilities.GetReferrer(r, config)
externalURL := getExternalHost(ctx)

otpNew, err := crypto.GenerateOtp(otpLength)
if err != nil {
Expand Down
6 changes: 1 addition & 5 deletions internal/api/recover.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (

"github.com/supabase/auth/internal/models"
"github.com/supabase/auth/internal/storage"
"github.com/supabase/auth/internal/utilities"
)

// RecoverParams holds the parameters for a password recovery request
Expand Down Expand Up @@ -34,7 +33,6 @@ func (p *RecoverParams) Validate() error {
func (a *API) Recover(w http.ResponseWriter, r *http.Request) error {
ctx := r.Context()
db := a.db.WithContext(ctx)
config := a.config
params := &RecoverParams{}
if err := retrieveRequestParams(r, params); err != nil {
return err
Expand Down Expand Up @@ -66,9 +64,7 @@ func (a *API) Recover(w http.ResponseWriter, r *http.Request) error {
if terr := models.NewAuditLogEntry(r, tx, user, models.UserRecoveryRequestedAction, "", nil); terr != nil {
return terr
}
referrer := utilities.GetReferrer(r, config)
externalURL := getExternalHost(ctx)
return a.sendPasswordRecovery(tx, user, referrer, externalURL, flowType)
return a.sendPasswordRecovery(ctx, r, tx, user, flowType)
})
if err != nil {
if errors.Is(err, MaxFrequencyLimitError) {
Expand Down
7 changes: 2 additions & 5 deletions internal/api/resend.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"github.com/supabase/auth/internal/conf"
"github.com/supabase/auth/internal/models"
"github.com/supabase/auth/internal/storage"
"github.com/supabase/auth/internal/utilities"
)

// ResendConfirmationParams holds the parameters for a resend request
Expand Down Expand Up @@ -115,16 +114,14 @@ func (a *API) Resend(w http.ResponseWriter, r *http.Request) error {
}

messageID := ""
referrer := utilities.GetReferrer(r, config)
externalURL := getExternalHost(ctx)
err = db.Transaction(func(tx *storage.Connection) error {
switch params.Type {
case signupVerification:
if terr := models.NewAuditLogEntry(r, tx, user, models.UserConfirmationRequestedAction, "", nil); terr != nil {
return terr
}
// PKCE not implemented yet
return a.sendConfirmation(tx, user, referrer, externalURL, models.ImplicitFlow)
return a.sendConfirmation(ctx, r, tx, user, models.ImplicitFlow)
case smsVerification:
if terr := models.NewAuditLogEntry(r, tx, user, models.UserRecoveryRequestedAction, "", nil); terr != nil {
return terr
Expand All @@ -139,7 +136,7 @@ func (a *API) Resend(w http.ResponseWriter, r *http.Request) error {
}
messageID = mID
case emailChangeVerification:
return a.sendEmailChange(tx, user, user.EmailChange, referrer, externalURL, models.ImplicitFlow)
return a.sendEmailChange(ctx, r, tx, user, user.EmailChange, models.ImplicitFlow)
case phoneChangeVerification:
smsProvider, terr := sms_provider.GetSmsProvider(*config)
if terr != nil {
Expand Down
5 changes: 1 addition & 4 deletions internal/api/signup.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"github.com/supabase/auth/internal/metering"
"github.com/supabase/auth/internal/models"
"github.com/supabase/auth/internal/storage"
"github.com/supabase/auth/internal/utilities"
)

// SignupParams are the parameters the Signup endpoint accepts
Expand Down Expand Up @@ -234,7 +233,6 @@ func (a *API) Signup(w http.ResponseWriter, r *http.Request) error {
return internalServerError("Database error updating user").WithInternalError(terr)
}
} else {
referrer := utilities.GetReferrer(r, config)
if terr = models.NewAuditLogEntry(r, tx, user, models.UserConfirmationRequestedAction, "", map[string]interface{}{
"provider": params.Provider,
}); terr != nil {
Expand All @@ -246,8 +244,7 @@ func (a *API) Signup(w http.ResponseWriter, r *http.Request) error {
return terr
}
}
externalURL := getExternalHost(ctx)
if terr = a.sendConfirmation(tx, user, referrer, externalURL, flowType); terr != nil {
if terr = a.sendConfirmation(ctx, r, tx, user, flowType); terr != nil {
if errors.Is(terr, MaxFrequencyLimitError) {
now := time.Now()
left := user.ConfirmationSentAt.Add(config.SMTP.MaxFrequency).Sub(now) / time.Second
Expand Down
5 changes: 1 addition & 4 deletions internal/api/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/supabase/auth/internal/api/sms_provider"
"github.com/supabase/auth/internal/models"
"github.com/supabase/auth/internal/storage"
"github.com/supabase/auth/internal/utilities"
)

// UserUpdateParams parameters for updating a user
Expand Down Expand Up @@ -194,7 +193,6 @@ func (a *API) UserUpdate(w http.ResponseWriter, r *http.Request) error {
}

if params.Email != "" && params.Email != user.GetEmail() {
referrer := utilities.GetReferrer(r, config)
flowType := getFlowFromChallenge(params.CodeChallenge)
if isPKCEFlow(flowType) {
_, terr := generateFlowState(tx, models.EmailChange.String(), models.EmailChange, params.CodeChallengeMethod, params.CodeChallenge, &user.ID)
Expand All @@ -203,8 +201,7 @@ func (a *API) UserUpdate(w http.ResponseWriter, r *http.Request) error {
}

}
externalURL := getExternalHost(ctx)
if terr = a.sendEmailChange(tx, user, params.Email, referrer, externalURL, flowType); terr != nil {
if terr = a.sendEmailChange(ctx, r, tx, user, params.Email, flowType); terr != nil {
if errors.Is(terr, MaxFrequencyLimitError) {
return tooManyRequestsError(ErrorCodeOverEmailSendRateLimit, "For security purposes, you can only request this once every 60 seconds")
}
Expand Down

0 comments on commit abb86f6

Please sign in to comment.