Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add throttle page #8

Merged
merged 7 commits into from
Jul 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ class OAuthController(
model: Model,
): Mono<Rendering> {
val loginFailed = request.queryParams.containsKey("login_failed")
val loginThrottled = request.queryParams.containsKey("login_throttled")
model.addAttribute("loginFailed", loginFailed)
model.addAttribute("loginThrottled", loginThrottled)
model.addAttribute("challenge", challenge)
model.addAttribute("passwordResetUrl", fafProperties.passwordResetUrl)
model.addAttribute("registerAccountUrl", fafProperties.registerAccountUrl)
Expand Down Expand Up @@ -64,7 +66,14 @@ class OAuthController(
when (it) {
is SuccessfulLogin -> redirect(response, it.redirectTo)
is UserBanned -> redirect(response, it.redirectTo)
is LoginThrottlingActive -> redirect(response, it.redirectTo)
is LoginThrottlingActive -> redirect(
response,
UriComponentsBuilder.fromUri(request.uri)
.queryParam("login_challenge", challenge)
.queryParam("login_throttled")
.build()
.toUriString()
)
is UserOrCredentialsMismatch -> redirect(
response,
UriComponentsBuilder.fromUri(request.uri)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ data class SecurityProperties(
)

sealed class LoginResult {
data class LoginThrottlingActive(val redirectTo: String) : LoginResult()
object LoginThrottlingActive : LoginResult()
object UserOrCredentialsMismatch : LoginResult()
data class SuccessfulLogin(val redirectTo: String) : LoginResult()
data class UserBanned(val redirectTo: String, val ban: Ban) : LoginResult()
Expand Down Expand Up @@ -90,8 +90,7 @@ class UserService(
): Mono<LoginResult> = checkLoginThrottlingRequired(ip)
.flatMap { throttlingRequired ->
if (throttlingRequired) {
hydraService.rejectLoginRequest(challenge, GenericError(HYDRA_ERROR_LOGIN_THROTTLED))
.map { LoginResult.LoginThrottlingActive(it.redirectTo) }
Mono.just(LoginResult.LoginThrottlingActive)
} else {
hydraService.getLoginRequest(challenge)
.flatMap { loginRequest ->
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/i18n/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ header.loggedInAs=You are logged in as: {0}
login.title=FAForever Login
login.welcomeBack=Welcome back, Commander!
login.badCredentials=Username or password was wrong
login.throttled=Too many of your login attempts have failed. Please wait some time before trying to login again.
login.usernameOrEmail=Username or email
login.password=Password
login.loginAction=Log in
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/i18n/messages_de.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ header.loggedInAs=Du bist eingeloggt als: {0}
login.title=FAForever Login
login.welcomeBack=Willkommen zurück, Commander!
login.badCredentials=Benutzername oder Passwort falsch
login.throttled=Zu viele deiner Login-Versuche sind fehlgeschlagen. Bitte warte einige Zeit bevor du es erneut versuchst.
login.usernameOrEmail=Benutzername oder Email
login.password=Passwort
login.loginAction=Einloggen
Expand Down
7 changes: 6 additions & 1 deletion src/main/resources/templates/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ <h2 id="form-header-right" th:text="#{login.welcomeBack}">Welcome back, commande

<div class="error" th:if="${loginFailed}">
<i class="fas fa-exclamation-triangle"></i>
<span th:text="#{login.badCredentials}">Username or password was wrong.</span>
<span th:text="#{login.badCredentials}">Username or password was wrong</span>
</div>

<div class="error" th:if="${loginThrottled}">
<i class="fas fa-exclamation-triangle"></i>
<span th:text="#{login.throttled}">Too many of your login attempts have failed. Please wait some time before trying to login again.</span>
</div>

<input type="hidden" name="login_challenge" th:value="${challenge}" th:if="${challenge != null }"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ class UserServiceApplicationTests {
.exchange()
.expectStatus().is3xxRedirection()
.expectHeader()
.location(hydraRedirectUrl)
.location("/login?login_challenge=someChallenge&login_challenge=someChallenge&login_throttled")
.expectBody(String::class.java)

verify(loginLogRepository).findFailedAttemptsByIp(anyString())
Expand Down