More Provider refactoring & cleanup

This commit is contained in:
Dario Ghunney Ware 2025-01-24 18:14:15 +00:00
parent 06a5ba892c
commit 8954990afb
64 changed files with 866 additions and 511 deletions

View File

@ -20,7 +20,7 @@ public class CleanUrlInterceptor implements HandlerInterceptor {
"endpoints",
"logout",
"error",
"erroroauth",
"errorOAuth",
"file",
"messageType",
"infoMessage");

View File

@ -69,7 +69,7 @@ public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationF
}
if (exception instanceof BadCredentialsException
|| exception instanceof UsernameNotFoundException) {
getRedirectStrategy().sendRedirect(request, response, "/login?error=badcredentials");
getRedirectStrategy().sendRedirect(request, response, "/login?error=badCredentials");
return;
}
if (exception instanceof InternalAuthenticationServiceException

View File

@ -27,57 +27,42 @@ import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrin
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.SPDF.model.ApplicationProperties.Security.SAML2;
import stirling.software.SPDF.model.exception.UnsupportedProviderException;
import stirling.software.SPDF.model.provider.Provider;
import stirling.software.SPDF.utils.UrlUtils;
@Slf4j
@AllArgsConstructor
public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
public static final String LOGOUT_PATH = "/login?logout=true";
private final ApplicationProperties applicationProperties;
@Override
public void onLogoutSuccess(
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException {
if (!response.isCommitted()) {
// Handle user logout due to disabled account
if (request.getParameter("userIsDisabled") != null) {
response.sendRedirect(
request.getContextPath() + "/login?erroroauth=userIsDisabled");
return;
}
// Handle OAuth2 authentication error
if (request.getParameter("oauth2AuthenticationErrorWeb") != null) {
response.sendRedirect(
request.getContextPath() + "/login?erroroauth=userAlreadyExistsWeb");
return;
}
if (authentication != null) {
// Handle SAML2 logout redirection
if (authentication instanceof Saml2Authentication) {
// Handle SAML2 logout redirection
getRedirect_saml2(request, response, authentication);
}
// Handle OAuth2 logout redirection
else if (authentication instanceof OAuth2AuthenticationToken) {
} else if (authentication instanceof OAuth2AuthenticationToken) {
// Handle OAuth2 logout redirection
getRedirect_oauth2(request, response, authentication);
}
// Handle Username/Password logout
else if (authentication instanceof UsernamePasswordAuthenticationToken) {
getRedirectStrategy().sendRedirect(request, response, "/login?logout=true");
}
// Handle unknown authentication types
else {
getRedirectStrategy().sendRedirect(request, response, LOGOUT_PATH);
} else {
// Handle unknown authentication types
log.error(
"authentication class unknown: {}",
"Authentication class unknown: {}",
authentication.getClass().getSimpleName());
getRedirectStrategy().sendRedirect(request, response, "/login?logout=true");
getRedirectStrategy().sendRedirect(request, response, LOGOUT_PATH);
}
} else {
// Redirect to login page after logout
getRedirectStrategy().sendRedirect(request, response, "/login?logout=true");
getRedirectStrategy().sendRedirect(request, response, LOGOUT_PATH);
}
}
}
@ -138,7 +123,7 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
samlClient.redirectToIdentityProvider(response, null, nameIdValue);
} catch (Exception e) {
log.error(nameIdValue, e);
getRedirectStrategy().sendRedirect(request, response, "/login?logout=true");
getRedirectStrategy().sendRedirect(request, response, LOGOUT_PATH);
}
}
@ -146,87 +131,81 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
private void getRedirect_oauth2(
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException {
String param = "logout=true";
String registrationId = null;
String issuer = null;
String clientId = null;
String registrationId;
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
String path = checkForErrors(request);
if (authentication instanceof OAuth2AuthenticationToken oauthToken) {
registrationId = oauthToken.getAuthorizedClientRegistrationId();
try {
// Get OAuth2 provider details from configuration
Provider provider = oauth.getClient().get(registrationId);
} catch (UnsupportedProviderException e) {
log.error(e.getMessage());
}
} else {
registrationId = oauth.getProvider() != null ? oauth.getProvider() : "";
}
issuer = oauth.getIssuer();
clientId = oauth.getClientId();
String errorMessage = "";
// Handle different error scenarios during logout
if (request.getParameter("oauth2AuthenticationErrorWeb") != null) {
param = "erroroauth=oauth2AuthenticationErrorWeb";
} else if ((errorMessage = request.getParameter("error")) != null) {
param = "error=" + sanitizeInput(errorMessage);
} else if ((errorMessage = request.getParameter("erroroauth")) != null) {
param = "erroroauth=" + sanitizeInput(errorMessage);
} else if (request.getParameter("oauth2AutoCreateDisabled") != null) {
param = "error=oauth2AutoCreateDisabled";
} else if (request.getParameter("oauth2_admin_blocked_user") != null) {
param = "erroroauth=oauth2_admin_blocked_user";
} else if (request.getParameter("userIsDisabled") != null) {
param = "erroroauth=userIsDisabled";
} else if (request.getParameter("badcredentials") != null) {
param = "error=badcredentials";
}
String redirect_url = UrlUtils.getOrigin(request) + "/login?" + param;
String redirectUrl = UrlUtils.getOrigin(request) + "/login?" + path;
// Redirect based on OAuth2 provider
switch (registrationId.toLowerCase()) {
case "keycloak" -> {
// Add Keycloak specific logout URL if needed
String logoutUrl =
issuer
oauth.getIssuer()
+ "/protocol/openid-connect/logout"
+ "?client_id="
+ clientId
+ oauth.getClientId()
+ "&post_logout_redirect_uri="
+ response.encodeRedirectURL(redirect_url);
log.info("Redirecting to Keycloak logout URL: " + logoutUrl);
+ response.encodeRedirectURL(redirectUrl);
log.info("Redirecting to Keycloak logout URL: {}", logoutUrl);
response.sendRedirect(logoutUrl);
}
case "github" -> {
// Add GitHub specific logout URL if needed
// todo: why does the redirect go to github? shouldn't it come to Stirling PDF?
String githubLogoutUrl = "https://github.com/logout";
log.info("Redirecting to GitHub logout URL: " + redirect_url);
response.sendRedirect(redirect_url);
}
case "google" -> {
// Add Google specific logout URL if needed
// String googleLogoutUrl =
// "https://accounts.google.com/Logout?continue=https://appengine.google.com/_ah/logout?continue="
// + response.encodeRedirectURL(redirect_url);
log.info("Google does not have a specific logout URL");
// log.info("Redirecting to Google logout URL: " + googleLogoutUrl);
// response.sendRedirect(googleLogoutUrl);
case "github", "google" -> {
log.info(
"No redirect URL for {} available. Redirecting to default logout URL: {}",
registrationId,
redirectUrl);
response.sendRedirect(redirectUrl);
}
default -> {
String defaultRedirectUrl = request.getContextPath() + "/login?" + param;
log.info("Redirecting to default logout URL: {}", defaultRedirectUrl);
response.sendRedirect(defaultRedirectUrl);
log.info("Redirecting to default logout URL: {}", redirectUrl);
response.sendRedirect(redirectUrl);
}
}
}
// Sanitize input to avoid potential security vulnerabilities
/**
* 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.
*/
private String checkForErrors(HttpServletRequest request) {
String errorMessage;
String path = "logout=true";
if (request.getParameter("oAuth2AuthenticationErrorWeb") != null) {
path = "errorOAuth=userAlreadyExistsWeb";
} else if ((errorMessage = request.getParameter("errorOAuth")) != null) {
path = "errorOAuth=" + sanitizeInput(errorMessage);
} else if (request.getParameter("oAuth2AutoCreateDisabled") != null) {
path = "errorOAuth=oAuth2AutoCreateDisabled";
} else if (request.getParameter("oAuth2AdminBlockedUser") != null) {
path = "errorOAuth=oAuth2AdminBlockedUser";
} else if (request.getParameter("userIsDisabled") != null) {
path = "errorOAuth=userIsDisabled";
} else if ((errorMessage = request.getParameter("error")) != null) {
path = "errorOAuth=" + sanitizeInput(errorMessage);
} else if (request.getParameter("badCredentials") != null) {
path = "errorOAuth=badCredentials";
}
return path;
}
/**
* Sanitize input to avoid potential security vulnerabilities. Will return a sanitised <code>
* String</code>.
*
* @return a sanitised <code>String</code>
*/
private String sanitizeInput(String input) {
return input.replaceAll("[^a-zA-Z0-9 ]", "");
}

View File

@ -227,7 +227,7 @@ public class SecurityConfiguration {
.permitAll());
}
// Handle OAUTH2 Logins
if (applicationProperties.getSecurity().isOauth2Activ()) {
if (applicationProperties.getSecurity().isOauth2Active()) {
http.oauth2Login(
oauth2 ->
oauth2.loginPage("/oauth2")
@ -258,7 +258,7 @@ public class SecurityConfiguration {
.permitAll());
}
// Handle SAML
if (applicationProperties.getSecurity().isSaml2Activ()) {
if (applicationProperties.getSecurity().isSaml2Active()) {
// && runningEE
// Configure the authentication provider
OpenSaml4AuthenticationProvider authenticationProvider =

View File

@ -177,7 +177,7 @@ public class UserAuthenticationFilter extends OncePerRequestFilter {
if (blockRegistration && !isUserExists) {
log.warn("Blocked registration for OAuth2/SAML user: {}", username);
response.sendRedirect(
request.getContextPath() + "/logout?oauth2_admin_blocked_user=true");
request.getContextPath() + "/logout?oAuth2AdminBlockedUser=true");
return;
}
@ -193,7 +193,7 @@ public class UserAuthenticationFilter extends OncePerRequestFilter {
// Redirect to logout if credentials are invalid
if (!isUserExists && notSsoLogin) {
response.sendRedirect(request.getContextPath() + "/logout?badcredentials=true");
response.sendRedirect(request.getContextPath() + "/logout?badCredentials=true");
return;
}
if (isUserDisabled) {

View File

@ -29,7 +29,7 @@ public class CustomOAuth2AuthenticationFailureHandler
if (exception instanceof BadCredentialsException) {
log.error("BadCredentialsException", exception);
getRedirectStrategy().sendRedirect(request, response, "/login?error=badcredentials");
getRedirectStrategy().sendRedirect(request, response, "/login?error=badCredentials");
return;
}
if (exception instanceof DisabledException) {
@ -52,8 +52,7 @@ public class CustomOAuth2AuthenticationFailureHandler
}
log.error("OAuth2 Authentication error: " + errorCode);
log.error("OAuth2AuthenticationException", exception);
getRedirectStrategy().sendRedirect(request, response, "/login?erroroauth=" + errorCode);
return;
getRedirectStrategy().sendRedirect(request, response, "/login?errorOAuth=" + errorCode);
}
log.error("Unhandled authentication exception", exception);
super.onAuthenticationFailure(request, response, exception);

View File

@ -26,13 +26,12 @@ import stirling.software.SPDF.utils.RequestUriUtils;
public class CustomOAuth2AuthenticationSuccessHandler
extends SavedRequestAwareAuthenticationSuccessHandler {
private LoginAttemptService loginAttemptService;
private ApplicationProperties applicationProperties;
private UserService userService;
private final LoginAttemptService loginAttemptService;
private final ApplicationProperties applicationProperties;
private final UserService userService;
public CustomOAuth2AuthenticationSuccessHandler(
final LoginAttemptService loginAttemptService,
LoginAttemptService loginAttemptService,
ApplicationProperties applicationProperties,
UserService userService) {
this.applicationProperties = applicationProperties;
@ -76,23 +75,22 @@ public class CustomOAuth2AuthenticationSuccessHandler
throw new LockedException(
"Your account has been locked due to too many failed login attempts.");
}
if (userService.isUserDisabled(username)) {
getRedirectStrategy()
.sendRedirect(request, response, "/logout?userIsDisabled=true");
return;
}
if (userService.usernameExistsIgnoreCase(username)
&& userService.hasPassword(username)
&& !userService.isAuthenticationTypeByUsername(username, AuthenticationType.SSO)
&& oAuth.getAutoCreateUser()) {
response.sendRedirect(contextPath + "/logout?oauth2AuthenticationErrorWeb=true");
return;
response.sendRedirect(contextPath + "/logout?oAuth2AuthenticationErrorWeb=true");
}
try {
if (oAuth.getBlockRegistration()
&& !userService.usernameExistsIgnoreCase(username)) {
response.sendRedirect(contextPath + "/logout?oauth2_admin_blocked_user=true");
return;
response.sendRedirect(contextPath + "/logout?oAuth2AdminBlockedUser=true");
}
if (principal instanceof OAuth2User) {
userService.processSSOPostLogin(username, oAuth.getAutoCreateUser());

View File

@ -25,11 +25,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,
@ -45,8 +45,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 {
@ -59,13 +60,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

@ -1,6 +1,7 @@
package stirling.software.SPDF.config.security.oauth2;
import static org.springframework.security.oauth2.core.AuthorizationGrantType.AUTHORIZATION_CODE;
import static stirling.software.SPDF.utils.validation.Validator.*;
import java.util.ArrayList;
import java.util.HashSet;
@ -28,9 +29,11 @@ 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.provider.GithubProvider;
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;
import stirling.software.SPDF.model.provider.Provider;
@Slf4j
@Configuration
@ -50,7 +53,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);
@ -58,54 +62,31 @@ 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);
}
private Optional<ClientRegistration> googleClientRegistration() {
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
if (oauth == null || !oauth.getEnabled()) {
return Optional.empty();
}
Client client = oauth.getClient();
if (client == null) {
return Optional.empty();
}
GoogleProvider google = client.getGoogle();
return google != null && google.isSettingsValid()
? Optional.of(
ClientRegistration.withRegistrationId(google.getName())
.clientId(google.getClientId())
.clientSecret(google.getClientSecret())
.scope(google.getScopes())
.authorizationUri(google.getAuthorizationUri())
.tokenUri(google.getTokenUri())
.userInfoUri(google.getUserinfoUri())
.userNameAttributeName(google.getUseAsUsername())
.clientName(google.getClientName())
.redirectUri(REDIRECT_URI_PATH + google.getName())
.authorizationGrantType(AUTHORIZATION_CODE)
.build())
: Optional.empty();
}
private Optional<ClientRegistration> keycloakClientRegistration() {
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
if (oauth == null || !oauth.getEnabled()) {
OAUTH2 oauth2 = applicationProperties.getSecurity().getOauth2();
if (isOAuth2Enabled(oauth2) || isClientInitialised(oauth2)) {
return Optional.empty();
}
Client client = oauth.getClient();
if (client == null) {
return Optional.empty();
}
KeycloakProvider keycloak = client.getKeycloak();
return keycloak != null && keycloak.isSettingsValid()
Client client = oauth2.getClient();
KeycloakProvider keycloakClient = client.getKeycloak();
Provider keycloak =
new KeycloakProvider(
keycloakClient.getIssuer(),
keycloakClient.getClientId(),
keycloakClient.getClientSecret(),
keycloakClient.getScopes(),
keycloakClient.getUseAsUsername());
return validateProvider(keycloak)
? Optional.of(
ClientRegistrations.fromIssuerLocation(keycloak.getIssuer())
.registrationId(keycloak.getName())
@ -118,15 +99,56 @@ public class OAuth2Configuration {
: Optional.empty();
}
private Optional<ClientRegistration> githubClientRegistration() {
if (isOauthOrClientEmpty()) {
private Optional<ClientRegistration> googleClientRegistration() {
OAUTH2 oAuth2 = applicationProperties.getSecurity().getOauth2();
if (isOAuth2Enabled(oAuth2) || isClientInitialised(oAuth2)) {
return Optional.empty();
}
GithubProvider github =
applicationProperties.getSecurity().getOauth2().getClient().getGithub();
Client client = oAuth2.getClient();
GoogleProvider googleClient = client.getGoogle();
Provider google =
new GoogleProvider(
googleClient.getClientId(),
googleClient.getClientSecret(),
googleClient.getScopes(),
googleClient.getUseAsUsername());
return github != null && github.isSettingsValid()
return validateProvider(google)
? Optional.of(
ClientRegistration.withRegistrationId(google.getName())
.clientId(google.getClientId())
.clientSecret(google.getClientSecret())
.scope(google.getScopes())
.authorizationUri(google.getAuthorizationUri())
.tokenUri(google.getTokenUri())
.userInfoUri(google.getUserInfoUri())
.userNameAttributeName(google.getUseAsUsername())
.clientName(google.getClientName())
.redirectUri(REDIRECT_URI_PATH + google.getName())
.authorizationGrantType(AUTHORIZATION_CODE)
.build())
: Optional.empty();
}
private Optional<ClientRegistration> githubClientRegistration() {
OAUTH2 oAuth2 = applicationProperties.getSecurity().getOauth2();
if (isOAuth2Enabled(oAuth2)) {
return Optional.empty();
}
Client client = oAuth2.getClient();
GitHubProvider githubClient = client.getGithub();
Provider github =
new GitHubProvider(
githubClient.getClientId(),
githubClient.getClientSecret(),
githubClient.getScopes(),
githubClient.getUseAsUsername());
return validateProvider(github)
? Optional.of(
ClientRegistration.withRegistrationId(github.getName())
.clientId(github.getClientId())
@ -134,7 +156,7 @@ public class OAuth2Configuration {
.scope(github.getScopes())
.authorizationUri(github.getAuthorizationUri())
.tokenUri(github.getTokenUri())
.userInfoUri(github.getUserinfoUri())
.userInfoUri(github.getUserInfoUri())
.userNameAttributeName(github.getUseAsUsername())
.clientName(github.getClientName())
.redirectUri(REDIRECT_URI_PATH + github.getName())
@ -146,49 +168,49 @@ public class OAuth2Configuration {
private Optional<ClientRegistration> oidcClientRegistration() {
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
if (oauth == null
|| oauth.getIssuer() == null
|| oauth.getIssuer().isEmpty()
|| oauth.getClientId() == null
|| oauth.getClientId().isEmpty()
|| oauth.getClientSecret() == null
|| oauth.getClientSecret().isEmpty()
|| oauth.getScopes() == null
|| oauth.getScopes().isEmpty()
|| oauth.getUseAsUsername() == null
|| oauth.getUseAsUsername().isEmpty()) {
if (isOAuth2Enabled(oauth) || isClientInitialised(oauth)) {
return Optional.empty();
}
if (isStringEmpty(oauth.getIssuer())
|| isStringEmpty(oauth.getClientId())
|| isStringEmpty(oauth.getClientSecret())
|| isCollectionEmpty(oauth.getScopes())
|| isStringEmpty(oauth.getUseAsUsername())) {
return Optional.empty();
}
String name = oauth.getProvider();
String firstChar = String.valueOf(name.charAt(0));
String clientName = name.replaceFirst(firstChar, firstChar.toUpperCase());
return Optional.of(
ClientRegistrations.fromIssuerLocation(oauth.getIssuer())
.registrationId("oidc")
.registrationId(name)
.clientId(oauth.getClientId())
.clientSecret(oauth.getClientSecret())
.scope(oauth.getScopes())
.userNameAttributeName(oauth.getUseAsUsername())
.clientName("OIDC")
.redirectUri(REDIRECT_URI_PATH + "oidc")
.clientName(clientName)
.redirectUri(REDIRECT_URI_PATH + name)
.authorizationGrantType(AUTHORIZATION_CODE)
.build());
}
private boolean isOauthOrClientEmpty() {
OAUTH2 oauth = applicationProperties.getSecurity().getOauth2();
private boolean isOAuth2Enabled(OAUTH2 oAuth2) {
return oAuth2 == null || !oAuth2.getEnabled();
}
if (oauth == null || !oauth.getEnabled()) {
return false;
}
Client client = oauth.getClient();
return client != null;
private boolean isClientInitialised(OAUTH2 oauth2) {
Client client = oauth2.getClient();
return client == null;
}
/*
This following function is to grant Authorities to the OAUTH2 user from the values stored in the database.
This is required for the internal; 'hasRole()' function to give out the correct role.
*/
@Bean
@ConditionalOnProperty(
value = "security.oauth2.enabled",
@ -213,11 +235,9 @@ public class OAuth2Configuration {
(String) oauth2Auth.getAttributes().get(useAsUsername));
if (userOpt.isPresent()) {
User user = userOpt.get();
if (user != null) {
mappedAuthorities.add(
new SimpleGrantedAuthority(
userService.findRole(user).getAuthority()));
}
mappedAuthorities.add(
new SimpleGrantedAuthority(
userService.findRole(user).getAuthority()));
}
}
});

View File

@ -26,13 +26,13 @@ public class CustomSaml2AuthenticationFailureHandler extends SimpleUrlAuthentica
if (exception instanceof Saml2AuthenticationException) {
Saml2Error error = ((Saml2AuthenticationException) exception).getSaml2Error();
getRedirectStrategy()
.sendRedirect(request, response, "/login?erroroauth=" + error.getErrorCode());
.sendRedirect(request, response, "/login?errorOAuth=" + error.getErrorCode());
} else if (exception instanceof ProviderNotFoundException) {
getRedirectStrategy()
.sendRedirect(
request,
response,
"/login?erroroauth=not_authentication_provider_found");
"/login?errorOAuth=not_authentication_provider_found");
}
log.error("AuthenticationException: " + exception);
}

View File

@ -97,7 +97,7 @@ public class CustomSaml2AuthenticationSuccessHandler
"User {} exists with password but is not SSO user, redirecting to logout",
username);
response.sendRedirect(
contextPath + "/logout?oauth2AuthenticationErrorWeb=true");
contextPath + "/logout?oAuth2AuthenticationErrorWeb=true");
return;
}
@ -105,7 +105,7 @@ public class CustomSaml2AuthenticationSuccessHandler
if (saml2.getBlockRegistration() && !userExists) {
log.debug("Registration blocked for new user: {}", username);
response.sendRedirect(
contextPath + "/login?erroroauth=oauth2_admin_blocked_user");
contextPath + "/login?errorOAuth=oAuth2AdminBlockedUser");
return;
}
log.debug("Processing SSO post-login for user: {}", username);

View File

@ -26,24 +26,17 @@ import stirling.software.SPDF.model.ApplicationProperties.Security.SAML2;
@Configuration
@Slf4j
@ConditionalOnProperty(
value = "security.saml2.enabled",
havingValue = "true",
matchIfMissing = false)
@ConditionalOnProperty(value = "security.saml2.enabled", havingValue = "true")
public class SAML2Configuration {
private final ApplicationProperties applicationProperties;
public SAML2Configuration(ApplicationProperties applicationProperties) {
this.applicationProperties = applicationProperties;
}
@Bean
@ConditionalOnProperty(
name = "security.saml2.enabled",
havingValue = "true",
matchIfMissing = false)
@ConditionalOnProperty(name = "security.saml2.enabled", havingValue = "true")
public RelyingPartyRegistrationRepository relyingPartyRegistrations() throws Exception {
SAML2 samlConf = applicationProperties.getSecurity().getSaml2();
X509Certificate idpCert = CertificateUtils.readCertificate(samlConf.getidpCert());
@ -73,10 +66,7 @@ public class SAML2Configuration {
}
@Bean
@ConditionalOnProperty(
name = "security.saml2.enabled",
havingValue = "true",
matchIfMissing = false)
@ConditionalOnProperty(name = "security.saml2.enabled", havingValue = "true")
public OpenSaml4AuthenticationRequestResolver authenticationRequestResolver(
RelyingPartyRegistrationRepository relyingPartyRegistrationRepository) {
OpenSaml4AuthenticationRequestResolver resolver =

View File

@ -1,5 +1,7 @@
package stirling.software.SPDF.controller.web;
import static stirling.software.SPDF.utils.validation.Validator.validateProvider;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.*;
@ -29,7 +31,7 @@ import stirling.software.SPDF.model.ApplicationProperties.Security;
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2.Client;
import stirling.software.SPDF.model.ApplicationProperties.Security.SAML2;
import stirling.software.SPDF.model.provider.GithubProvider;
import stirling.software.SPDF.model.provider.GitHubProvider;
import stirling.software.SPDF.model.provider.GoogleProvider;
import stirling.software.SPDF.model.provider.KeycloakProvider;
import stirling.software.SPDF.repository.UserRepository;
@ -40,12 +42,11 @@ import stirling.software.SPDF.repository.UserRepository;
public class AccountWebController {
public static final String OAUTH_2_AUTHORIZATION = "/oauth2/authorization/";
private final ApplicationProperties applicationProperties;
private final SessionPersistentRegistry sessionPersistentRegistry;
private final UserRepository // Assuming you have a repository for user operations
userRepository;
// Assuming you have a repository for user operations
private final UserRepository userRepository;
public AccountWebController(
ApplicationProperties applicationProperties,
@ -62,28 +63,40 @@ public class AccountWebController {
if (authentication != null && authentication.isAuthenticated()) {
return "redirect:/";
}
Map<String, String> providerList = new HashMap<>();
Security securityProps = applicationProperties.getSecurity();
OAUTH2 oauth = securityProps.getOauth2();
if (oauth != null) {
if (oauth.getEnabled()) {
if (oauth.isSettingsValid()) {
providerList.put(OAUTH_2_AUTHORIZATION + "oidc", oauth.getProvider());
String firstChar = String.valueOf(oauth.getProvider().charAt(0));
String clientName =
oauth.getProvider().replaceFirst(firstChar, firstChar.toUpperCase());
providerList.put(OAUTH_2_AUTHORIZATION + "oidc", clientName);
}
Client client = oauth.getClient();
if (client != null) {
GoogleProvider google = client.getGoogle();
if (google.isSettingsValid()) {
if (validateProvider(google)) {
providerList.put(
OAUTH_2_AUTHORIZATION + google.getName(), google.getClientName());
}
GithubProvider github = client.getGithub();
if (github.isSettingsValid()) {
GitHubProvider github = client.getGithub();
if (validateProvider(github)) {
providerList.put(
OAUTH_2_AUTHORIZATION + github.getName(), github.getClientName());
}
KeycloakProvider keycloak = client.getKeycloak();
if (keycloak.isSettingsValid()) {
if (validateProvider(keycloak)) {
providerList.put(
OAUTH_2_AUTHORIZATION + keycloak.getName(),
keycloak.getClientName());
@ -91,101 +104,74 @@ public class AccountWebController {
}
}
}
SAML2 saml2 = securityProps.getSaml2();
if (securityProps.isSaml2Activ()
if (securityProps.isSaml2Active()
&& applicationProperties.getSystem().getEnableAlphaFunctionality()) {
providerList.put("/saml2/authenticate/" + saml2.getRegistrationId(), "SAML 2");
}
// Remove any null keys/values from the providerList
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;
model.addAttribute("altLogin", altLogin);
model.addAttribute("currentPage", "login");
String error = request.getParameter("error");
if (error != null) {
switch (error) {
case "badcredentials":
error = "login.invalid";
break;
case "locked":
error = "login.locked";
break;
case "oauth2AuthenticationError":
error = "userAlreadyExistsOAuthMessage";
break;
default:
break;
case "badCredentials" -> error = "login.invalid";
case "locked" -> error = "login.locked";
case "oauth2AuthenticationError" -> error = "userAlreadyExistsOAuthMessage";
}
model.addAttribute("error", error);
}
String erroroauth = request.getParameter("erroroauth");
if (erroroauth != null) {
switch (erroroauth) {
case "oauth2AutoCreateDisabled":
erroroauth = "login.oauth2AutoCreateDisabled";
break;
case "invalidUsername":
erroroauth = "login.invalid";
break;
case "userAlreadyExistsWeb":
erroroauth = "userAlreadyExistsWebMessage";
break;
case "oauth2AuthenticationErrorWeb":
erroroauth = "login.oauth2InvalidUserType";
break;
case "invalid_token_response":
erroroauth = "login.oauth2InvalidTokenResponse";
break;
case "authorization_request_not_found":
erroroauth = "login.oauth2RequestNotFound";
break;
case "access_denied":
erroroauth = "login.oauth2AccessDenied";
break;
case "invalid_user_info_response":
erroroauth = "login.oauth2InvalidUserInfoResponse";
break;
case "invalid_request":
erroroauth = "login.oauth2invalidRequest";
break;
case "invalid_id_token":
erroroauth = "login.oauth2InvalidIdToken";
break;
case "oauth2_admin_blocked_user":
erroroauth = "login.oauth2AdminBlockedUser";
break;
case "userIsDisabled":
erroroauth = "login.userIsDisabled";
break;
case "invalid_destination":
erroroauth = "login.invalid_destination";
break;
case "relying_party_registration_not_found":
erroroauth = "login.relyingPartyRegistrationNotFound";
break;
String errorOAuth = request.getParameter("errorOAuth");
if (errorOAuth != null) {
switch (errorOAuth) {
case "oAuth2AutoCreateDisabled" -> errorOAuth = "login.oAuth2AutoCreateDisabled";
case "invalidUsername" -> errorOAuth = "login.invalid";
case "userAlreadyExistsWeb" -> errorOAuth = "userAlreadyExistsWebMessage";
case "oAuth2AuthenticationErrorWeb" -> errorOAuth = "login.oauth2InvalidUserType";
case "invalid_token_response" -> errorOAuth = "login.oauth2InvalidTokenResponse";
case "authorization_request_not_found" ->
errorOAuth = "login.oauth2RequestNotFound";
case "access_denied" -> errorOAuth = "login.oauth2AccessDenied";
case "invalid_user_info_response" ->
errorOAuth = "login.oauth2InvalidUserInfoResponse";
case "invalid_request" -> errorOAuth = "login.oauth2invalidRequest";
case "invalid_id_token" -> errorOAuth = "login.oauth2InvalidIdToken";
case "oAuth2AdminBlockedUser" -> errorOAuth = "login.oAuth2AdminBlockedUser";
case "userIsDisabled" -> errorOAuth = "login.userIsDisabled";
case "invalid_destination" -> errorOAuth = "login.invalid_destination";
case "relying_party_registration_not_found" ->
errorOAuth = "login.relyingPartyRegistrationNotFound";
// Valid InResponseTo was not available from the validation context, unable to
// evaluate
case "invalid_in_response_to":
erroroauth = "login.invalid_in_response_to";
break;
case "not_authentication_provider_found":
erroroauth = "login.not_authentication_provider_found";
break;
default:
break;
case "invalid_in_response_to" -> errorOAuth = "login.invalid_in_response_to";
case "not_authentication_provider_found" ->
errorOAuth = "login.not_authentication_provider_found";
}
model.addAttribute("erroroauth", erroroauth);
model.addAttribute("errorOAuth", errorOAuth);
}
if (request.getParameter("messageType") != null) {
model.addAttribute("messageType", "changedCredsMessage");
}
if (request.getParameter("logout") != null) {
model.addAttribute("logoutMessage", "You have been logged out.");
}
return "login";
}
@ -339,40 +325,28 @@ public class AccountWebController {
if (authentication != null && authentication.isAuthenticated()) {
Object principal = authentication.getPrincipal();
String username = null;
if (principal instanceof UserDetails) {
// Cast the principal object to UserDetails
UserDetails userDetails = (UserDetails) principal;
if (principal instanceof UserDetails userDetails) {
// Retrieve username and other attributes
username = userDetails.getUsername();
// Add oAuth2 Login attributes to the model
model.addAttribute("oAuth2Login", false);
}
if (principal instanceof OAuth2User) {
// Cast the principal object to OAuth2User
OAuth2User userDetails = (OAuth2User) principal;
if (principal instanceof OAuth2User userDetails) {
// Retrieve username and other attributes
username =
userDetails.getAttribute(
applicationProperties.getSecurity().getOauth2().getUseAsUsername());
username = userDetails.getName();
// Add oAuth2 Login attributes to the model
model.addAttribute("oAuth2Login", true);
}
if (principal instanceof CustomSaml2AuthenticatedPrincipal) {
// Cast the principal object to OAuth2User
CustomSaml2AuthenticatedPrincipal userDetails =
(CustomSaml2AuthenticatedPrincipal) principal;
if (principal instanceof CustomSaml2AuthenticatedPrincipal userDetails) {
// Retrieve username and other attributes
username = userDetails.getName();
// Add oAuth2 Login attributes to the model
model.addAttribute("oAuth2Login", true);
}
if (username != null) {
// Fetch user details from the database
Optional<User> user =
userRepository
.findByUsernameIgnoreCaseWithSettings( // Assuming findByUsername
// method exists
username);
// Fetch user details from the database, assuming findByUsername method exists
Optional<User> user = userRepository.findByUsernameIgnoreCaseWithSettings(username);
if (!user.isPresent()) {
return "redirect:/error";
}
@ -386,31 +360,20 @@ public class AccountWebController {
log.error("exception", e);
return "redirect:/error";
}
String messageType = request.getParameter("messageType");
if (messageType != null) {
switch (messageType) {
case "notAuthenticated":
messageType = "notAuthenticatedMessage";
break;
case "userNotFound":
messageType = "userNotFoundMessage";
break;
case "incorrectPassword":
messageType = "incorrectPasswordMessage";
break;
case "usernameExists":
messageType = "usernameExistsMessage";
break;
case "invalidUsername":
messageType = "invalidUsernameMessage";
break;
default:
break;
case "notAuthenticated" -> messageType = "notAuthenticatedMessage";
case "userNotFound" -> messageType = "userNotFoundMessage";
case "incorrectPassword" -> messageType = "incorrectPasswordMessage";
case "usernameExists" -> messageType = "usernameExistsMessage";
case "invalidUsername" -> messageType = "invalidUsernameMessage";
}
model.addAttribute("messageType", messageType);
}
// Add attributes to the model
model.addAttribute("username", username);
model.addAttribute("messageType", messageType);
model.addAttribute("role", user.get().getRolesAsString());
model.addAttribute("settings", settingsJson);
model.addAttribute("changeCredsFlag", user.get().isFirstLogin());

View File

@ -1,5 +1,7 @@
package stirling.software.SPDF.model;
import static stirling.software.SPDF.utils.validation.Validator.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@ -35,7 +37,7 @@ import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.InstallationPathConfig;
import stirling.software.SPDF.config.YamlPropertySourceFactory;
import stirling.software.SPDF.model.exception.UnsupportedProviderException;
import stirling.software.SPDF.model.provider.GithubProvider;
import stirling.software.SPDF.model.provider.GitHubProvider;
import stirling.software.SPDF.model.provider.GoogleProvider;
import stirling.software.SPDF.model.provider.KeycloakProvider;
import stirling.software.SPDF.model.provider.Provider;
@ -244,17 +246,17 @@ public class ApplicationProperties {
}
public boolean isSettingsValid() {
return isValid(this.getIssuer(), "issuer")
&& isValid(this.getClientId(), "clientId")
&& isValid(this.getClientSecret(), "clientSecret")
&& isValid(this.getScopes(), "scopes")
&& isValid(this.getUseAsUsername(), "useAsUsername");
return !isStringEmpty(this.getIssuer())
&& !isStringEmpty(this.getClientId())
&& !isStringEmpty(this.getClientSecret())
&& !isCollectionEmpty(this.getScopes())
&& !isStringEmpty(this.getUseAsUsername());
}
@Data
public static class Client {
private GoogleProvider google = new GoogleProvider();
private GithubProvider github = new GithubProvider();
private GitHubProvider github = new GitHubProvider();
private KeycloakProvider keycloak = new KeycloakProvider();
public Provider get(String registrationId) throws UnsupportedProviderException {
@ -262,8 +264,10 @@ public class ApplicationProperties {
case "google" -> getGoogle();
case "github" -> getGithub();
case "keycloak" -> getKeycloak();
default -> throw new UnsupportedProviderException(
"Logout from the provider is not supported. Report it at https://github.com/Stirling-Tools/Stirling-PDF/issues");
default ->
throw new UnsupportedProviderException(
"Logout from the provider " + registrationId + " is not supported. "
+ "Report it at https://github.com/Stirling-Tools/Stirling-PDF/issues");
};
}
}

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

@ -5,9 +5,8 @@ import java.util.Collection;
import lombok.NoArgsConstructor;
// @Setter
@NoArgsConstructor
public class GithubProvider extends Provider {
public class GitHubProvider extends Provider {
private static final String NAME = "github";
private static final String CLIENT_NAME = "GitHub";
@ -15,51 +14,68 @@ public class GithubProvider extends Provider {
private static final String TOKEN_URI = "https://github.com/login/oauth/access_token";
private static final String USER_INFO_URI = "https://api.github.com/user";
private String clientId;
private String clientSecret;
private Collection<String> scopes = new ArrayList<>();
private String useAsUsername = "login";
public GithubProvider(
public GitHubProvider(
String clientId, String clientSecret, Collection<String> scopes, String useAsUsername) {
super(null, NAME, CLIENT_NAME, clientId, clientSecret, scopes, useAsUsername);
this.clientId = clientId;
this.clientSecret = clientSecret;
this.scopes = scopes;
this.useAsUsername = useAsUsername;
super(
null,
NAME,
CLIENT_NAME,
clientId,
clientSecret,
scopes,
useAsUsername != null ? useAsUsername : "login",
AUTHORIZATION_URI,
TOKEN_URI,
USER_INFO_URI);
}
@Override
public String getAuthorizationUri() {
return AUTHORIZATION_URI;
}
@Override
public String getTokenUri() {
return TOKEN_URI;
}
public String getUserinfoUri() {
@Override
public String getUserInfoUri() {
return USER_INFO_URI;
}
@Override
public String getName() {
return NAME;
}
@Override
public String getClientName() {
return CLIENT_NAME;
}
@Override
public Collection<String> getScopes() {
Collection<String> scopes = super.getScopes();
if (scopes == null || scopes.isEmpty()) {
scopes = new ArrayList<>();
scopes.add("read:user");
}
return scopes;
}
@Override
public String toString() {
return "GitHub [clientId="
+ clientId
+ getClientId()
+ ", clientSecret="
+ (clientSecret != null && !clientSecret.isEmpty() ? "MASKED" : "NULL")
+ (getClientSecret() != null && !getClientSecret().isEmpty() ? "*****" : "NULL")
+ ", scopes="
+ scopes
+ getScopes()
+ ", useAsUsername="
+ useAsUsername
+ getUseAsUsername()
+ "]";
}
}

View File

@ -5,7 +5,6 @@ import java.util.Collection;
import lombok.NoArgsConstructor;
// @Setter
@NoArgsConstructor
public class GoogleProvider extends Provider {
@ -16,18 +15,19 @@ public class GoogleProvider extends Provider {
private static final String USER_INFO_URI =
"https://www.googleapis.com/oauth2/v3/userinfo?alt=json";
private String clientId;
private String clientSecret;
private Collection<String> scopes = new ArrayList<>();
private String useAsUsername = "email";
public GoogleProvider(
String clientId, String clientSecret, Collection<String> scopes, String useAsUsername) {
super(null, NAME, CLIENT_NAME, clientId, clientSecret, scopes, useAsUsername);
this.clientId = clientId;
this.clientSecret = clientSecret;
this.scopes = scopes;
this.useAsUsername = useAsUsername;
super(
null,
NAME,
CLIENT_NAME,
clientId,
clientSecret,
scopes,
useAsUsername,
AUTHORIZATION_URI,
TOKEN_URI,
USER_INFO_URI);
}
public String getAuthorizationUri() {
@ -42,26 +42,39 @@ public class GoogleProvider extends Provider {
return USER_INFO_URI;
}
@Override
public String getName() {
return NAME;
}
@Override
public String getClientName() {
return CLIENT_NAME;
}
@Override
public Collection<String> getScopes() {
Collection<String> scopes = super.getScopes();
if (scopes == null || scopes.isEmpty()) {
scopes = new ArrayList<>();
scopes.add("https://www.googleapis.com/auth/userinfo.email");
scopes.add("https://www.googleapis.com/auth/userinfo.profile");
}
return scopes;
}
@Override
public String toString() {
return "Google [clientId="
+ clientId
+ getClientId()
+ ", clientSecret="
+ (clientSecret != null && !clientSecret.isEmpty() ? "MASKED" : "NULL")
+ (getClientSecret() != null && !getClientSecret().isEmpty() ? "*****" : "NULL")
+ ", scopes="
+ scopes
+ getScopes()
+ ", useAsUsername="
+ useAsUsername
+ getUseAsUsername()
+ "]";
}
}

View File

@ -5,36 +5,44 @@ import java.util.Collection;
import lombok.NoArgsConstructor;
// @Setter
@NoArgsConstructor
public class KeycloakProvider extends Provider {
private static final String NAME = "keycloak";
private static final String CLIENT_NAME = "Keycloak";
private String issuer;
private String clientId;
private String clientSecret;
private Collection<String> scopes;
private String useAsUsername = "email";
public KeycloakProvider(
String issuer,
String clientId,
String clientSecret,
Collection<String> scopes,
String useAsUsername) {
super(issuer, NAME, CLIENT_NAME, clientId, clientSecret, scopes, useAsUsername);
this.useAsUsername = useAsUsername;
this.issuer = issuer;
this.clientId = clientId;
this.clientSecret = clientSecret;
this.scopes = scopes;
super(
issuer,
NAME,
CLIENT_NAME,
clientId,
clientSecret,
scopes,
useAsUsername,
null,
null,
null);
}
@Override
public String getName() {
return NAME;
}
@Override
public String getClientName() {
return CLIENT_NAME;
}
@Override
public Collection<String> getScopes() {
var scopes = super.getScopes();
Collection<String> scopes = super.getScopes();
if (scopes == null || scopes.isEmpty()) {
scopes = new ArrayList<>();
@ -48,15 +56,15 @@ public class KeycloakProvider extends Provider {
@Override
public String toString() {
return "Keycloak [issuer="
+ issuer
+ getIssuer()
+ ", clientId="
+ clientId
+ getClientId()
+ ", clientSecret="
+ (clientSecret != null && !clientSecret.isBlank() ? "MASKED" : "NULL")
+ (getClientSecret() != null && !getClientSecret().isBlank() ? "*****" : "NULL")
+ ", scopes="
+ scopes
+ getScopes()
+ ", useAsUsername="
+ useAsUsername
+ getUseAsUsername()
+ "]";
}
}

View File

@ -1,15 +1,18 @@
package stirling.software.SPDF.model.provider;
import static stirling.software.SPDF.utils.validation.Validator.isStringEmpty;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;
import lombok.Getter;
import lombok.Data;
import lombok.NoArgsConstructor;
@Getter
@Data
@NoArgsConstructor
public abstract class Provider {
public class Provider {
private String issuer;
private String name;
@ -18,6 +21,9 @@ public abstract class Provider {
private String clientSecret;
private Collection<String> scopes;
private String useAsUsername;
private String authorizationUri;
private String tokenUri;
private String userInfoUri;
public Provider(
String issuer,
@ -26,59 +32,43 @@ public abstract class Provider {
String clientId,
String clientSecret,
Collection<String> scopes,
String useAsUsername) {
String useAsUsername,
String authorizationUri,
String tokenUri,
String userInfoUri) {
this.issuer = issuer;
this.name = name;
this.clientName = clientName;
this.clientId = clientId;
this.clientSecret = clientSecret;
this.scopes = scopes;
this.useAsUsername = !useAsUsername.isBlank() ? useAsUsername : "email";
}
// todo: why are we passing name here if it's not used?
public boolean isSettingsValid() {
return isValid(this.getIssuer(), "issuer")
&& isValid(this.getClientId(), "clientId")
&& isValid(this.getClientSecret(), "clientSecret")
&& isValid(this.getScopes(), "scopes")
&& isValid(this.getUseAsUsername(), "useAsUsername");
}
private boolean isValid(String value, String name) {
return value != null && !value.isBlank();
}
private boolean isValid(Collection<String> value, String name) {
return value != null && !value.isEmpty();
}
public void setIssuer(String issuer) {
this.issuer = issuer;
}
public void setName(String name) {
this.name = name;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
this.scopes = scopes == null ? new ArrayList<>() : scopes;
this.useAsUsername = isStringEmpty(useAsUsername) ? "email" : useAsUsername;
this.authorizationUri = authorizationUri;
this.tokenUri = tokenUri;
this.userInfoUri = userInfoUri;
}
public void setScopes(String scopes) {
this.scopes =
Arrays.stream(scopes.split(",")).map(String::trim).collect(Collectors.toList());
if (scopes != null && !scopes.isBlank()) {
this.scopes =
Arrays.stream(scopes.split(",")).map(String::trim).collect(Collectors.toList());
}
}
public void setUseAsUsername(String useAsUsername) {
this.useAsUsername = useAsUsername;
@Override
public String toString() {
return "Provider [name="
+ getName()
+ ", clientName="
+ getClientName()
+ ", clientId="
+ getClientId()
+ ", clientSecret="
+ (getClientSecret() != null && !getClientSecret().isEmpty() ? "*****" : "NULL")
+ ", scopes="
+ getScopes()
+ ", useAsUsername="
+ getUseAsUsername()
+ "]";
}
}

View File

@ -7,8 +7,6 @@ import jakarta.servlet.http.HttpServletRequest;
public class UrlUtils {
private UrlUtils() {}
public static String getOrigin(HttpServletRequest request) {
String scheme = request.getScheme(); // http or https
String serverName = request.getServerName(); // localhost

View File

@ -0,0 +1,40 @@
package stirling.software.SPDF.utils.validation;
import java.util.Collection;
import stirling.software.SPDF.model.provider.Provider;
public class Validator {
public static boolean validateProvider(Provider provider) {
if (provider == null) {
return false;
}
if (isStringEmpty(provider.getClientId())) {
return false;
}
if (isStringEmpty(provider.getClientSecret())) {
return false;
}
if (isCollectionEmpty(provider.getScopes())) {
return false;
}
if (isStringEmpty(provider.getUseAsUsername())) {
return false;
}
return true;
}
public static boolean isStringEmpty(String input) {
return input == null || input.isBlank();
}
public static boolean isCollectionEmpty(Collection<String> input) {
return input == null || input.isEmpty();
}
}

View File

@ -572,8 +572,8 @@ login.invalid=اسم المستخدم أو كلمة المرور غير صالح
login.locked=تم قفل حسابك.
login.signinTitle=الرجاء تسجيل الدخول
login.ssoSignIn=تسجيل الدخول عبر تسجيل الدخول الأحادي
login.oauth2AutoCreateDisabled=تم تعطيل الإنشاء التلقائي لمستخدم OAuth2
login.oauth2AdminBlockedUser=تم حظر تسجيل أو تسجيل دخول المستخدمين غير المسجلين حاليًا. يرجى الاتصال بالمسؤول.
login.oAuth2AutoCreateDisabled=تم تعطيل الإنشاء التلقائي لمستخدم OAuth2
login.oAuth2AdminBlockedUser=تم حظر تسجيل أو تسجيل دخول المستخدمين غير المسجلين حاليًا. يرجى الاتصال بالمسؤول.
login.oauth2RequestNotFound=لم يتم العثور على طلب التفويض
login.oauth2InvalidUserInfoResponse=استجابة معلومات المستخدم غير صالحة
login.oauth2invalidRequest=طلب غير صالح

View File

@ -572,8 +572,8 @@ login.invalid=Etibarsız istifadəçi adı və ya şifr.
login.locked=Sizin hesabınız kilidlənmişdir.
login.signinTitle=Zəhmət olmasa, daxil olun
login.ssoSignIn=Single Sign-on vasitəsilə daxil olun
login.oauth2AutoCreateDisabled=OAUTH2 Auto-Create İstifadəçisi Deaktivləşdirilmişdir
login.oauth2AdminBlockedUser=Qeydiyyatdan keçməmiş istifadəçilərin qeydiyyatı və daxil olması hal-hazırda bloklanmışdır. Zəhmət olmasa, administratorla əlaqə saxlayın.
login.oAuth2AutoCreateDisabled=OAUTH2 Auto-Create İstifadəçisi Deaktivləşdirilmişdir
login.oAuth2AdminBlockedUser=Qeydiyyatdan keçməmiş istifadəçilərin qeydiyyatı və daxil olması hal-hazırda bloklanmışdır. Zəhmət olmasa, administratorla əlaqə saxlayın.
login.oauth2RequestNotFound=Təsdiqlənmə sorğusu tapılmadı
login.oauth2InvalidUserInfoResponse=Yanlış İstifadəçi Məlumatı Cavabı
login.oauth2invalidRequest=Etibarsız Sorğu

View File

@ -572,8 +572,8 @@ login.invalid=Невалидно потребителско име или пар
login.locked=Вашият акаунт е заключен.
login.signinTitle=Моля впишете се
login.ssoSignIn=Влизане чрез еднократно влизане
login.oauth2AutoCreateDisabled=OAUTH2 Автоматично създаване на потребител е деактивирано
login.oauth2AdminBlockedUser=Регистрацията или влизането на нерегистрирани потребители в момента е блокирано. Моля, свържете се с администратора.
login.oAuth2AutoCreateDisabled=OAUTH2 Автоматично създаване на потребител е деактивирано
login.oAuth2AdminBlockedUser=Регистрацията или влизането на нерегистрирани потребители в момента е блокирано. Моля, свържете се с администратора.
login.oauth2RequestNotFound=Заявката за оторизация не е намерена
login.oauth2InvalidUserInfoResponse=Невалидна информация за потребителя
login.oauth2invalidRequest=Невалидна заявка

View File

@ -572,8 +572,8 @@ login.invalid=Nom d'usuari/contrasenya no vàlid
login.locked=Compte bloquejat
login.signinTitle=Autenticat
login.ssoSignIn=Inicia sessió mitjançant inici de sessió únic
login.oauth2AutoCreateDisabled=La creació automàtica d'usuaris OAUTH2 està desactivada
login.oauth2AdminBlockedUser=El registre o inici de sessió d'usuaris no registrats està actualment bloquejat. Si us plau, contacta amb l'administrador.
login.oAuth2AutoCreateDisabled=La creació automàtica d'usuaris OAUTH2 està desactivada
login.oAuth2AdminBlockedUser=El registre o inici de sessió d'usuaris no registrats està actualment bloquejat. Si us plau, contacta amb l'administrador.
login.oauth2RequestNotFound=Sol·licitud d'autorització no trobada
login.oauth2InvalidUserInfoResponse=Resposta d'informació d'usuari no vàlida
login.oauth2invalidRequest=Sol·licitud no vàlida

View File

@ -572,8 +572,8 @@ login.invalid=Neplatné uživatelské jméno nebo heslo.
login.locked=Váš účet byl uzamčen.
login.signinTitle=Prosím přihlaste se
login.ssoSignIn=Přihlásit se přes Single Sign-on
login.oauth2AutoCreateDisabled=Automatické vytváření OAUTH2 uživatelů je zakázáno
login.oauth2AdminBlockedUser=Registrace nebo přihlášení neregistrovaných uživatelů je momentálně blokováno. Kontaktujte prosím správce.
login.oAuth2AutoCreateDisabled=Automatické vytváření OAUTH2 uživatelů je zakázáno
login.oAuth2AdminBlockedUser=Registrace nebo přihlášení neregistrovaných uživatelů je momentálně blokováno. Kontaktujte prosím správce.
login.oauth2RequestNotFound=Požadavek na autorizaci nebyl nalezen
login.oauth2InvalidUserInfoResponse=Neplatná odpověď s informacemi o uživateli
login.oauth2invalidRequest=Neplatný požadavek

View File

@ -572,8 +572,8 @@ login.invalid=Ugyldigt brugernavn eller adgangskode.
login.locked=Din konto er blevet låst.
login.signinTitle=Log venligst ind
login.ssoSignIn=Log ind via Single Sign-on
login.oauth2AutoCreateDisabled=OAUTH2 Auto-Opret Bruger Deaktiveret
login.oauth2AdminBlockedUser=Registrering eller login af ikke-registrerede brugere er i øjeblikket blokeret. Kontakt venligst administratoren.
login.oAuth2AutoCreateDisabled=OAUTH2 Auto-Opret Bruger Deaktiveret
login.oAuth2AdminBlockedUser=Registrering eller login af ikke-registrerede brugere er i øjeblikket blokeret. Kontakt venligst administratoren.
login.oauth2RequestNotFound=Autorisationsanmodning ikke fundet
login.oauth2InvalidUserInfoResponse=Ugyldigt Brugerinfo Svar
login.oauth2invalidRequest=Ugyldig Anmodning

View File

@ -572,8 +572,8 @@ login.invalid=Benutzername oder Passwort ungültig.
login.locked=Ihr Konto wurde gesperrt.
login.signinTitle=Bitte melden Sie sich an.
login.ssoSignIn=Anmeldung per Single Sign-On
login.oauth2AutoCreateDisabled=OAUTH2 Benutzer automatisch erstellen deaktiviert
login.oauth2AdminBlockedUser=Die Registrierung bzw. das anmelden von nicht registrierten Benutzern ist derzeit gesperrt. Bitte wenden Sie sich an den Administrator.
login.oAuth2AutoCreateDisabled=OAUTH2 Benutzer automatisch erstellen deaktiviert
login.oAuth2AdminBlockedUser=Die Registrierung bzw. das anmelden von nicht registrierten Benutzern ist derzeit gesperrt. Bitte wenden Sie sich an den Administrator.
login.oauth2RequestNotFound=Autorisierungsanfrage nicht gefunden
login.oauth2InvalidUserInfoResponse=Ungültige Benutzerinformationsantwort
login.oauth2invalidRequest=ungültige Anfrage

View File

@ -572,8 +572,8 @@ login.invalid=Μη έγκυρο όνομα χρήστη ή κωδικός.
login.locked=Ο λογαριασμός σας έχει κλειδωθεί.
login.signinTitle=Παρακαλώ συνδεθείτε
login.ssoSignIn=Σύνδεση μέσω Single Sign-on
login.oauth2AutoCreateDisabled=Η αυτόματη δημιουργία χρήστη OAUTH2 είναι απενεργοποιημένη
login.oauth2AdminBlockedUser=Η εγγραφή ή σύνδεση μη εγγεγραμμένων χρηστών είναι προς το παρόν αποκλεισμένη. Παρακαλώ επικοινωνήστε με τον διαχειριστή.
login.oAuth2AutoCreateDisabled=Η αυτόματη δημιουργία χρήστη OAUTH2 είναι απενεργοποιημένη
login.oAuth2AdminBlockedUser=Η εγγραφή ή σύνδεση μη εγγεγραμμένων χρηστών είναι προς το παρόν αποκλεισμένη. Παρακαλώ επικοινωνήστε με τον διαχειριστή.
login.oauth2RequestNotFound=Το αίτημα εξουσιοδότησης δεν βρέθηκε
login.oauth2InvalidUserInfoResponse=Μη έγκυρη απόκριση πληροφοριών χρήστη
login.oauth2invalidRequest=Μη έγκυρο αίτημα

View File

@ -572,8 +572,8 @@ login.invalid=Invalid username or password.
login.locked=Your account has been locked.
login.signinTitle=Please sign in
login.ssoSignIn=Login via Single Sign-on
login.oauth2AutoCreateDisabled=OAUTH2 Auto-Create User Disabled
login.oauth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
login.oAuth2AutoCreateDisabled=OAUTH2 Auto-Create User Disabled
login.oAuth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
login.oauth2RequestNotFound=Authorization request not found
login.oauth2InvalidUserInfoResponse=Invalid User Info Response
login.oauth2invalidRequest=Invalid Request

View File

@ -572,8 +572,8 @@ login.invalid=Invalid username or password.
login.locked=Your account has been locked.
login.signinTitle=Please sign in
login.ssoSignIn=Login via Single Sign-on
login.oauth2AutoCreateDisabled=OAUTH2 Auto-Create User Disabled
login.oauth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
login.oAuth2AutoCreateDisabled=OAUTH2 Auto-Create User Disabled
login.oAuth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
login.oauth2RequestNotFound=Authorization request not found
login.oauth2InvalidUserInfoResponse=Invalid User Info Response
login.oauth2invalidRequest=Invalid Request

View File

@ -572,8 +572,8 @@ login.invalid=Nombre de usuario o contraseña erróneos.
login.locked=Su cuenta se ha bloqueado.
login.signinTitle=Por favor, inicie sesión
login.ssoSignIn=Iniciar sesión a través del inicio de sesión único
login.oauth2AutoCreateDisabled=Usuario de creación automática de OAUTH2 DESACTIVADO
login.oauth2AdminBlockedUser=El registro o inicio de sesión de usuarios no registrados está actualmente bloqueado. Por favor, contáctese con el administrador.
login.oAuth2AutoCreateDisabled=Usuario de creación automática de OAUTH2 DESACTIVADO
login.oAuth2AdminBlockedUser=El registro o inicio de sesión de usuarios no registrados está actualmente bloqueado. Por favor, contáctese con el administrador.
login.oauth2RequestNotFound=Solicitud de autorización no encontrada
login.oauth2InvalidUserInfoResponse=Respuesta de información de usuario no válida
login.oauth2invalidRequest=Solicitud no válida

View File

@ -572,8 +572,8 @@ login.invalid=Okerreko erabiltzaile izena edo pasahitza.
login.locked=Zure kontua blokeatu egin da.
login.signinTitle=Mesedez, hasi saioa
login.ssoSignIn=Hasi saioa Saioa hasteko modu bakarraren bidez
login.oauth2AutoCreateDisabled=OAUTH2 Sortu automatikoki erabiltzailea desgaituta dago
login.oauth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
login.oAuth2AutoCreateDisabled=OAUTH2 Sortu automatikoki erabiltzailea desgaituta dago
login.oAuth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
login.oauth2RequestNotFound=Authorization request not found
login.oauth2InvalidUserInfoResponse=Invalid User Info Response
login.oauth2invalidRequest=Invalid Request

View File

@ -572,8 +572,8 @@ login.invalid=نام کاربری یا رمز عبور اشتباه است.
login.locked=حساب شما قفل شده است.
login.signinTitle=لطفاً وارد شوید
login.ssoSignIn=ورود از طریق Single Sign-on
login.oauth2AutoCreateDisabled=ایجاد خودکار کاربر با OAUTH2 غیرفعال است
login.oauth2AdminBlockedUser=ثبت‌نام یا ورود کاربران ثبت‌نشده در حال حاضر مسدود است. لطفاً با مدیر تماس بگیرید.
login.oAuth2AutoCreateDisabled=ایجاد خودکار کاربر با OAUTH2 غیرفعال است
login.oAuth2AdminBlockedUser=ثبت‌نام یا ورود کاربران ثبت‌نشده در حال حاضر مسدود است. لطفاً با مدیر تماس بگیرید.
login.oauth2RequestNotFound=درخواست احراز هویت پیدا نشد
login.oauth2InvalidUserInfoResponse=پاسخ اطلاعات کاربری نامعتبر است
login.oauth2invalidRequest=درخواست نامعتبر

View File

@ -572,8 +572,8 @@ login.invalid=Nom d'utilisateur ou mot de passe invalide.
login.locked=Votre compte a été verrouillé.
login.signinTitle=Veuillez vous connecter
login.ssoSignIn=Se connecter via l'authentification unique
login.oauth2AutoCreateDisabled=OAUTH2 Création automatique d'utilisateur désactivée
login.oauth2AdminBlockedUser=La création ou l'authentification d'utilisateurs non enregistrés est actuellement bloquée. Veuillez contacter l'administrateur.
login.oAuth2AutoCreateDisabled=OAUTH2 Création automatique d'utilisateur désactivée
login.oAuth2AdminBlockedUser=La création ou l'authentification d'utilisateurs non enregistrés est actuellement bloquée. Veuillez contacter l'administrateur.
login.oauth2RequestNotFound=Demande d'autorisation introuvable
login.oauth2InvalidUserInfoResponse=Réponse contenant les informations de l'utilisateur est invalide
login.oauth2invalidRequest=Requête invalide

View File

@ -572,8 +572,8 @@ login.invalid=अमान्य उपयोगकर्ता नाम या
login.locked=आपका खाता लॉक कर दिया गया है।
login.signinTitle=कृपया साइन इन करें
login.ssoSignIn=सिंगल साइन-ऑन के माध्यम से लॉगिन करें
login.oauth2AutoCreateDisabled=OAUTH2 स्वतः उपयोगकर्ता निर्माण अक्षम है
login.oauth2AdminBlockedUser=गैर-पंजीकृत उपयोगकर्ताओं का पंजीकरण या लॉगिन वर्तमान में अवरुद्ध है। कृपया व्यवस्थापक से संपर्क करें।
login.oAuth2AutoCreateDisabled=OAUTH2 स्वतः उपयोगकर्ता निर्माण अक्षम है
login.oAuth2AdminBlockedUser=गैर-पंजीकृत उपयोगकर्ताओं का पंजीकरण या लॉगिन वर्तमान में अवरुद्ध है। कृपया व्यवस्थापक से संपर्क करें।
login.oauth2RequestNotFound=प्राधिकरण अनुरोध नहीं मिला
login.oauth2InvalidUserInfoResponse=अमान्य उपयोगकर्ता जानकारी प्रतिक्रिया
login.oauth2invalidRequest=अमान्य अनुरोध

View File

@ -572,8 +572,8 @@ login.invalid=Neispravno korisničko ime ili zaporka.
login.locked=Vaš račun je zaključan.
login.signinTitle=Molimo vas da se prijavite
login.ssoSignIn=Prijavite se putem jedinstvene prijave
login.oauth2AutoCreateDisabled=OAUTH2 automatsko kreiranje korisnika je onemogućeno
login.oauth2AdminBlockedUser=Registracija ili prijava nekadreguiranih korisnika trenutno su blokirane. Molimo Vas da kontaktirate administratora.
login.oAuth2AutoCreateDisabled=OAUTH2 automatsko kreiranje korisnika je onemogućeno
login.oAuth2AdminBlockedUser=Registracija ili prijava nekadreguiranih korisnika trenutno su blokirane. Molimo Vas da kontaktirate administratora.
login.oauth2RequestNotFound=Zahtjev za autorizaciju nije pronađen
login.oauth2InvalidUserInfoResponse=Nevažeće informacije o korisniku
login.oauth2invalidRequest=Neispravan zahtjev

View File

@ -572,8 +572,8 @@ login.invalid=Érvénytelen felhasználónév vagy jelszó.
login.locked=A fiókja zárolva van.
login.signinTitle=Kérjük, jelentkezzen be
login.ssoSignIn=Bejelentkezés egyszeri bejelentkezéssel
login.oauth2AutoCreateDisabled=OAuth2 automatikus felhasználólétrehozás letiltva
login.oauth2AdminBlockedUser=A nem regisztrált felhasználók regisztrációja vagy bejelentkezése jelenleg le van tiltva. Kérjük, forduljon a rendszergazdához.
login.oAuth2AutoCreateDisabled=OAuth2 automatikus felhasználólétrehozás letiltva
login.oAuth2AdminBlockedUser=A nem regisztrált felhasználók regisztrációja vagy bejelentkezése jelenleg le van tiltva. Kérjük, forduljon a rendszergazdához.
login.oauth2RequestNotFound=A hitelesítési kérés nem található
login.oauth2InvalidUserInfoResponse=Érvénytelen felhasználói információ válasz
login.oauth2invalidRequest=Érvénytelen kérés

View File

@ -572,8 +572,8 @@ login.invalid=Nama pengguna atau kata sandi tidak valid.
login.locked=Akun Anda telah dikunci.
login.signinTitle=Silakan masuk
login.ssoSignIn=Masuk melalui Single Sign - on
login.oauth2AutoCreateDisabled=OAUTH2 Buat Otomatis Pengguna Dinonaktifkan
login.oauth2AdminBlockedUser=Registrasi atau login pengguna yang tidak terdaftar saat ini diblokir. Silakan hubungi administrator.
login.oAuth2AutoCreateDisabled=OAUTH2 Buat Otomatis Pengguna Dinonaktifkan
login.oAuth2AdminBlockedUser=Registrasi atau login pengguna yang tidak terdaftar saat ini diblokir. Silakan hubungi administrator.
login.oauth2RequestNotFound=Permintaan otorisasi tidak ditemukan
login.oauth2InvalidUserInfoResponse=Respons Info Pengguna Tidak Valid
login.oauth2invalidRequest=Permintaan Tidak Valid

View File

@ -572,8 +572,8 @@ login.invalid=Nome utente o password errati.
login.locked=Il tuo account è stato bloccato.
login.signinTitle=Per favore accedi
login.ssoSignIn=Accedi tramite Single Sign-on
login.oauth2AutoCreateDisabled=Creazione automatica utente OAUTH2 DISABILITATA
login.oauth2AdminBlockedUser=La registrazione o l'accesso degli utenti non registrati è attualmente bloccata. Si prega di contattare l'amministratore.
login.oAuth2AutoCreateDisabled=Creazione automatica utente OAUTH2 DISABILITATA
login.oAuth2AdminBlockedUser=La registrazione o l'accesso degli utenti non registrati è attualmente bloccata. Si prega di contattare l'amministratore.
login.oauth2RequestNotFound=Richiesta di autorizzazione non trovata
login.oauth2InvalidUserInfoResponse=Risposta relativa alle informazioni utente non valida
login.oauth2invalidRequest=Richiesta non valida

View File

@ -572,8 +572,8 @@ login.invalid=ユーザー名かパスワードが無効です。
login.locked=あなたのアカウントはロックされています。
login.signinTitle=サインインしてください
login.ssoSignIn=シングルサインオンでログイン
login.oauth2AutoCreateDisabled=OAuth 2自動作成ユーザーが無効
login.oauth2AdminBlockedUser=現在、未登録ユーザーの登録またはログインはブロックされています。管理者にお問い合わせください。
login.oAuth2AutoCreateDisabled=OAuth 2自動作成ユーザーが無効
login.oAuth2AdminBlockedUser=現在、未登録ユーザーの登録またはログインはブロックされています。管理者にお問い合わせください。
login.oauth2RequestNotFound=認証リクエストが見つかりません
login.oauth2InvalidUserInfoResponse=無効なユーザー情報の応答
login.oauth2invalidRequest=無効なリクエスト

View File

@ -572,8 +572,8 @@ login.invalid=사용자 이름 또는 비밀번호가 잘못되었습니다.
login.locked=계정이 잠겼습니다.
login.signinTitle=로그인해 주세요
login.ssoSignIn=단일 로그인으로 로그인
login.oauth2AutoCreateDisabled=OAuth2 사용자 자동 생성이 비활성화되었습니다
login.oauth2AdminBlockedUser=현재 미등록 사용자의 등록 또는 로그인이 차단되어 있습니다. 관리자에게 문의하세요.
login.oAuth2AutoCreateDisabled=OAuth2 사용자 자동 생성이 비활성화되었습니다
login.oAuth2AdminBlockedUser=현재 미등록 사용자의 등록 또는 로그인이 차단되어 있습니다. 관리자에게 문의하세요.
login.oauth2RequestNotFound=인증 요청을 찾을 수 없습니다
login.oauth2InvalidUserInfoResponse=잘못된 사용자 정보 응답
login.oauth2invalidRequest=잘못된 요청

View File

@ -572,8 +572,8 @@ login.invalid=Ongeldige gebruikersnaam of wachtwoord.
login.locked=Je account is geblokkeerd.
login.signinTitle=Gelieve in te loggen
login.ssoSignIn=Inloggen via Single Sign-on
login.oauth2AutoCreateDisabled=OAUTH2 Automatisch aanmaken gebruiker uitgeschakeld
login.oauth2AdminBlockedUser=Registratie of inloggen van niet-registreerde gebruikers is helaas momenteel geblokkeerd. Neem contact op met de beheerder.
login.oAuth2AutoCreateDisabled=OAUTH2 Automatisch aanmaken gebruiker uitgeschakeld
login.oAuth2AdminBlockedUser=Registratie of inloggen van niet-registreerde gebruikers is helaas momenteel geblokkeerd. Neem contact op met de beheerder.
login.oauth2RequestNotFound=Autorisatieverzoek niet gevonden
login.oauth2InvalidUserInfoResponse=Ongeldige reactie op gebruikersinfo
login.oauth2invalidRequest=Ongeldig verzoek

View File

@ -572,8 +572,8 @@ login.invalid=Ugyldig brukernavn eller passord.
login.locked=Kontoen din har blitt låst.
login.signinTitle=Vennligst logg inn
login.ssoSignIn=Logg inn via Enkel Pålogging
login.oauth2AutoCreateDisabled=OAUTH2 Auto-Opretting av bruker deaktivert
login.oauth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
login.oAuth2AutoCreateDisabled=OAUTH2 Auto-Opretting av bruker deaktivert
login.oAuth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
login.oauth2RequestNotFound=Autentiseringsforespørsel ikke funnet
login.oauth2InvalidUserInfoResponse=Ugyldig brukerinforespons
login.oauth2invalidRequest=Ugyldig forespørsel

View File

@ -572,8 +572,8 @@ login.invalid=Nieprawidłowe dane logowania
login.locked=Konto jest zablokowane
login.signinTitle=Zaloguj się
login.ssoSignIn=Zaloguj się za pomocą logowania jednokrotnego
login.oauth2AutoCreateDisabled=Wyłączono automatyczne tworzenie użytkownika OAUTH2
login.oauth2AdminBlockedUser=Rejestracja lub logowanie niezarejestrowanych użytkowników jest obecnie zablokowane. Prosimy o kontakt z administratorem.
login.oAuth2AutoCreateDisabled=Wyłączono automatyczne tworzenie użytkownika OAUTH2
login.oAuth2AdminBlockedUser=Rejestracja lub logowanie niezarejestrowanych użytkowników jest obecnie zablokowane. Prosimy o kontakt z administratorem.
login.oauth2RequestNotFound=Błąd logowania OAuth2
login.oauth2InvalidUserInfoResponse=Niewłaściwe dane logowania
login.oauth2invalidRequest=Nieprawidłowe żądanie

View File

@ -572,8 +572,8 @@ login.invalid=Usuário ou senha inválidos.
login.locked=Sua conta foi bloqueada.
login.signinTitle=Por favor, inicie a sessão
login.ssoSignIn=Iniciar sessão através de login único (SSO)
login.oauth2AutoCreateDisabled=Auto-Criar Usuário OAUTH2 Desativado
login.oauth2AdminBlockedUser=O registro ou login de usuários não registrados está atualmente bloqueado. Entre em contato com o administrador.
login.oAuth2AutoCreateDisabled=Auto-Criar Usuário OAUTH2 Desativado
login.oAuth2AdminBlockedUser=O registro ou login de usuários não registrados está atualmente bloqueado. Entre em contato com o administrador.
login.oauth2RequestNotFound=Solicitação de autorização não encontrada
login.oauth2InvalidUserInfoResponse=Resposta de informação de usuário inválida
login.oauth2invalidRequest=Requisição Inválida

View File

@ -572,8 +572,8 @@ login.invalid=Nome de utilizador ou palavra-passe inválidos.
login.locked=A sua conta foi bloqueada.
login.signinTitle=Por favor inicie sessão
login.ssoSignIn=Login via Single Sign-on
login.oauth2AutoCreateDisabled=Criação Automática de Utilizador OAUTH2 Desativada
login.oauth2AdminBlockedUser=O registo ou login de utilizadores não registados está atualmente bloqueado. Por favor contacte o administrador.
login.oAuth2AutoCreateDisabled=Criação Automática de Utilizador OAUTH2 Desativada
login.oAuth2AdminBlockedUser=O registo ou login de utilizadores não registados está atualmente bloqueado. Por favor contacte o administrador.
login.oauth2RequestNotFound=Pedido de autorização não encontrado
login.oauth2InvalidUserInfoResponse=Resposta de Informação de Utilizador Inválida
login.oauth2invalidRequest=Pedido Inválido

View File

@ -572,8 +572,8 @@ login.invalid=Nume de utilizator sau parolă invalidă.
login.locked=Contul tău a fost blocat.
login.signinTitle=Te rugăm să te autentifici
login.ssoSignIn=Conectare prin conectare unică
login.oauth2AutoCreateDisabled=OAUTH2 Creare automată utilizator dezactivată
login.oauth2AdminBlockedUser=Înregistrarea sau conectarea utilizatorilor neînregistrați este în prezent blocată. Te rugăm să contactezi administratorul.
login.oAuth2AutoCreateDisabled=OAUTH2 Creare automată utilizator dezactivată
login.oAuth2AdminBlockedUser=Înregistrarea sau conectarea utilizatorilor neînregistrați este în prezent blocată. Te rugăm să contactezi administratorul.
login.oauth2RequestNotFound=Cererea de autorizare nu a fost găsită
login.oauth2InvalidUserInfoResponse=Răspuns Invalid la Informațiile Utilizatorului
login.oauth2invalidRequest=Cerere Invalidă

View File

@ -572,8 +572,8 @@ login.invalid=Неверное имя пользователя или парол
login.locked=Ваша учетная запись заблокирована.
login.signinTitle=Пожалуйста, войдите
login.ssoSignIn=Вход через единый вход
login.oauth2AutoCreateDisabled=Автоматическое создание пользователей OAuth2 отключено
login.oauth2AdminBlockedUser=Регистрация или вход незарегистрированных пользователей в настоящее время заблокированы. Обратитесь к администратору.
login.oAuth2AutoCreateDisabled=Автоматическое создание пользователей OAuth2 отключено
login.oAuth2AdminBlockedUser=Регистрация или вход незарегистрированных пользователей в настоящее время заблокированы. Обратитесь к администратору.
login.oauth2RequestNotFound=Запрос авторизации не найден
login.oauth2InvalidUserInfoResponse=Недействительный ответ с информацией о пользователе
login.oauth2invalidRequest=Недействительный запрос

View File

@ -572,8 +572,8 @@ login.invalid=Neplatné používateľské meno alebo heslo.
login.locked=Váš účet bol uzamknutý.
login.signinTitle=Prosím, prihláste sa
login.ssoSignIn=Prihlásiť sa cez Single Sign-on
login.oauth2AutoCreateDisabled=Vytváranie používateľa cez OAUTH2 je zakázané
login.oauth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
login.oAuth2AutoCreateDisabled=Vytváranie používateľa cez OAUTH2 je zakázané
login.oAuth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
login.oauth2RequestNotFound=Authorization request not found
login.oauth2InvalidUserInfoResponse=Invalid User Info Response
login.oauth2invalidRequest=Invalid Request

View File

@ -572,8 +572,8 @@ login.invalid=Neveljavno uporabniško ime ali geslo.
login.locked=Vaš račun je bil zaklenjen.
login.signinTitle=Prosim prijavite se
login.ssoSignIn=Prijava prek enotne prijave
login.oauth2AutoCreateDisabled=OAUTH2 Samodejno ustvarjanje uporabnika onemogočeno
login.oauth2AdminBlockedUser=Registracija ali prijava neregistriranih uporabnikov je trenutno blokirana. Prosimo kontaktirajte skrbnika.
login.oAuth2AutoCreateDisabled=OAUTH2 Samodejno ustvarjanje uporabnika onemogočeno
login.oAuth2AdminBlockedUser=Registracija ali prijava neregistriranih uporabnikov je trenutno blokirana. Prosimo kontaktirajte skrbnika.
login.oauth2RequestNotFound=Zahteva za avtorizacijo ni bila najdena
login.oauth2InvalidUserInfoResponse=Neveljaven odgovor z informacijami o uporabniku
login.oauth2invalidRequest=Neveljavna zahteva

View File

@ -572,8 +572,8 @@ login.invalid=Neispravno korisničko ime ili lozinka.
login.locked=Vaš nalog je zaključan.
login.signinTitle=Molimo vas da se prijavite
login.ssoSignIn=Prijavite se putem jedinstvene prijave
login.oauth2AutoCreateDisabled=OAUTH2 automatsko kreiranje korisnika je onemogućeno
login.oauth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
login.oAuth2AutoCreateDisabled=OAUTH2 automatsko kreiranje korisnika je onemogućeno
login.oAuth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
login.oauth2RequestNotFound=Authorization request not found
login.oauth2InvalidUserInfoResponse=Invalid User Info Response
login.oauth2invalidRequest=Invalid Request

View File

@ -572,8 +572,8 @@ login.invalid=Ogiltigt användarnamn eller lösenord.
login.locked=Ditt konto har låsts.
login.signinTitle=Vänligen logga in
login.ssoSignIn=Logga in via enkel inloggning
login.oauth2AutoCreateDisabled=OAUTH2 Auto-skapa användare inaktiverad
login.oauth2AdminBlockedUser=Registrering eller inloggning av icke-registrerade användare är för närvarande blockerad. Kontakta administratören.
login.oAuth2AutoCreateDisabled=OAUTH2 Auto-skapa användare inaktiverad
login.oAuth2AdminBlockedUser=Registrering eller inloggning av icke-registrerade användare är för närvarande blockerad. Kontakta administratören.
login.oauth2RequestNotFound=Auktoriseringsbegäran hittades inte
login.oauth2InvalidUserInfoResponse=Ogiltigt svar på användarinformation
login.oauth2invalidRequest=Ogiltig begäran

View File

@ -572,8 +572,8 @@ login.invalid=ชื่อผู้ใช้หรือรหัสผ่าน
login.locked=บัญชีของคุณถูกล็อค
login.signinTitle=กรุณาลงชื่อเข้าใช้
login.ssoSignIn=เข้าสู่ระบบด้วย Single Sign-on
login.oauth2AutoCreateDisabled=การสร้างผู้ใช้ OAuth2 อัตโนมัติถูกปิดใช้งาน
login.oauth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
login.oAuth2AutoCreateDisabled=การสร้างผู้ใช้ OAuth2 อัตโนมัติถูกปิดใช้งาน
login.oAuth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
login.oauth2RequestNotFound=ไม่พบคำขอการอนุญาต
login.oauth2InvalidUserInfoResponse=การตอบกลับข้อมูลผู้ใช้ไม่ถูกต้อง
login.oauth2invalidRequest=คำขอไม่ถูกต้อง

View File

@ -572,8 +572,8 @@ login.invalid=Geçersiz kullanıcı adı veya şifre.
login.locked=Hesabınız kilitlendi.
login.signinTitle=Lütfen giriş yapınız.
login.ssoSignIn=Tek Oturum Açma ile Giriş Yap
login.oauth2AutoCreateDisabled=OAUTH2 Otomatik Oluşturma Kullanıcı Devre Dışı Bırakıldı
login.oauth2AdminBlockedUser=Kayıtlı olmayan kullanıcıların kayıt veya giriş yapması şu anda engellenmiştir. Lütfen yöneticiyle iletişime geçin.
login.oAuth2AutoCreateDisabled=OAUTH2 Otomatik Oluşturma Kullanıcı Devre Dışı Bırakıldı
login.oAuth2AdminBlockedUser=Kayıtlı olmayan kullanıcıların kayıt veya giriş yapması şu anda engellenmiştir. Lütfen yöneticiyle iletişime geçin.
login.oauth2RequestNotFound=Yetkilendirme isteği bulunamadı
login.oauth2InvalidUserInfoResponse=Geçersiz Kullanıcı Bilgisi Yanıtı
login.oauth2invalidRequest=Geçersiz İstek

View File

@ -572,8 +572,8 @@ login.invalid=Недійсне ім'я користувача або парол
login.locked=Ваш обліковий запис заблоковано.
login.signinTitle=Будь ласка, увійдіть
login.ssoSignIn=Увійти через єдиний вхід
login.oauth2AutoCreateDisabled=Автоматичне створення користувача OAUTH2 ВИМКНЕНО
login.oauth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
login.oAuth2AutoCreateDisabled=Автоматичне створення користувача OAUTH2 ВИМКНЕНО
login.oAuth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
login.oauth2RequestNotFound=Запит на авторизація не знайдено
login.oauth2InvalidUserInfoResponse=Недійсна відповідь з інформацією користувача
login.oauth2invalidRequest=Недійсний запит

View File

@ -572,8 +572,8 @@ login.invalid=Tên đăng nhập hoặc mật khẩu không hợp lệ.
login.locked=Tài khoản của bạn đã bị khóa.
login.signinTitle=Vui lòng đăng nhập
login.ssoSignIn=Đăng nhập qua Single Sign-on
login.oauth2AutoCreateDisabled=Tự động tạo người dùng OAUTH2 bị vô hiệu hóa
login.oauth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
login.oAuth2AutoCreateDisabled=Tự động tạo người dùng OAUTH2 bị vô hiệu hóa
login.oAuth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
login.oauth2RequestNotFound=Không tìm thấy yêu cầu ủy quyền
login.oauth2InvalidUserInfoResponse=Phản hồi thông tin người dùng không hợp lệ
login.oauth2invalidRequest=Yêu cầu không hợp lệ

View File

@ -572,8 +572,8 @@ login.invalid=སྤྱོད་མིང་ངམ་གསང་ཚིག་ན
login.locked=ཁྱེད་ཀྱི་ཐོ་མཛོད་ཟྭ་རྒྱག་བརྒྱབ་ཟིན།
login.signinTitle=ནང་འཛུལ་གནང་རོགས།
login.ssoSignIn=གཅིག་གྱུར་ནང་འཛུལ་བརྒྱུད་ནས་ནང་འཛུལ།
login.oauth2AutoCreateDisabled=OAUTH2 རང་འགུལ་སྤྱོད་མཁན་གསར་བཟོ་བཀག་སྡོམ་བྱས་ཟིན།
login.oauth2AdminBlockedUser=ད་ལྟ་ཐོ་འགོད་མ་བྱས་པའི་སྤྱོད་མཁན་གྱི་ཐོ་འགོད་དང་ནང་འཛུལ་བཀག་སྡོམ་བྱས་ཡོད། དོ་དམ་པར་འབྲེལ་བ་གནང་རོགས།
login.oAuth2AutoCreateDisabled=OAUTH2 རང་འགུལ་སྤྱོད་མཁན་གསར་བཟོ་བཀག་སྡོམ་བྱས་ཟིན།
login.oAuth2AdminBlockedUser=ད་ལྟ་ཐོ་འགོད་མ་བྱས་པའི་སྤྱོད་མཁན་གྱི་ཐོ་འགོད་དང་ནང་འཛུལ་བཀག་སྡོམ་བྱས་ཡོད། དོ་དམ་པར་འབྲེལ་བ་གནང་རོགས།
login.oauth2RequestNotFound=དབང་སྤྲོད་རེ་ཞུ་རྙེད་མ་བྱུང་།
login.oauth2InvalidUserInfoResponse=སྤྱོད་མཁན་གྱི་གནས་ཚུལ་ལན་འདེབས་ནོར་འཁྲུལ།
login.oauth2invalidRequest=རེ་ཞུ་ནོར་འཁྲུལ།

View File

@ -572,8 +572,8 @@ login.invalid=用户名或密码无效。
login.locked=您的账户已被锁定。
login.signinTitle=请登录
login.ssoSignIn=通过单点登录登录
login.oauth2AutoCreateDisabled=OAuth2 自动创建用户已禁用
login.oauth2AdminBlockedUser=目前已阻止未注册用户的注册或登录。请联系管理员。
login.oAuth2AutoCreateDisabled=OAuth2 自动创建用户已禁用
login.oAuth2AdminBlockedUser=目前已阻止未注册用户的注册或登录。请联系管理员。
login.oauth2RequestNotFound=找不到验证请求
login.oauth2InvalidUserInfoResponse=无效的用户信息响应
login.oauth2invalidRequest=无效请求

View File

@ -572,8 +572,8 @@ login.invalid=使用者名稱或密碼無效。
login.locked=您的帳號已被鎖定。
login.signinTitle=請登入
login.ssoSignIn=透過 SSO 單一登入
login.oauth2AutoCreateDisabled=OAuth 2.0 自動建立使用者功能已停用
login.oauth2AdminBlockedUser=目前不允許未註冊的使用者註冊或登入。請聯絡系統管理員。
login.oAuth2AutoCreateDisabled=OAuth 2.0 自動建立使用者功能已停用
login.oAuth2AdminBlockedUser=目前不允許未註冊的使用者註冊或登入。請聯絡系統管理員。
login.oauth2RequestNotFound=找不到驗證請求
login.oauth2InvalidUserInfoResponse=使用者資訊回應無效
login.oauth2invalidRequest=請求無效

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 &&
@ -104,8 +104,8 @@
<br>
<hr />
</div>
<div th:if="${erroroauth}" class="alert alert-danger text-center">
<div th:if="${erroroauth}" th:text="#{${erroroauth}}">OAuth2: Error Message</div>
<div th:if="${errorOAuth}" class="alert alert-danger text-center">
<div th:if="${errorOAuth}" th:text="#{${errorOAuth}}">OAuth2: Error Message</div>
</div>
<div th:if="${error}" class="alert alert-danger text-center">
@ -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>

View File

@ -0,0 +1,266 @@
package stirling.software.SPDF.config.security;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import stirling.software.SPDF.model.ApplicationProperties;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class CustomLogoutSuccessHandlerTest {
@Mock
private ApplicationProperties applicationProperties;
@InjectMocks
private CustomLogoutSuccessHandler customLogoutSuccessHandler;
@Test
void testSuccessfulLogout() throws IOException {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
String logoutPath = "/login?logout=true";
when(response.isCommitted()).thenReturn(false);
when(request.getContextPath()).thenReturn("");
when(response.encodeRedirectURL(logoutPath)).thenReturn(logoutPath);
customLogoutSuccessHandler.onLogoutSuccess(request, response, null);
verify(response).sendRedirect(logoutPath);
}
@Test
void testSuccessfulLogoutViaOAuth2() throws IOException {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
OAuth2AuthenticationToken oAuth2AuthenticationToken = mock(OAuth2AuthenticationToken.class);
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
ApplicationProperties.Security.OAUTH2 oauth = mock(ApplicationProperties.Security.OAUTH2.class);
when(response.isCommitted()).thenReturn(false);
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
when(request.getParameter("errorOAuth")).thenReturn(null);
when(request.getScheme()).thenReturn("http");
when(request.getServerName()).thenReturn("localhost");
when(request.getServerPort()).thenReturn(8080);
when(request.getContextPath()).thenReturn("");
when(applicationProperties.getSecurity()).thenReturn(security);
when(security.getOauth2()).thenReturn(oauth);
when(oAuth2AuthenticationToken.getAuthorizedClientRegistrationId()).thenReturn("test");
customLogoutSuccessHandler.onLogoutSuccess(request, response, oAuth2AuthenticationToken);
verify(response).sendRedirect("http://localhost:8080/login?logout=true");
}
@Test
void testUserIsDisabledRedirect() throws IOException {
String error = "userIsDisabled";
String url = "http://localhost:8080";
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
ApplicationProperties.Security.OAUTH2 oauth = mock(ApplicationProperties.Security.OAUTH2.class);
when(response.isCommitted()).thenReturn(false);
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
when(request.getParameter("errorOAuth")).thenReturn(null);
when(request.getParameter("oAuth2AutoCreateDisabled")).thenReturn(null);
when(request.getParameter("oAuth2AdminBlockedUser")).thenReturn(null);
when(request.getParameter(error)).thenReturn("true");
when(request.getScheme()).thenReturn("http");
when(request.getServerName()).thenReturn("localhost");
when(request.getServerPort()).thenReturn(8080);
when(request.getContextPath()).thenReturn("");
when(applicationProperties.getSecurity()).thenReturn(security);
when(security.getOauth2()).thenReturn(oauth);
when(authentication.getAuthorizedClientRegistrationId()).thenReturn("test");
customLogoutSuccessHandler.onLogoutSuccess(request, response, authentication);
verify(response).sendRedirect(url + "/login?errorOAuth=" + error);
}
@Test
void testUserAlreadyExistsWebRedirect() throws IOException {
String error = "oAuth2AuthenticationErrorWeb";
String errorPath = "userAlreadyExistsWeb";
String url = "http://localhost:8080";
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
ApplicationProperties.Security.OAUTH2 oauth = mock(ApplicationProperties.Security.OAUTH2.class);
when(response.isCommitted()).thenReturn(false);
when(request.getParameter(error)).thenReturn("true");
when(request.getScheme()).thenReturn("http");
when(request.getServerName()).thenReturn("localhost");
when(request.getServerPort()).thenReturn(8080);
when(request.getContextPath()).thenReturn("");
when(applicationProperties.getSecurity()).thenReturn(security);
when(security.getOauth2()).thenReturn(oauth);
when(authentication.getAuthorizedClientRegistrationId()).thenReturn("test");
customLogoutSuccessHandler.onLogoutSuccess(request, response, authentication);
verify(response).sendRedirect(url + "/login?errorOAuth=" + errorPath);
}
@Test
void testErrorOAuthRedirect() throws IOException {
String error = "testError";
String url = "http://localhost:8080";
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
ApplicationProperties.Security.OAUTH2 oauth = mock(ApplicationProperties.Security.OAUTH2.class);
when(response.isCommitted()).thenReturn(false);
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
when(request.getParameter("errorOAuth")).thenReturn("!!!" + error + "!!!");
when(request.getScheme()).thenReturn("http");
when(request.getServerName()).thenReturn("localhost");
when(request.getServerPort()).thenReturn(8080);
when(request.getContextPath()).thenReturn("");
when(applicationProperties.getSecurity()).thenReturn(security);
when(security.getOauth2()).thenReturn(oauth);
when(authentication.getAuthorizedClientRegistrationId()).thenReturn("test");
customLogoutSuccessHandler.onLogoutSuccess(request, response, authentication);
verify(response).sendRedirect(url + "/login?errorOAuth=" + error);
}
@Test
void testOAuth2AutoCreateDisabled() throws IOException {
String error = "oAuth2AutoCreateDisabled";
String url = "http://localhost:8080";
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
ApplicationProperties.Security.OAUTH2 oauth = mock(ApplicationProperties.Security.OAUTH2.class);
when(response.isCommitted()).thenReturn(false);
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
when(request.getParameter("errorOAuth")).thenReturn(null);
when(request.getParameter(error)).thenReturn("true");
when(request.getContextPath()).thenReturn(url);
when(request.getScheme()).thenReturn("http");
when(request.getServerName()).thenReturn("localhost");
when(request.getServerPort()).thenReturn(8080);
when(request.getContextPath()).thenReturn("");
when(applicationProperties.getSecurity()).thenReturn(security);
when(security.getOauth2()).thenReturn(oauth);
when(authentication.getAuthorizedClientRegistrationId()).thenReturn("test");
customLogoutSuccessHandler.onLogoutSuccess(request, response, authentication);
verify(response).sendRedirect(url + "/login?errorOAuth=" + error);
}
@Test
void testOAuth2Error() throws IOException {
String error = "test";
String url = "http://localhost:8080";
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
ApplicationProperties.Security.OAUTH2 oauth = mock(ApplicationProperties.Security.OAUTH2.class);
when(response.isCommitted()).thenReturn(false);
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
when(request.getParameter("errorOAuth")).thenReturn(null);
when(request.getParameter("oAuth2AutoCreateDisabled")).thenReturn(null);
when(request.getParameter("oAuth2AdminBlockedUser")).thenReturn(null);
when(request.getParameter("userIsDisabled")).thenReturn(null);
when(request.getParameter("error")).thenReturn("!@$!@£" + error + "£$%^*$");
when(request.getScheme()).thenReturn("http");
when(request.getServerName()).thenReturn("localhost");
when(request.getServerPort()).thenReturn(8080);
when(request.getContextPath()).thenReturn("");
when(applicationProperties.getSecurity()).thenReturn(security);
when(security.getOauth2()).thenReturn(oauth);
when(authentication.getAuthorizedClientRegistrationId()).thenReturn("test");
customLogoutSuccessHandler.onLogoutSuccess(request, response, authentication);
verify(response).sendRedirect(url + "/login?errorOAuth=" + error);
}
@Test
void testOAuth2BadCredentialsError() throws IOException {
String error = "badCredentials";
String url = "http://localhost:8080";
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
ApplicationProperties.Security.OAUTH2 oauth = mock(ApplicationProperties.Security.OAUTH2.class);
when(response.isCommitted()).thenReturn(false);
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
when(request.getParameter("errorOAuth")).thenReturn(null);
when(request.getParameter("oAuth2AutoCreateDisabled")).thenReturn(null);
when(request.getParameter("oAuth2AdminBlockedUser")).thenReturn(null);
when(request.getParameter("userIsDisabled")).thenReturn(null);
when(request.getParameter("error")).thenReturn(null);
when(request.getParameter(error)).thenReturn("true");
when(request.getScheme()).thenReturn("http");
when(request.getServerName()).thenReturn("localhost");
when(request.getServerPort()).thenReturn(8080);
when(request.getContextPath()).thenReturn("");
when(applicationProperties.getSecurity()).thenReturn(security);
when(security.getOauth2()).thenReturn(oauth);
when(authentication.getAuthorizedClientRegistrationId()).thenReturn("test");
customLogoutSuccessHandler.onLogoutSuccess(request, response, authentication);
verify(response).sendRedirect(url + "/login?errorOAuth=" + error);
}
@Test
void testOAuth2AdminBlockedUser() throws IOException {
String error = "oAuth2AdminBlockedUser";
String url = "http://localhost:8080";
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
ApplicationProperties.Security.OAUTH2 oauth = mock(ApplicationProperties.Security.OAUTH2.class);
when(response.isCommitted()).thenReturn(false);
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
when(request.getParameter("errorOAuth")).thenReturn(null);
when(request.getParameter("oAuth2AutoCreateDisabled")).thenReturn(null);
when(request.getParameter(error)).thenReturn("true");
when(request.getScheme()).thenReturn("http");
when(request.getServerName()).thenReturn("localhost");
when(request.getServerPort()).thenReturn(8080);
when(request.getContextPath()).thenReturn("");
when(applicationProperties.getSecurity()).thenReturn(security);
when(security.getOauth2()).thenReturn(oauth);
when(authentication.getAuthorizedClientRegistrationId()).thenReturn("test");
customLogoutSuccessHandler.onLogoutSuccess(request, response, authentication);
verify(response).sendRedirect(url + "/login?errorOAuth=" + error);
}
}

View File

@ -0,0 +1,58 @@
package stirling.software.SPDF.utils.validation;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.junit.jupiter.MockitoExtension;
import stirling.software.SPDF.model.provider.GitHubProvider;
import stirling.software.SPDF.model.provider.GoogleProvider;
import stirling.software.SPDF.model.provider.KeycloakProvider;
import stirling.software.SPDF.model.provider.Provider;
import java.util.List;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class ValidatorTest {
@Test
void testSuccessfulValidation() {
var provider = mock(GitHubProvider.class);
when(provider.getClientId()).thenReturn("clientId");
when(provider.getClientSecret()).thenReturn("clientSecret");
when(provider.getScopes()).thenReturn(List.of("read:user"));
when(provider.getUseAsUsername()).thenReturn("email");
assertTrue(Validator.validateProvider(provider));
}
@ParameterizedTest
@MethodSource("providerParams")
void testUnsuccessfulValidation(Provider provider) {
assertFalse(Validator.validateProvider(provider));
}
public static Stream<Arguments> providerParams() {
Provider generic = null;
var google = new GoogleProvider(null, "clientSecret", List.of("scope"), "email");
var github = new GitHubProvider("clientId", "", List.of("scope"), "login");
var keycloak = new KeycloakProvider("issuer", "clientId", "clientSecret", List.of("scope"), "email");
keycloak.setUseAsUsername(null);
return Stream.of(
Arguments.of(generic),
Arguments.of(google),
Arguments.of(github),
Arguments.of(keycloak)
);
}
}