Skip to content

Commit

Permalink
Preserve remember-me option after authentication failure
Browse files Browse the repository at this point in the history
Signed-off-by: JohnNiang <[email protected]>
  • Loading branch information
JohnNiang committed Oct 12, 2024
1 parent 6d149ae commit 6e734ad
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ private boolean isValidCookieTokensLength(String[] cookieTokens) {
public Mono<Void> loginFail(ServerWebExchange exchange) {
log.debug("Interactive login attempt was unsuccessful.");
cancelCookie(exchange);
return Mono.empty();
return rememberMeRequestCache.saveRememberMe(exchange);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package run.halo.app.security.authentication.rememberme;

import static java.lang.Boolean.parseBoolean;

import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebSession;
import reactor.core.publisher.Mono;
Expand All @@ -23,9 +21,7 @@ public class WebSessionRememberMeRequestCache implements RememberMeRequestCache
@Override
public Mono<Void> saveRememberMe(ServerWebExchange exchange) {
return resolveFromQuery(exchange)
.filter(Boolean::booleanValue)
.switchIfEmpty(resolveFromForm(exchange))
.filter(Boolean::booleanValue)
.flatMap(rememberMe -> exchange.getSession().doOnNext(
session -> session.getAttributes().put(SESSION_ATTRIBUTE_NAME, rememberMe))
)
Expand All @@ -35,9 +31,7 @@ public Mono<Void> saveRememberMe(ServerWebExchange exchange) {
@Override
public Mono<Boolean> isRememberMe(ServerWebExchange exchange) {
return resolveFromQuery(exchange)
.filter(Boolean::booleanValue)
.switchIfEmpty(resolveFromForm(exchange))
.filter(Boolean::booleanValue)
.switchIfEmpty(resolveFromSession(exchange))
.defaultIfEmpty(false);
}
Expand All @@ -50,22 +44,20 @@ public Mono<Void> removeRememberMe(ServerWebExchange exchange) {
}

private Mono<Boolean> resolveFromQuery(ServerWebExchange exchange) {
return Mono.just(
parseBoolean(exchange.getRequest().getQueryParams().getFirst(DEFAULT_PARAMETER))
);
return Mono.justOrEmpty(exchange.getRequest().getQueryParams().getFirst(DEFAULT_PARAMETER))
.map(Boolean::parseBoolean);
}

private Mono<Boolean> resolveFromForm(ServerWebExchange exchange) {
return exchange.getFormData()
.map(form -> parseBoolean(form.getFirst(DEFAULT_PARAMETER)))
.filter(Boolean::booleanValue);
.mapNotNull(form -> form.getFirst(DEFAULT_PARAMETER))
.map(Boolean::parseBoolean);
}

private Mono<Boolean> resolveFromSession(ServerWebExchange exchange) {
return exchange.getSession()
.map(session -> {
var rememberMeObject = session.getAttribute(SESSION_ATTRIBUTE_NAME);
return rememberMeObject instanceof Boolean rememberMe ? rememberMe : false;
});
.mapNotNull(session -> session.getAttribute(SESSION_ATTRIBUTE_NAME))
.filter(Boolean.class::isInstance)
.cast(Boolean.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import run.halo.app.security.AuthProviderService;
import run.halo.app.security.HaloServerRequestCache;
import run.halo.app.security.authentication.CryptoService;
import run.halo.app.security.authentication.rememberme.RememberMeRequestCache;
import run.halo.app.security.authentication.rememberme.WebSessionRememberMeRequestCache;

/**
* Pre-auth login endpoints.
Expand All @@ -40,6 +42,8 @@ class PreAuthLoginEndpoint {

private final ServerRequestCache serverRequestCache = new HaloServerRequestCache();

private final RememberMeRequestCache rememberMeRequestCache = new WebSessionRememberMeRequestCache();

PreAuthLoginEndpoint(CryptoService cryptoService, GlobalInfoService globalInfoService,
AuthProviderService authProviderService) {
this.cryptoService = cryptoService;
Expand Down Expand Up @@ -91,7 +95,8 @@ RouterFunction<ServerResponse> preAuthLoginEndpoints() {
"authProvider", authProvider,
"fragmentTemplateName", fragmentTemplateName,
"socialAuthProviders", socialAuthProviders,
"formAuthProviders", formAuthProviders
"formAuthProviders", formAuthProviders,
"rememberMe", rememberMeRequestCache.isRememberMe(exchange)
// TODO Add more models here
))
));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<div th:replace="~{__${fragmentTemplateName}__::form}"></div>

<div th:if="${authProvider.spec.rememberMeSupport}" class="form-item-compact">
<input type="checkbox" id="remember-me" name="remember-me" value="true" />
<input type="checkbox" id="remember-me" name="remember-me" value="true" th:checked="${rememberMe}"/>
<label for="remember-me" th:text="#{form.rememberMe.label}"></label>
</div>

Expand Down

0 comments on commit 6e734ad

Please sign in to comment.