@@ -34,6 +34,12 @@ class AuthProvider(metaclass=SupportsMeta):
34
34
#: Useful to reliably retrieve identifier data in applications that use
35
35
#: multiple auth providers.
36
36
identifier_field_name = None
37
+ #: The rate limiter used for login attempts in local auth providers.
38
+ #: This should be an instance of :class:`~flask_limiter.Limiter`.
39
+ rate_limiter = None
40
+ #: The rate limiter used for login attempts bound to a specific user
41
+ #: This should be an instance of :class:`~flask_limiter.Limiter`.
42
+ rate_limiter_user = None
37
43
38
44
def __init__ (self , multipass , name , settings ):
39
45
self .multipass = multipass
@@ -50,6 +56,13 @@ def is_external(self):
50
56
"""
51
57
return self .login_form is None
52
58
59
+ @property
60
+ def is_rate_limited (self ):
61
+ """True if rate limiters are set for local auth provider."""
62
+ if self .is_external :
63
+ return False
64
+ return self .rate_limiter is not None or self .rate_limiter_user is not None
65
+
53
66
def process_local_login (self , data ): # pragma: no cover
54
67
"""Handles the login process based on form data.
55
68
@@ -117,5 +130,14 @@ def process_logout(self, return_url):
117
130
"""
118
131
return None
119
132
133
+ def notify_failed_login (self , identifier = None ):
134
+ """Notify the provider about a failed login attempt."""
135
+ if not self .is_rate_limited :
136
+ return
137
+ if identifier and self .rate_limiter_user :
138
+ self .rate_limiter_user .hit (identifier )
139
+ elif self .rate_limiter :
140
+ self .rate_limiter .hit ()
141
+
120
142
def __repr__ (self ):
121
143
return f'<{ type (self ).__name__ } ({ self .name } )>'
0 commit comments