From 3d71d526091f7c1e9d25cd35a420c3d562d6ed8e Mon Sep 17 00:00:00 2001
From: Felix <23635466+its-felix@users.noreply.github.com>
Date: Fri, 25 Oct 2024 23:19:49 +0200
Subject: [PATCH] feat: always prompt the login/account selection screen at IDP

---
 .../OAuth2ClientConfiguration.java            | 54 +++++++++++++++----
 1 file changed, 43 insertions(+), 11 deletions(-)

diff --git a/src/main/java/com/gw2auth/oauth2/server/configuration/OAuth2ClientConfiguration.java b/src/main/java/com/gw2auth/oauth2/server/configuration/OAuth2ClientConfiguration.java
index 3fe9177..b168d6d 100644
--- a/src/main/java/com/gw2auth/oauth2/server/configuration/OAuth2ClientConfiguration.java
+++ b/src/main/java/com/gw2auth/oauth2/server/configuration/OAuth2ClientConfiguration.java
@@ -39,7 +39,7 @@ public ClientRegistration findByRegistrationId(String registrationId) {
             return Optional.ofNullable(uriComponents.getHost())
                     .flatMap((host) -> findBase(registrationId + "@" + host))
                     .or(() -> findBase(registrationId))
-                    .map((v) -> maybeChangeAuthorizationURL(v, uriComponents))
+                    .map(CustomClientRegistrationRepository::changeAuthorizationURL)
                     .orElse(null);
         }
 
@@ -47,19 +47,40 @@ private Optional<ClientRegistration> findBase(String registrationId) {
             return Optional.ofNullable(this.base.findByRegistrationId(registrationId));
         }
 
-        private ClientRegistration maybeChangeAuthorizationURL(ClientRegistration base, UriComponents uriComponents) {
-            if (!Objects.equals(uriComponents.getQueryParams().getFirst("add"), "true")) {
-                return base;
+        private static ClientRegistration changeAuthorizationURL(ClientRegistration base) {
+            // Google and GitHub provider details are populated by org.springframework.security.config.oauth2.client.CommonOAuth2Provider
+
+            final String issuerUri = base.getProviderDetails().getIssuerUri();
+            if (issuerUri != null && !issuerUri.isEmpty()) {
+                final UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(issuerUri).build();
+                final String host = uriComponents.getHost();
+
+                if (host != null) {
+                    if (host.startsWith("cognito-idp") && host.endsWith("amazonaws.com")) {
+                        return changeAuthorizationURLCognito(base);
+                    } else if (Objects.equals(host, "accounts.google.com")) {
+                        return changeAuthorizationURLGitHubOrGoogle(base);
+                    } else if (Objects.equals(host, "gw2auth.com")) {
+                        return changeAuthorizationURLGw2auth(base);
+                    }
+                }
             }
 
-            return switch (base.getRegistrationId()) {
-                case "cognito" -> changeAuthorizationURLCognito(base);
-                case "github", "google" -> changeAuthorizationURLGitHubOrGoogle(base);
-                default -> base;
-            };
+            // GitHub provider details dont have a issuer uri, use authorization uri for detection instead
+            final String authorizationUri = base.getProviderDetails().getAuthorizationUri();
+            if (authorizationUri != null && !authorizationUri.isEmpty()) {
+                final UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(authorizationUri).build();
+                final String host = uriComponents.getHost();
+
+                if (Objects.equals(host, "github.com")) {
+                    return changeAuthorizationURLGitHubOrGoogle(base);
+                }
+            }
+
+            return base;
         }
 
-        private ClientRegistration changeAuthorizationURLCognito(ClientRegistration base) {
+        private static ClientRegistration changeAuthorizationURLCognito(ClientRegistration base) {
             // https://docs.aws.amazon.com/cognito/latest/developerguide/logout-endpoint.html
             final String authorizationUri = UriComponentsBuilder.fromHttpUrl(base.getProviderDetails().getAuthorizationUri())
                     .replacePath("/logout")
@@ -70,7 +91,7 @@ private ClientRegistration changeAuthorizationURLCognito(ClientRegistration base
                     .build();
         }
 
-        private ClientRegistration changeAuthorizationURLGitHubOrGoogle(ClientRegistration base) {
+        private static ClientRegistration changeAuthorizationURLGitHubOrGoogle(ClientRegistration base) {
             // https://developers.google.com/identity/openid-connect/openid-connect?hl=de#authenticationuriparameters
             // https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps#1-request-a-users-github-identity
             final String authorizationUri = UriComponentsBuilder.fromHttpUrl(base.getProviderDetails().getAuthorizationUri())
@@ -81,5 +102,16 @@ private ClientRegistration changeAuthorizationURLGitHubOrGoogle(ClientRegistrati
                     .authorizationUri(authorizationUri)
                     .build();
         }
+
+        private static ClientRegistration changeAuthorizationURLGw2auth(ClientRegistration base) {
+            // https://github.com/gw2auth/oauth2-server/wiki/GW2Auth-Developer-Guide#redirect-the-user-to-the-authorization_endpoint
+            final String authorizationUri = UriComponentsBuilder.fromHttpUrl(base.getProviderDetails().getAuthorizationUri())
+                    .replaceQueryParam("prompt", "consent")
+                    .toUriString();
+
+            return ClientRegistration.withClientRegistration(base)
+                    .authorizationUri(authorizationUri)
+                    .build();
+        }
     }
 }