11import * as http from "http"
2+ import * as limiter from "limiter"
23import * as querystring from "querystring"
34import { HttpCode , HttpError } from "../../common/http"
45import { AuthType , HttpProvider , HttpResponse , Route } from "../http"
@@ -48,6 +49,8 @@ export class LoginHttpProvider extends HttpProvider {
4849 return this . replaceTemplates ( route , response )
4950 }
5051
52+ private limiter = new RateLimiter ( )
53+
5154 /**
5255 * Try logging in. On failure, show the login page with an error.
5356 */
@@ -59,6 +62,10 @@ export class LoginHttpProvider extends HttpProvider {
5962 }
6063
6164 try {
65+ if ( ! this . limiter . try ( ) ) {
66+ throw new Error ( "Login rate limited!" )
67+ }
68+
6269 const data = await this . getData ( request )
6370 const payload = data ? querystring . parse ( data ) : { }
6471 return await this . login ( payload , route , request )
@@ -69,6 +76,8 @@ export class LoginHttpProvider extends HttpProvider {
6976
7077 /**
7178 * Return a cookie if the user is authenticated otherwise throw an error.
79+ *
80+ * Only allows max 3 logins a second.
7281 */
7382 private async login ( payload : LoginPayload , route : Route , request : http . IncomingMessage ) : Promise < HttpResponse > {
7483 const password = this . authenticated ( request , {
@@ -108,3 +117,18 @@ export class LoginHttpProvider extends HttpProvider {
108117 throw new Error ( "Missing password" )
109118 }
110119}
120+
121+ // RateLimiter wraps around the limiter library for logins.
122+ // It allows 2 logins every minute and 12 logins every hour.
123+ class RateLimiter {
124+ private readonly minuteLimiter = new limiter . RateLimiter ( 2 , "minute" )
125+ private readonly hourLimiter = new limiter . RateLimiter ( 12 , "hour" )
126+
127+ public try ( ) : boolean {
128+ console . info ( this . minuteLimiter . getTokensRemaining ( ) , this . hourLimiter . getTokensRemaining ( ) )
129+ if ( this . minuteLimiter . tryRemoveTokens ( 1 ) ) {
130+ return true
131+ }
132+ return this . hourLimiter . tryRemoveTokens ( 1 )
133+ }
134+ }
0 commit comments