From 721e1ed5f1f68637b738c24a139b6e7050ad4c1c Mon Sep 17 00:00:00 2001
From: guqing <i@guqing.email>
Date: Fri, 2 Aug 2024 15:02:53 +0800
Subject: [PATCH] refactor: enhance OAuth2 error handling by adding
 user-friendly exception messages

---
 build.gradle                                  |  1 +
 .../halo/oauth/Oauth2LoginConfiguration.java  | 35 +++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/build.gradle b/build.gradle
index e7866cf..9bed6f9 100644
--- a/build.gradle
+++ b/build.gradle
@@ -30,4 +30,5 @@ test {
 
 halo {
     version = '2.17'
+    debug = true
 }
diff --git a/src/main/java/run/halo/oauth/Oauth2LoginConfiguration.java b/src/main/java/run/halo/oauth/Oauth2LoginConfiguration.java
index 0cbb46b..65268ea 100644
--- a/src/main/java/run/halo/oauth/Oauth2LoginConfiguration.java
+++ b/src/main/java/run/halo/oauth/Oauth2LoginConfiguration.java
@@ -1,6 +1,9 @@
 package run.halo.oauth;
 
+import com.google.common.base.Throwables;
 import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.authentication.DelegatingReactiveAuthenticationManager;
 import org.springframework.security.authentication.ReactiveAuthenticationManager;
@@ -40,6 +43,7 @@
 import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
 import org.springframework.stereotype.Component;
 import org.springframework.util.ClassUtils;
+import org.springframework.util.MultiValueMap;
 import reactor.core.publisher.Mono;
 import run.halo.app.extension.ReactiveExtensionClient;
 import run.halo.app.security.LoginHandlerEnhancer;
@@ -50,6 +54,7 @@
  * @author guqing
  * @since 1.0.0
  */
+@Slf4j
 @Getter
 @Component
 public final class Oauth2LoginConfiguration {
@@ -108,12 +113,42 @@ ServerAuthenticationFailureHandler getAuthenticationFailureHandler() {
                 @Override
                 public Mono<Void> onAuthenticationFailure(WebFilterExchange webFilterExchange,
                                                           AuthenticationException exception) {
+                    var queryParams = webFilterExchange.getExchange().getRequest().getQueryParams();
+                    var response = new OAuth2ErrorResponse(queryParams);
+                    log.error("An error occurred while attempting to oauth2 authenticate: \n{}",
+                        response, Throwables.getRootCause(exception));
                     return loginHandlerEnhancer.onLoginFailure(webFilterExchange.getExchange(), exception)
                         .then(super.onAuthenticationFailure(webFilterExchange, exception));
                 }
             };
         }
 
+        @RequiredArgsConstructor
+        static class OAuth2ErrorResponse {
+            private final MultiValueMap<String, String> queryParams;
+
+            public String error() {
+                return queryParams.getFirst("error");
+            }
+
+            public String errorDescription() {
+                return queryParams.getFirst("error_description");
+            }
+
+            public String errorUri() {
+                return queryParams.getFirst("error_uri");
+            }
+
+            @Override
+            public String toString() {
+                return """
+                    error: %s
+                    error_description: %s
+                    error_uri: %s
+                    """.formatted(error(), errorDescription(), errorUri());
+            }
+        }
+
         GrantedAuthoritiesMapper getAuthoritiesMapper() {
             return new SimpleAuthorityMapper();
         }