added: Differentiate login methods and more (#1471)
- Added Portuguese in the table (README.md) - ApplicationProperties.class diluted, provider outsourced to its own class - Added UnsupportedProviderException to indicate a meaningful error - Closes #1357 - Closes #1238
This commit is contained in:
parent
baa9410242
commit
036c10fc27
10 changed files with 368 additions and 317 deletions
|
@ -178,6 +178,7 @@ Stirling PDF currently supports 32!
|
||||||
| Romanian (Română) (ro_RO) | ![39%](https://geps.dev/progress/39) |
|
| Romanian (Română) (ro_RO) | ![39%](https://geps.dev/progress/39) |
|
||||||
| Korean (한국어) (ko_KR) | ![86%](https://geps.dev/progress/86) |
|
| Korean (한국어) (ko_KR) | ![86%](https://geps.dev/progress/86) |
|
||||||
| Portuguese Brazilian (Português) (pt_BR) | ![61%](https://geps.dev/progress/61) |
|
| Portuguese Brazilian (Português) (pt_BR) | ![61%](https://geps.dev/progress/61) |
|
||||||
|
| Portuguese (Português) (pt_PT) | ![61%](https://geps.dev/progress/61) |
|
||||||
| Russian (Русский) (ru_RU) | ![86%](https://geps.dev/progress/86) |
|
| Russian (Русский) (ru_RU) | ![86%](https://geps.dev/progress/86) |
|
||||||
| Basque (Euskara) (eu_ES) | ![63%](https://geps.dev/progress/63) |
|
| Basque (Euskara) (eu_ES) | ![63%](https://geps.dev/progress/63) |
|
||||||
| Japanese (日本語) (ja_JP) | ![92%](https://geps.dev/progress/92) |
|
| Japanese (日本語) (ja_JP) | ![92%](https://geps.dev/progress/92) |
|
||||||
|
|
|
@ -38,12 +38,12 @@ import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationS
|
||||||
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2LogoutSuccessHandler;
|
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2LogoutSuccessHandler;
|
||||||
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2UserService;
|
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2UserService;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.GithubProvider;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.GoogleProvider;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.KeycloakProvider;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
|
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2.Client;
|
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2.Client;
|
||||||
import stirling.software.SPDF.model.User;
|
import stirling.software.SPDF.model.User;
|
||||||
|
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.JPATokenRepositoryImpl;
|
import stirling.software.SPDF.repository.JPATokenRepositoryImpl;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
|
|
|
@ -16,6 +16,7 @@ import jakarta.servlet.http.HttpSession;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
|
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
|
||||||
import stirling.software.SPDF.model.Provider;
|
import stirling.software.SPDF.model.Provider;
|
||||||
|
import stirling.software.SPDF.model.provider.UnsupportedProviderException;
|
||||||
import stirling.software.SPDF.utils.UrlUtils;
|
import stirling.software.SPDF.utils.UrlUtils;
|
||||||
|
|
||||||
public class CustomOAuth2LogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
public class CustomOAuth2LogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
|
||||||
|
@ -51,8 +52,8 @@ public class CustomOAuth2LogoutSuccessHandler extends SimpleUrlLogoutSuccessHand
|
||||||
Provider provider = oauth.getClient().get(registrationId);
|
Provider provider = oauth.getClient().get(registrationId);
|
||||||
issuer = provider.getIssuer();
|
issuer = provider.getIssuer();
|
||||||
clientId = provider.getClientId();
|
clientId = provider.getClientId();
|
||||||
} catch (Exception e) {
|
} catch (UnsupportedProviderException e) {
|
||||||
logger.error("exception", e);
|
logger.error(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -24,14 +24,14 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.GithubProvider;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.GoogleProvider;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.KeycloakProvider;
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
|
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2.Client;
|
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2.Client;
|
||||||
import stirling.software.SPDF.model.Authority;
|
import stirling.software.SPDF.model.Authority;
|
||||||
import stirling.software.SPDF.model.Role;
|
import stirling.software.SPDF.model.Role;
|
||||||
import stirling.software.SPDF.model.User;
|
import stirling.software.SPDF.model.User;
|
||||||
|
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;
|
import stirling.software.SPDF.repository.UserRepository;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
|
@ -74,6 +74,7 @@ public class AccountWebController {
|
||||||
}
|
}
|
||||||
model.addAttribute("providerlist", providerList);
|
model.addAttribute("providerlist", providerList);
|
||||||
|
|
||||||
|
model.addAttribute("loginMethod", applicationProperties.getSecurity().getLoginMethod());
|
||||||
model.addAttribute(
|
model.addAttribute(
|
||||||
"oAuth2Enabled", applicationProperties.getSecurity().getOAUTH2().getEnabled());
|
"oAuth2Enabled", applicationProperties.getSecurity().getOAUTH2().getEnabled());
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,10 @@ import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.PropertySource;
|
import org.springframework.context.annotation.PropertySource;
|
||||||
|
|
||||||
import stirling.software.SPDF.config.YamlPropertySourceFactory;
|
import stirling.software.SPDF.config.YamlPropertySourceFactory;
|
||||||
|
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.UnsupportedProviderException;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConfigurationProperties(prefix = "")
|
@ConfigurationProperties(prefix = "")
|
||||||
|
@ -128,6 +132,15 @@ public class ApplicationProperties {
|
||||||
private OAUTH2 oauth2;
|
private OAUTH2 oauth2;
|
||||||
private int loginAttemptCount;
|
private int loginAttemptCount;
|
||||||
private long loginResetTimeMinutes;
|
private long loginResetTimeMinutes;
|
||||||
|
private String loginMethod = "all";
|
||||||
|
|
||||||
|
public String getLoginMethod() {
|
||||||
|
return loginMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoginMethod(String loginMethod) {
|
||||||
|
this.loginMethod = loginMethod;
|
||||||
|
}
|
||||||
|
|
||||||
public int getLoginAttemptCount() {
|
public int getLoginAttemptCount() {
|
||||||
return loginAttemptCount;
|
return loginAttemptCount;
|
||||||
|
@ -187,6 +200,8 @@ public class ApplicationProperties {
|
||||||
+ initialLogin
|
+ initialLogin
|
||||||
+ ", csrfDisabled="
|
+ ", csrfDisabled="
|
||||||
+ csrfDisabled
|
+ csrfDisabled
|
||||||
|
+ ", loginMethod="
|
||||||
|
+ loginMethod
|
||||||
+ "]";
|
+ "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,7 +370,7 @@ public class ApplicationProperties {
|
||||||
private GithubProvider github = new GithubProvider();
|
private GithubProvider github = new GithubProvider();
|
||||||
private KeycloakProvider keycloak = new KeycloakProvider();
|
private KeycloakProvider keycloak = new KeycloakProvider();
|
||||||
|
|
||||||
public Provider get(String registrationId) throws Exception {
|
public Provider get(String registrationId) throws UnsupportedProviderException {
|
||||||
switch (registrationId.toLowerCase()) {
|
switch (registrationId.toLowerCase()) {
|
||||||
case "google":
|
case "google":
|
||||||
return getGoogle();
|
return getGoogle();
|
||||||
|
@ -366,7 +381,8 @@ public class ApplicationProperties {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
throw new Exception("Provider not supported, use custom setting.");
|
throw new UnsupportedProviderException(
|
||||||
|
"Logout from the provider is not supported? Report it at https://github.com/Stirling-Tools/Stirling-PDF/issues");
|
||||||
}
|
}
|
||||||
|
|
||||||
public GoogleProvider getGoogle() {
|
public GoogleProvider getGoogle() {
|
||||||
|
@ -407,311 +423,6 @@ public class ApplicationProperties {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class GoogleProvider extends Provider {
|
|
||||||
|
|
||||||
private static final String authorizationUri =
|
|
||||||
"https://accounts.google.com/o/oauth2/v2/auth";
|
|
||||||
private static final String tokenUri = "https://www.googleapis.com/oauth2/v4/token";
|
|
||||||
private static final String userInfoUri =
|
|
||||||
"https://www.googleapis.com/oauth2/v3/userinfo?alt=json";
|
|
||||||
|
|
||||||
public String getAuthorizationuri() {
|
|
||||||
return authorizationUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTokenuri() {
|
|
||||||
return tokenUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUserinfouri() {
|
|
||||||
return userInfoUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String clientId;
|
|
||||||
private String clientSecret;
|
|
||||||
private Collection<String> scopes = new ArrayList<>();
|
|
||||||
private String useAsUsername = "email";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getClientId() {
|
|
||||||
return this.clientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setClientId(String clientId) {
|
|
||||||
this.clientId = clientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getClientSecret() {
|
|
||||||
return this.clientSecret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setClientSecret(String clientSecret) {
|
|
||||||
this.clientSecret = clientSecret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<String> 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 void setScopes(String scopes) {
|
|
||||||
this.scopes =
|
|
||||||
Arrays.stream(scopes.split(",")).map(String::trim).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUseAsUsername() {
|
|
||||||
return this.useAsUsername;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setUseAsUsername(String useAsUsername) {
|
|
||||||
this.useAsUsername = useAsUsername;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Google [clientId="
|
|
||||||
+ clientId
|
|
||||||
+ ", clientSecret="
|
|
||||||
+ (clientSecret != null && !clientSecret.isEmpty() ? "MASKED" : "NULL")
|
|
||||||
+ ", scopes="
|
|
||||||
+ scopes
|
|
||||||
+ ", useAsUsername="
|
|
||||||
+ useAsUsername
|
|
||||||
+ "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "google";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getClientName() {
|
|
||||||
return "Google";
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSettingsValid() {
|
|
||||||
return super.isValid(this.getClientId(), "clientId")
|
|
||||||
&& super.isValid(this.getClientSecret(), "clientSecret")
|
|
||||||
&& super.isValid(this.getScopes(), "scopes")
|
|
||||||
&& isValid(this.getUseAsUsername(), "useAsUsername");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class GithubProvider extends Provider {
|
|
||||||
private static final String authorizationUri = "https://github.com/login/oauth/authorize";
|
|
||||||
private static final String tokenUri = "https://github.com/login/oauth/access_token";
|
|
||||||
private static final String userInfoUri = "https://api.github.com/user";
|
|
||||||
|
|
||||||
public String getAuthorizationuri() {
|
|
||||||
return authorizationUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTokenuri() {
|
|
||||||
return tokenUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUserinfouri() {
|
|
||||||
return userInfoUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String clientId;
|
|
||||||
private String clientSecret;
|
|
||||||
private Collection<String> scopes = new ArrayList<>();
|
|
||||||
private String useAsUsername = "login";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getIssuer() {
|
|
||||||
return new String();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setIssuer(String issuer) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getClientId() {
|
|
||||||
return this.clientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setClientId(String clientId) {
|
|
||||||
this.clientId = clientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getClientSecret() {
|
|
||||||
return this.clientSecret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setClientSecret(String clientSecret) {
|
|
||||||
this.clientSecret = clientSecret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<String> getScopes() {
|
|
||||||
if (scopes == null || scopes.isEmpty()) {
|
|
||||||
scopes = new ArrayList<>();
|
|
||||||
scopes.add("read:user");
|
|
||||||
}
|
|
||||||
return scopes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setScopes(String scopes) {
|
|
||||||
this.scopes =
|
|
||||||
Arrays.stream(scopes.split(",")).map(String::trim).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUseAsUsername() {
|
|
||||||
return this.useAsUsername;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setUseAsUsername(String useAsUsername) {
|
|
||||||
this.useAsUsername = useAsUsername;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "GitHub [clientId="
|
|
||||||
+ clientId
|
|
||||||
+ ", clientSecret="
|
|
||||||
+ (clientSecret != null && !clientSecret.isEmpty() ? "MASKED" : "NULL")
|
|
||||||
+ ", scopes="
|
|
||||||
+ scopes
|
|
||||||
+ ", useAsUsername="
|
|
||||||
+ useAsUsername
|
|
||||||
+ "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "github";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getClientName() {
|
|
||||||
return "GitHub";
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSettingsValid() {
|
|
||||||
return super.isValid(this.getClientId(), "clientId")
|
|
||||||
&& super.isValid(this.getClientSecret(), "clientSecret")
|
|
||||||
&& super.isValid(this.getScopes(), "scopes")
|
|
||||||
&& isValid(this.getUseAsUsername(), "useAsUsername");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class KeycloakProvider extends Provider {
|
|
||||||
private String issuer;
|
|
||||||
private String clientId;
|
|
||||||
private String clientSecret;
|
|
||||||
private Collection<String> scopes = new ArrayList<>();
|
|
||||||
private String useAsUsername = "email";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getIssuer() {
|
|
||||||
return this.issuer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setIssuer(String issuer) {
|
|
||||||
this.issuer = issuer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getClientId() {
|
|
||||||
return this.clientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setClientId(String clientId) {
|
|
||||||
this.clientId = clientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getClientSecret() {
|
|
||||||
return this.clientSecret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setClientSecret(String clientSecret) {
|
|
||||||
this.clientSecret = clientSecret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<String> getScopes() {
|
|
||||||
if (scopes == null || scopes.isEmpty()) {
|
|
||||||
scopes = new ArrayList<>();
|
|
||||||
scopes.add("profile");
|
|
||||||
scopes.add("email");
|
|
||||||
}
|
|
||||||
return scopes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setScopes(String scopes) {
|
|
||||||
this.scopes =
|
|
||||||
Arrays.stream(scopes.split(",")).map(String::trim).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUseAsUsername() {
|
|
||||||
return this.useAsUsername;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setUseAsUsername(String useAsUsername) {
|
|
||||||
this.useAsUsername = useAsUsername;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Keycloak [issuer="
|
|
||||||
+ issuer
|
|
||||||
+ ", clientId="
|
|
||||||
+ clientId
|
|
||||||
+ ", clientSecret="
|
|
||||||
+ (clientSecret != null && !clientSecret.isEmpty() ? "MASKED" : "NULL")
|
|
||||||
+ ", scopes="
|
|
||||||
+ scopes
|
|
||||||
+ ", useAsUsername="
|
|
||||||
+ useAsUsername
|
|
||||||
+ "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "keycloak";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getClientName() {
|
|
||||||
return "Keycloak";
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSettingsValid() {
|
|
||||||
return isValid(this.getIssuer(), "issuer")
|
|
||||||
&& isValid(this.getClientId(), "clientId")
|
|
||||||
&& isValid(this.getClientSecret(), "clientSecret")
|
|
||||||
&& isValid(this.getScopes(), "scopes")
|
|
||||||
&& isValid(this.getUseAsUsername(), "useAsUsername");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class System {
|
public static class System {
|
||||||
private String defaultLocale;
|
private String defaultLocale;
|
||||||
private Boolean googlevisibility;
|
private Boolean googlevisibility;
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
package stirling.software.SPDF.model.provider;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import stirling.software.SPDF.model.Provider;
|
||||||
|
|
||||||
|
public class GithubProvider extends Provider {
|
||||||
|
|
||||||
|
private static final String authorizationUri = "https://github.com/login/oauth/authorize";
|
||||||
|
private static final String tokenUri = "https://github.com/login/oauth/access_token";
|
||||||
|
private static final String userInfoUri = "https://api.github.com/user";
|
||||||
|
|
||||||
|
public String getAuthorizationuri() {
|
||||||
|
return authorizationUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTokenuri() {
|
||||||
|
return tokenUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserinfouri() {
|
||||||
|
return userInfoUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String clientId;
|
||||||
|
private String clientSecret;
|
||||||
|
private Collection<String> scopes = new ArrayList<>();
|
||||||
|
private String useAsUsername = "login";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIssuer() {
|
||||||
|
return new String();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setIssuer(String issuer) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClientId() {
|
||||||
|
return this.clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setClientId(String clientId) {
|
||||||
|
this.clientId = clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClientSecret() {
|
||||||
|
return this.clientSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setClientSecret(String clientSecret) {
|
||||||
|
this.clientSecret = clientSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> getScopes() {
|
||||||
|
if (scopes == null || scopes.isEmpty()) {
|
||||||
|
scopes = new ArrayList<>();
|
||||||
|
scopes.add("read:user");
|
||||||
|
}
|
||||||
|
return scopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setScopes(String scopes) {
|
||||||
|
this.scopes =
|
||||||
|
Arrays.stream(scopes.split(",")).map(String::trim).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUseAsUsername() {
|
||||||
|
return this.useAsUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUseAsUsername(String useAsUsername) {
|
||||||
|
this.useAsUsername = useAsUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "GitHub [clientId="
|
||||||
|
+ clientId
|
||||||
|
+ ", clientSecret="
|
||||||
|
+ (clientSecret != null && !clientSecret.isEmpty() ? "MASKED" : "NULL")
|
||||||
|
+ ", scopes="
|
||||||
|
+ scopes
|
||||||
|
+ ", useAsUsername="
|
||||||
|
+ useAsUsername
|
||||||
|
+ "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "github";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClientName() {
|
||||||
|
return "GitHub";
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSettingsValid() {
|
||||||
|
return super.isValid(this.getClientId(), "clientId")
|
||||||
|
&& super.isValid(this.getClientSecret(), "clientSecret")
|
||||||
|
&& super.isValid(this.getScopes(), "scopes")
|
||||||
|
&& isValid(this.getUseAsUsername(), "useAsUsername");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
package stirling.software.SPDF.model.provider;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import stirling.software.SPDF.model.Provider;
|
||||||
|
|
||||||
|
public class GoogleProvider extends Provider {
|
||||||
|
|
||||||
|
private static final String authorizationUri = "https://accounts.google.com/o/oauth2/v2/auth";
|
||||||
|
private static final String tokenUri = "https://www.googleapis.com/oauth2/v4/token";
|
||||||
|
private static final String userInfoUri =
|
||||||
|
"https://www.googleapis.com/oauth2/v3/userinfo?alt=json";
|
||||||
|
|
||||||
|
public String getAuthorizationuri() {
|
||||||
|
return authorizationUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTokenuri() {
|
||||||
|
return tokenUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserinfouri() {
|
||||||
|
return userInfoUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String clientId;
|
||||||
|
private String clientSecret;
|
||||||
|
private Collection<String> scopes = new ArrayList<>();
|
||||||
|
private String useAsUsername = "email";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClientId() {
|
||||||
|
return this.clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setClientId(String clientId) {
|
||||||
|
this.clientId = clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClientSecret() {
|
||||||
|
return this.clientSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setClientSecret(String clientSecret) {
|
||||||
|
this.clientSecret = clientSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> 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 void setScopes(String scopes) {
|
||||||
|
this.scopes =
|
||||||
|
Arrays.stream(scopes.split(",")).map(String::trim).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUseAsUsername() {
|
||||||
|
return this.useAsUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUseAsUsername(String useAsUsername) {
|
||||||
|
this.useAsUsername = useAsUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Google [clientId="
|
||||||
|
+ clientId
|
||||||
|
+ ", clientSecret="
|
||||||
|
+ (clientSecret != null && !clientSecret.isEmpty() ? "MASKED" : "NULL")
|
||||||
|
+ ", scopes="
|
||||||
|
+ scopes
|
||||||
|
+ ", useAsUsername="
|
||||||
|
+ useAsUsername
|
||||||
|
+ "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "google";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClientName() {
|
||||||
|
return "Google";
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSettingsValid() {
|
||||||
|
return super.isValid(this.getClientId(), "clientId")
|
||||||
|
&& super.isValid(this.getClientSecret(), "clientSecret")
|
||||||
|
&& super.isValid(this.getScopes(), "scopes")
|
||||||
|
&& isValid(this.getUseAsUsername(), "useAsUsername");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
package stirling.software.SPDF.model.provider;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import stirling.software.SPDF.model.Provider;
|
||||||
|
|
||||||
|
public class KeycloakProvider extends Provider {
|
||||||
|
|
||||||
|
private String issuer;
|
||||||
|
private String clientId;
|
||||||
|
private String clientSecret;
|
||||||
|
private Collection<String> scopes = new ArrayList<>();
|
||||||
|
private String useAsUsername = "email";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIssuer() {
|
||||||
|
return this.issuer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setIssuer(String issuer) {
|
||||||
|
this.issuer = issuer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClientId() {
|
||||||
|
return this.clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setClientId(String clientId) {
|
||||||
|
this.clientId = clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClientSecret() {
|
||||||
|
return this.clientSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setClientSecret(String clientSecret) {
|
||||||
|
this.clientSecret = clientSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> getScopes() {
|
||||||
|
if (scopes == null || scopes.isEmpty()) {
|
||||||
|
scopes = new ArrayList<>();
|
||||||
|
scopes.add("profile");
|
||||||
|
scopes.add("email");
|
||||||
|
}
|
||||||
|
return scopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setScopes(String scopes) {
|
||||||
|
this.scopes =
|
||||||
|
Arrays.stream(scopes.split(",")).map(String::trim).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUseAsUsername() {
|
||||||
|
return this.useAsUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUseAsUsername(String useAsUsername) {
|
||||||
|
this.useAsUsername = useAsUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Keycloak [issuer="
|
||||||
|
+ issuer
|
||||||
|
+ ", clientId="
|
||||||
|
+ clientId
|
||||||
|
+ ", clientSecret="
|
||||||
|
+ (clientSecret != null && !clientSecret.isEmpty() ? "MASKED" : "NULL")
|
||||||
|
+ ", scopes="
|
||||||
|
+ scopes
|
||||||
|
+ ", useAsUsername="
|
||||||
|
+ useAsUsername
|
||||||
|
+ "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "keycloak";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClientName() {
|
||||||
|
return "Keycloak";
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSettingsValid() {
|
||||||
|
return isValid(this.getIssuer(), "issuer")
|
||||||
|
&& isValid(this.getClientId(), "clientId")
|
||||||
|
&& isValid(this.getClientSecret(), "clientSecret")
|
||||||
|
&& isValid(this.getScopes(), "scopes")
|
||||||
|
&& isValid(this.getUseAsUsername(), "useAsUsername");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package stirling.software.SPDF.model.provider;
|
||||||
|
|
||||||
|
public class UnsupportedProviderException extends Exception {
|
||||||
|
public UnsupportedProviderException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
|
@ -114,7 +114,7 @@
|
||||||
<img class="mb-4" src="favicon.svg" alt="favicon" width="144" height="144">
|
<img class="mb-4" src="favicon.svg" alt="favicon" width="144" height="144">
|
||||||
|
|
||||||
<h1 class="h1 mb-3 fw-normal" th:text="${@appName}">Stirling-PDF</h1>
|
<h1 class="h1 mb-3 fw-normal" th:text="${@appName}">Stirling-PDF</h1>
|
||||||
<div th:if="${oAuth2Enabled}">
|
<div th:if="${oAuth2Enabled} and (${loginMethod} == 'all' or ${loginMethod} == 'oauth2')">
|
||||||
<a href="#" class="w-100 btn btn-lg btn-primary" data-bs-toggle="modal" data-bs-target="#loginsModal" th:text="#{login.ssoSignIn}">Login Via SSO</a>
|
<a href="#" class="w-100 btn btn-lg btn-primary" data-bs-toggle="modal" data-bs-target="#loginsModal" th:text="#{login.ssoSignIn}">Login Via SSO</a>
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
@ -134,7 +134,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<form th:action="@{login}" method="post">
|
<form th:if="${loginMethod} == 'all' or ${loginMethod} == 'normal'" th:action="@{login}" method="post">
|
||||||
<h2 class="h5 mb-3 fw-normal" th:text="#{login.signinTitle}">Please sign in</h2>
|
<h2 class="h5 mb-3 fw-normal" th:text="#{login.signinTitle}">Please sign in</h2>
|
||||||
<div class="form-floating">
|
<div class="form-floating">
|
||||||
<input type="text" class="form-control" id="username" name="username" placeholder="admin">
|
<input type="text" class="form-control" id="username" name="username" placeholder="admin">
|
||||||
|
|
Loading…
Reference in a new issue