103 lines
2.9 KiB
Go
103 lines
2.9 KiB
Go
package api
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/didip/tollbooth/v5"
|
|
"github.com/didip/tollbooth/v5/limiter"
|
|
"github.com/supabase/auth/internal/conf"
|
|
"github.com/supabase/auth/internal/ratelimit"
|
|
)
|
|
|
|
type Option interface {
|
|
apply(*API)
|
|
}
|
|
|
|
type LimiterOptions struct {
|
|
Email ratelimit.Limiter
|
|
Phone ratelimit.Limiter
|
|
|
|
Signups *limiter.Limiter
|
|
AnonymousSignIns *limiter.Limiter
|
|
Recover *limiter.Limiter
|
|
Resend *limiter.Limiter
|
|
MagicLink *limiter.Limiter
|
|
Otp *limiter.Limiter
|
|
Token *limiter.Limiter
|
|
Verify *limiter.Limiter
|
|
User *limiter.Limiter
|
|
FactorVerify *limiter.Limiter
|
|
FactorChallenge *limiter.Limiter
|
|
SSO *limiter.Limiter
|
|
SAMLAssertion *limiter.Limiter
|
|
}
|
|
|
|
func (lo *LimiterOptions) apply(a *API) { a.limiterOpts = lo }
|
|
|
|
func NewLimiterOptions(gc *conf.GlobalConfiguration) *LimiterOptions {
|
|
o := &LimiterOptions{}
|
|
|
|
o.Email = ratelimit.New(gc.RateLimitEmailSent)
|
|
o.Phone = ratelimit.New(gc.RateLimitSmsSent)
|
|
|
|
o.AnonymousSignIns = tollbooth.NewLimiter(gc.RateLimitAnonymousUsers/(60*60),
|
|
&limiter.ExpirableOptions{
|
|
DefaultExpirationTTL: time.Hour,
|
|
}).SetBurst(int(gc.RateLimitAnonymousUsers)).SetMethods([]string{"POST"})
|
|
|
|
o.Token = tollbooth.NewLimiter(gc.RateLimitTokenRefresh/(60*5),
|
|
&limiter.ExpirableOptions{
|
|
DefaultExpirationTTL: time.Hour,
|
|
}).SetBurst(30)
|
|
|
|
o.Verify = tollbooth.NewLimiter(gc.RateLimitVerify/(60*5),
|
|
&limiter.ExpirableOptions{
|
|
DefaultExpirationTTL: time.Hour,
|
|
}).SetBurst(30)
|
|
|
|
o.User = tollbooth.NewLimiter(gc.RateLimitOtp/(60*5),
|
|
&limiter.ExpirableOptions{
|
|
DefaultExpirationTTL: time.Hour,
|
|
}).SetBurst(30)
|
|
|
|
o.FactorVerify = tollbooth.NewLimiter(gc.MFA.RateLimitChallengeAndVerify/60,
|
|
&limiter.ExpirableOptions{
|
|
DefaultExpirationTTL: time.Minute,
|
|
}).SetBurst(30)
|
|
|
|
o.FactorChallenge = tollbooth.NewLimiter(gc.MFA.RateLimitChallengeAndVerify/60,
|
|
&limiter.ExpirableOptions{
|
|
DefaultExpirationTTL: time.Minute,
|
|
}).SetBurst(30)
|
|
|
|
o.SSO = tollbooth.NewLimiter(gc.RateLimitSso/(60*5),
|
|
&limiter.ExpirableOptions{
|
|
DefaultExpirationTTL: time.Hour,
|
|
}).SetBurst(30)
|
|
|
|
o.SAMLAssertion = tollbooth.NewLimiter(gc.SAML.RateLimitAssertion/(60*5),
|
|
&limiter.ExpirableOptions{
|
|
DefaultExpirationTTL: time.Hour,
|
|
}).SetBurst(30)
|
|
|
|
o.Signups = tollbooth.NewLimiter(gc.RateLimitOtp/(60*5),
|
|
&limiter.ExpirableOptions{
|
|
DefaultExpirationTTL: time.Hour,
|
|
}).SetBurst(30)
|
|
|
|
// These all use the OTP limit per 5 min with 1hour ttl and burst of 30.
|
|
o.Recover = newLimiterPer5mOver1h(gc.RateLimitOtp)
|
|
o.Resend = newLimiterPer5mOver1h(gc.RateLimitOtp)
|
|
o.MagicLink = newLimiterPer5mOver1h(gc.RateLimitOtp)
|
|
o.Otp = newLimiterPer5mOver1h(gc.RateLimitOtp)
|
|
return o
|
|
}
|
|
|
|
func newLimiterPer5mOver1h(rate float64) *limiter.Limiter {
|
|
freq := rate / (60 * 5)
|
|
lim := tollbooth.NewLimiter(freq, &limiter.ExpirableOptions{
|
|
DefaultExpirationTTL: time.Hour,
|
|
}).SetBurst(30)
|
|
return lim
|
|
}
|