wip - testing different name attributes for SSO

This commit is contained in:
DarioGii 2025-01-30 18:42:32 +00:00 committed by Dario Ghunney Ware
parent d3cfc813e7
commit acabb69e1f
9 changed files with 51 additions and 36 deletions

View File

@ -169,7 +169,9 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
}
/**
* Handles different error scenarios during logout. Will return a <code>String</code> containing the error request parameter.
* Handles different error scenarios during logout. Will return a <code>String</code> containing
* the error request parameter.
*
* @param request the user's <code>HttpServletRequest</code> request.
* @return a <code>String</code> containing the error request parameter.
*/

View File

@ -24,11 +24,11 @@ public class CustomOAuth2UserService implements OAuth2UserService<OidcUserReques
private final OidcUserService delegate = new OidcUserService();
private UserService userService;
private final UserService userService;
private LoginAttemptService loginAttemptService;
private final LoginAttemptService loginAttemptService;
private ApplicationProperties applicationProperties;
private final ApplicationProperties applicationProperties;
public CustomOAuth2UserService(
ApplicationProperties applicationProperties,
@ -44,8 +44,9 @@ public class CustomOAuth2UserService implements OAuth2UserService<OidcUserReques
OAUTH2 oauth2 = applicationProperties.getSecurity().getOauth2();
String usernameAttribute = oauth2.getUseAsUsername();
if (usernameAttribute == null || usernameAttribute.trim().isEmpty()) {
if (usernameAttribute == null || usernameAttribute.isEmpty()) {
Client client = oauth2.getClient();
if (client != null && client.getKeycloak() != null) {
usernameAttribute = client.getKeycloak().getUseAsUsername();
} else {
@ -58,13 +59,14 @@ public class CustomOAuth2UserService implements OAuth2UserService<OidcUserReques
String username = user.getUserInfo().getClaimAsString(usernameAttribute);
// Check if the username claim is null or empty
if (username == null || username.trim().isEmpty()) {
if (username == null || username.isBlank()) {
throw new IllegalArgumentException(
"Claim '" + usernameAttribute + "' cannot be null or empty");
}
Optional<User> duser = userService.findByUsernameIgnoreCase(username);
if (duser.isPresent()) {
Optional<User> internalUser = userService.findByUsernameIgnoreCase(username);
if (internalUser.isPresent()) {
if (loginAttemptService.isBlocked(username)) {
throw new LockedException(
"Your account has been locked due to too many failed login attempts.");

View File

@ -28,6 +28,7 @@ import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2.Client;
import stirling.software.SPDF.model.User;
import stirling.software.SPDF.model.exception.NoProviderFoundException;
import stirling.software.SPDF.model.provider.GitHubProvider;
import stirling.software.SPDF.model.provider.GoogleProvider;
import stirling.software.SPDF.model.provider.KeycloakProvider;
@ -51,7 +52,8 @@ public class OAuth2Configuration {
@Bean
@ConditionalOnProperty(value = "security.oauth2.enabled", havingValue = "true")
public ClientRegistrationRepository clientRegistrationRepository() {
public ClientRegistrationRepository clientRegistrationRepository()
throws NoProviderFoundException {
List<ClientRegistration> registrations = new ArrayList<>();
githubClientRegistration().ifPresent(registrations::add);
oidcClientRegistration().ifPresent(registrations::add);
@ -59,8 +61,8 @@ public class OAuth2Configuration {
keycloakClientRegistration().ifPresent(registrations::add);
if (registrations.isEmpty()) {
log.error("At least one OAuth2 provider must be configured");
System.exit(1);
log.error("No OAuth2 provider registered");
throw new NoProviderFoundException("At least one OAuth2 provider must be configured.");
}
return new InMemoryClientRegistrationRepository(registrations);
@ -69,7 +71,7 @@ public class OAuth2Configuration {
private Optional<ClientRegistration> keycloakClientRegistration() {
OAUTH2 oauth2 = applicationProperties.getSecurity().getOauth2();
if (isOauthOrClientEmpty(oauth2)) {
if (isOAuth2Enabled(oauth2) || isClientInitialised(oauth2)) {
return Optional.empty();
}
@ -97,13 +99,13 @@ public class OAuth2Configuration {
}
private Optional<ClientRegistration> googleClientRegistration() {
OAUTH2 oauth2 = applicationProperties.getSecurity().getOauth2();
OAUTH2 oAuth2 = applicationProperties.getSecurity().getOauth2();
if (isOauthOrClientEmpty(oauth2)) {
if (isOAuth2Enabled(oAuth2) || isClientInitialised(oAuth2)) {
return Optional.empty();
}
Client client = oauth2.getClient();
Client client = oAuth2.getClient();
GoogleProvider googleClient = client.getGoogle();
Provider google =
new GoogleProvider(
@ -130,13 +132,13 @@ public class OAuth2Configuration {
}
private Optional<ClientRegistration> githubClientRegistration() {
OAUTH2 oauth2 = applicationProperties.getSecurity().getOauth2();
OAUTH2 oAuth2 = applicationProperties.getSecurity().getOauth2();
if (isOauthOrClientEmpty(oauth2)) {
if (isOAuth2Enabled(oAuth2)) {
return Optional.empty();
}
Client client = oauth2.getClient();
Client client = oAuth2.getClient();
GitHubProvider githubClient = client.getGithub();
Provider github =
new GitHubProvider(
@ -165,7 +167,7 @@ public class OAuth2Configuration {
private Optional<ClientRegistration> oidcClientRegistration() {
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
if (isOauthOrClientEmpty(oauth)) {
if (isOAuth2Enabled(oauth) || isClientInitialised(oauth)) {
return Optional.empty();
}
@ -194,12 +196,12 @@ public class OAuth2Configuration {
.build());
}
private boolean isOauthOrClientEmpty(OAUTH2 oauth) {
if (oauth == null || !oauth.getEnabled()) {
return false;
}
private boolean isOAuth2Enabled(OAUTH2 oAuth2) {
return oAuth2 == null || !oAuth2.getEnabled();
}
Client client = oauth.getClient();
private boolean isClientInitialised(OAUTH2 oauth2) {
Client client = oauth2.getClient();
return client == null;
}

View File

@ -114,7 +114,7 @@ public class AccountWebController {
providerList
.entrySet()
.removeIf(entry -> entry.getKey() == null || entry.getValue() == null);
model.addAttribute("providerlist", providerList);
model.addAttribute("providerList", providerList);
model.addAttribute("loginMethod", securityProps.getLoginMethod());
boolean altLogin = !providerList.isEmpty() ? securityProps.isAltLogin() : false;

View File

@ -245,11 +245,11 @@ public class ApplicationProperties {
}
public boolean isSettingsValid() {
return isStringEmpty(this.getIssuer())
&& isStringEmpty(this.getClientId())
&& isStringEmpty(this.getClientSecret())
&& isCollectionEmpty(this.getScopes())
&& isStringEmpty(this.getUseAsUsername());
return !isStringEmpty(this.getIssuer())
&& !isStringEmpty(this.getClientId())
&& !isStringEmpty(this.getClientSecret())
&& !isCollectionEmpty(this.getScopes())
&& !isStringEmpty(this.getUseAsUsername());
}
@Data

View File

@ -0,0 +1,11 @@
package stirling.software.SPDF.model.exception;
public class NoProviderFoundException extends Exception {
public NoProviderFoundException(String message) {
super(message);
}
public NoProviderFoundException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -57,9 +57,7 @@ public class Provider {
@Override
public String toString() {
return "Provider [issuer="
+ getIssuer()
+ ", name="
return "Provider [name="
+ getName()
+ ", clientName="
+ getClientName()

View File

@ -32,7 +32,7 @@ security:
google:
clientId: '' # client ID for Google OAuth2
clientSecret: '' # client secret for Google OAuth2
scopes: https://www.googleapis.com/auth/userinfo.email, https://www.googleapis.com/auth/userinfo.profile # scopes for Google OAuth2
scopes: email, profile # scopes for Google OAuth2
useAsUsername: email # field to use as the username for Google OAuth2
github:
clientId: '' # client ID for GitHub OAuth2

View File

@ -42,7 +42,7 @@
const runningEE = /*[[${@runningEE}]]*/ false;
const SSOAutoLogin = /*[[${@SSOAutoLogin}]]*/ false;
const loginMethod = /*[[${loginMethod}]]*/ 'normal';
const providerList = /*[[${providerlist}]]*/ {};
const providerList = /*[[${providerList}]]*/ {};
const shouldAutoRedirect = !hasRedirectError &&
!hasLogout &&
!hasMessage &&
@ -164,7 +164,7 @@
</button>
</div>
<div class="modal-body">
<div class="mb-3" th:each="provider : ${providerlist}">
<div class="mb-3" th:each="provider : ${providerList}">
<a th:href="@{|${provider.key}|}" th:text="${provider.value}" class="w-100 btn btn-lg btn-primary">Login Provider</a>
</div>
</div>