-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
535 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
169 changes: 169 additions & 0 deletions
169
src/main/java/de/aservo/confapi/jira/model/util/AuthenticationIdpBeanUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
package de.aservo.confapi.jira.model.util; | ||
|
||
import com.atlassian.plugins.authentication.api.config.IdpConfig; | ||
import com.atlassian.plugins.authentication.api.config.SsoType; | ||
import com.atlassian.plugins.authentication.api.config.oidc.OidcConfig; | ||
import com.atlassian.plugins.authentication.api.config.saml.SamlConfig; | ||
import de.aservo.confapi.commons.exception.BadRequestException; | ||
import de.aservo.confapi.commons.exception.InternalServerErrorException; | ||
import de.aservo.confapi.commons.model.AbstractAuthenticationIdpBean; | ||
import de.aservo.confapi.commons.model.AuthenticationIdpOidcBean; | ||
import de.aservo.confapi.commons.model.AuthenticationIdpSamlBean; | ||
|
||
public class AuthenticationIdpBeanUtil { | ||
|
||
public static IdpConfig toIdpConfig( | ||
final AbstractAuthenticationIdpBean authenticationIdpBean) { | ||
|
||
return toIdpConfig(authenticationIdpBean, null); | ||
} | ||
|
||
public static IdpConfig toIdpConfig( | ||
final AbstractAuthenticationIdpBean authenticationIdpBean, | ||
final IdpConfig existingIdpConfig) { | ||
|
||
if (authenticationIdpBean instanceof AuthenticationIdpOidcBean) { | ||
return toOidcConfig((AuthenticationIdpOidcBean) authenticationIdpBean, existingIdpConfig); | ||
} | ||
|
||
throw new BadRequestException("IDP types other than OIDC are not (yet) supported"); | ||
} | ||
|
||
private static OidcConfig toOidcConfig( | ||
final AuthenticationIdpOidcBean authenticationIdpOidcBean, | ||
final IdpConfig existingIdpConfig) { | ||
|
||
final OidcConfig.Builder oidcConfigBuilder; | ||
|
||
if (existingIdpConfig == null) { | ||
oidcConfigBuilder = OidcConfig.builder(); | ||
} else { | ||
verifyIdAndType(authenticationIdpOidcBean, existingIdpConfig, OidcConfig.class); | ||
oidcConfigBuilder = OidcConfig.builder((OidcConfig) existingIdpConfig); | ||
} | ||
|
||
if (authenticationIdpOidcBean.getId() != null) { | ||
oidcConfigBuilder.setId(authenticationIdpOidcBean.getId()); | ||
} | ||
if (authenticationIdpOidcBean.getName() != null) { | ||
oidcConfigBuilder.setName(authenticationIdpOidcBean.getName()); | ||
} | ||
if (authenticationIdpOidcBean.getEnabled() != null) { | ||
oidcConfigBuilder.setEnabled(authenticationIdpOidcBean.getEnabled()); | ||
} | ||
if (authenticationIdpOidcBean.getUrl() != null) { | ||
oidcConfigBuilder.setIssuer(authenticationIdpOidcBean.getUrl()); | ||
} | ||
if (authenticationIdpOidcBean.getEnableRememberMe() != null) { | ||
oidcConfigBuilder.setEnableRememberMe(authenticationIdpOidcBean.getEnableRememberMe()); | ||
} | ||
if (authenticationIdpOidcBean.getButtonText() != null) { | ||
oidcConfigBuilder.setButtonText(authenticationIdpOidcBean.getButtonText()); | ||
} | ||
if (authenticationIdpOidcBean.getClientId() != null) { | ||
oidcConfigBuilder.setClientId(authenticationIdpOidcBean.getClientId()); | ||
} | ||
if (authenticationIdpOidcBean.getClientSecret() != null) { | ||
oidcConfigBuilder.setClientSecret(authenticationIdpOidcBean.getClientSecret()); | ||
} | ||
if (authenticationIdpOidcBean.getUsernameClaim() != null) { | ||
oidcConfigBuilder.setUsernameClaim(authenticationIdpOidcBean.getUsernameClaim()); | ||
} | ||
if (authenticationIdpOidcBean.getAdditionalScopes() != null) { | ||
oidcConfigBuilder.setAdditionalScopes(authenticationIdpOidcBean.getAdditionalScopes()); | ||
} | ||
if (authenticationIdpOidcBean.getDiscoveryEnabled() != null) { | ||
oidcConfigBuilder.setDiscoveryEnabled(authenticationIdpOidcBean.getDiscoveryEnabled()); | ||
} | ||
if (authenticationIdpOidcBean.getAuthorizationEndpoint() != null) { | ||
oidcConfigBuilder.setAuthorizationEndpoint(authenticationIdpOidcBean.getAuthorizationEndpoint()); | ||
} | ||
if (authenticationIdpOidcBean.getTokenEndpoint() != null) { | ||
oidcConfigBuilder.setTokenEndpoint(authenticationIdpOidcBean.getTokenEndpoint()); | ||
} | ||
if (authenticationIdpOidcBean.getUserInfoEndpoint() != null) { | ||
oidcConfigBuilder.setUserInfoEndpoint(authenticationIdpOidcBean.getUserInfoEndpoint()); | ||
} | ||
|
||
return oidcConfigBuilder.build(); | ||
} | ||
|
||
public static AbstractAuthenticationIdpBean toAuthenticationIdpBean( | ||
final IdpConfig idpConfig) { | ||
|
||
if (idpConfig.getSsoType().equals(SsoType.OIDC)) { | ||
return toAuthenticationIdpOidcBean(idpConfig); | ||
} else if (idpConfig.getSsoType().equals(SsoType.SAML)) { | ||
return toAuthenticationIdpSamlBean(idpConfig); | ||
} | ||
|
||
throw new UnsupportedOperationException("The IDP type cannot be NONE"); | ||
} | ||
|
||
private static AuthenticationIdpOidcBean toAuthenticationIdpOidcBean( | ||
final IdpConfig idpConfig) { | ||
|
||
if (!(idpConfig instanceof OidcConfig)) { | ||
throw new InternalServerErrorException("The class of the IDP config is not OIDC"); | ||
} | ||
|
||
final OidcConfig oidcConfig = (OidcConfig) idpConfig; | ||
|
||
final AuthenticationIdpOidcBean authenticationIdpOidcBean = new AuthenticationIdpOidcBean(); | ||
authenticationIdpOidcBean.setId(oidcConfig.getId()); | ||
authenticationIdpOidcBean.setName(oidcConfig.getName()); | ||
authenticationIdpOidcBean.setEnabled(oidcConfig.isEnabled()); | ||
authenticationIdpOidcBean.setUrl(oidcConfig.getIssuer()); | ||
authenticationIdpOidcBean.setEnableRememberMe(oidcConfig.isEnableRememberMe()); | ||
authenticationIdpOidcBean.setButtonText(oidcConfig.getButtonText()); | ||
authenticationIdpOidcBean.setClientId(oidcConfig.getClientId()); | ||
authenticationIdpOidcBean.setUsernameClaim(oidcConfig.getUsernameClaim()); | ||
authenticationIdpOidcBean.setAdditionalScopes(oidcConfig.getAdditionalScopes()); | ||
authenticationIdpOidcBean.setDiscoveryEnabled(oidcConfig.isDiscoveryEnabled()); | ||
authenticationIdpOidcBean.setAuthorizationEndpoint(oidcConfig.getAuthorizationEndpoint()); | ||
authenticationIdpOidcBean.setTokenEndpoint(oidcConfig.getTokenEndpoint()); | ||
authenticationIdpOidcBean.setUserInfoEndpoint(oidcConfig.getUserInfoEndpoint()); | ||
|
||
return authenticationIdpOidcBean; | ||
} | ||
|
||
private static AuthenticationIdpSamlBean toAuthenticationIdpSamlBean( | ||
final IdpConfig idpConfig) { | ||
|
||
if (!(idpConfig instanceof SamlConfig)) { | ||
throw new InternalServerErrorException("The class of the IDP config is not SAML"); | ||
} | ||
|
||
final SamlConfig samlConfig = (SamlConfig) idpConfig; | ||
|
||
final AuthenticationIdpSamlBean authenticationIdpSamlBean = new AuthenticationIdpSamlBean(); | ||
authenticationIdpSamlBean.setId(samlConfig.getId()); | ||
authenticationIdpSamlBean.setName(samlConfig.getName()); | ||
authenticationIdpSamlBean.setEnabled(samlConfig.isEnabled()); | ||
authenticationIdpSamlBean.setUrl(samlConfig.getIssuer()); | ||
authenticationIdpSamlBean.setEnableRememberMe(samlConfig.isEnableRememberMe()); | ||
authenticationIdpSamlBean.setButtonText(samlConfig.getButtonText()); | ||
// is it wanted to return the certificate here? | ||
authenticationIdpSamlBean.setUsernameAttribute(samlConfig.getUsernameAttribute()); | ||
|
||
return authenticationIdpSamlBean; | ||
} | ||
|
||
private static void verifyIdAndType( | ||
final AbstractAuthenticationIdpBean authenticationIdpBean, | ||
final IdpConfig existingIdpConfig, | ||
final Class<? extends IdpConfig> clazz) { | ||
|
||
if (authenticationIdpBean.getId() != null && !authenticationIdpBean.getId().equals(existingIdpConfig.getId())) { | ||
throw new BadRequestException("An ID has been passed but it does not match the ID of the existing IDP with the same name"); | ||
} | ||
|
||
if (!clazz.isAssignableFrom(existingIdpConfig.getClass())) { | ||
throw new BadRequestException("The existing IDP config with the same name is not of type OIDC"); | ||
} | ||
} | ||
|
||
private AuthenticationIdpBeanUtil() { | ||
} | ||
|
||
} |
46 changes: 46 additions & 0 deletions
46
src/main/java/de/aservo/confapi/jira/model/util/AuthenticationSsoBeanUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package de.aservo.confapi.jira.model.util; | ||
|
||
import com.atlassian.plugins.authentication.api.config.ImmutableSsoConfig; | ||
import com.atlassian.plugins.authentication.api.config.SsoConfig; | ||
import de.aservo.confapi.commons.model.AuthenticationSsoBean; | ||
|
||
public class AuthenticationSsoBeanUtil { | ||
|
||
public static SsoConfig toSsoConfig( | ||
final AuthenticationSsoBean authenticationSsoBean) { | ||
|
||
return toSsoConfig(authenticationSsoBean, null); | ||
} | ||
|
||
public static SsoConfig toSsoConfig( | ||
final AuthenticationSsoBean authenticationSsoBean, | ||
final SsoConfig existingSsoConfig) { | ||
|
||
final ImmutableSsoConfig.Builder ssoConfigBuilder; | ||
|
||
if (existingSsoConfig != null) { | ||
ssoConfigBuilder = ImmutableSsoConfig.toBuilder(existingSsoConfig); | ||
} else { | ||
ssoConfigBuilder = ImmutableSsoConfig.builder(); | ||
} | ||
|
||
if (authenticationSsoBean.getShowOnLogin() != null) { | ||
ssoConfigBuilder.setShowLoginForm(authenticationSsoBean.getShowOnLogin()); | ||
} | ||
|
||
return ssoConfigBuilder.build(); | ||
} | ||
|
||
public static AuthenticationSsoBean toAuthenticationSsoBean( | ||
final SsoConfig ssoConfig) { | ||
|
||
final AuthenticationSsoBean authenticationSsoBean = new AuthenticationSsoBean(); | ||
authenticationSsoBean.setShowOnLogin(ssoConfig.getShowLoginForm()); | ||
|
||
return authenticationSsoBean; | ||
} | ||
|
||
private AuthenticationSsoBeanUtil() { | ||
} | ||
|
||
} |
23 changes: 23 additions & 0 deletions
23
src/main/java/de/aservo/confapi/jira/rest/AuthenticationResourceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package de.aservo.confapi.jira.rest; | ||
|
||
import com.sun.jersey.spi.container.ResourceFilters; | ||
import de.aservo.confapi.commons.constants.ConfAPI; | ||
import de.aservo.confapi.commons.rest.AbstractAuthenticationResourceImpl; | ||
import de.aservo.confapi.commons.service.api.AuthenticationService; | ||
import de.aservo.confapi.jira.filter.SysadminOnlyResourceFilter; | ||
import org.springframework.stereotype.Component; | ||
|
||
import javax.inject.Inject; | ||
import javax.ws.rs.Path; | ||
|
||
@Path(ConfAPI.AUTHENTICATION) | ||
@ResourceFilters(SysadminOnlyResourceFilter.class) | ||
@Component | ||
public class AuthenticationResourceImpl extends AbstractAuthenticationResourceImpl { | ||
|
||
@Inject | ||
public AuthenticationResourceImpl(AuthenticationService authenticationService) { | ||
super(authenticationService); | ||
} | ||
|
||
} |
105 changes: 105 additions & 0 deletions
105
src/main/java/de/aservo/confapi/jira/service/AuthenticationServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package de.aservo.confapi.jira.service; | ||
|
||
import com.atlassian.plugin.spring.scanner.annotation.export.ExportAsService; | ||
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport; | ||
import com.atlassian.plugins.authentication.api.config.IdpConfig; | ||
import com.atlassian.plugins.authentication.api.config.IdpConfigService; | ||
import com.atlassian.plugins.authentication.api.config.SsoConfig; | ||
import com.atlassian.plugins.authentication.api.config.SsoConfigService; | ||
import de.aservo.confapi.commons.exception.BadRequestException; | ||
import de.aservo.confapi.commons.model.AbstractAuthenticationIdpBean; | ||
import de.aservo.confapi.commons.model.AuthenticationIdpsBean; | ||
import de.aservo.confapi.commons.model.AuthenticationSsoBean; | ||
import de.aservo.confapi.commons.service.api.AuthenticationService; | ||
import de.aservo.confapi.jira.model.util.AuthenticationIdpBeanUtil; | ||
import de.aservo.confapi.jira.model.util.AuthenticationSsoBeanUtil; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.util.Comparator; | ||
import java.util.Map; | ||
import java.util.function.Function; | ||
import java.util.stream.Collectors; | ||
|
||
@Component | ||
@ExportAsService(AuthenticationService.class) | ||
public class AuthenticationServiceImpl implements AuthenticationService { | ||
|
||
@ComponentImport | ||
private final IdpConfigService idpConfigService; | ||
|
||
@ComponentImport | ||
private final SsoConfigService ssoConfigService; | ||
|
||
public AuthenticationServiceImpl( | ||
final IdpConfigService idpConfigService, | ||
final SsoConfigService ssoConfigService) { | ||
|
||
this.idpConfigService = idpConfigService; | ||
this.ssoConfigService = ssoConfigService; | ||
} | ||
|
||
@Override | ||
public AuthenticationIdpsBean getAuthenticationIdps() { | ||
return new AuthenticationIdpsBean(idpConfigService.getIdpConfigs().stream() | ||
.map(AuthenticationIdpBeanUtil::toAuthenticationIdpBean) | ||
.sorted(authenticationIdpBeanComparator) | ||
.collect(Collectors.toList())); | ||
} | ||
|
||
@Override | ||
public AuthenticationIdpsBean setAuthenticationIdps( | ||
final AuthenticationIdpsBean authenticationIdpsBean) { | ||
|
||
return new AuthenticationIdpsBean(authenticationIdpsBean.getAuthenticationIdpBeans().stream() | ||
.map(this::setAuthenticationIdp) | ||
.sorted(authenticationIdpBeanComparator) | ||
.collect(Collectors.toList())); | ||
} | ||
|
||
public AbstractAuthenticationIdpBean setAuthenticationIdp( | ||
final AbstractAuthenticationIdpBean authenticationIdpBean) { | ||
|
||
if (authenticationIdpBean.getName() == null || authenticationIdpBean.getName().trim().isEmpty()) { | ||
throw new BadRequestException("The name cannot be empty"); | ||
} | ||
|
||
final IdpConfig existingIdpConfig = findIdpConfigByName(authenticationIdpBean.getName()); | ||
|
||
if (existingIdpConfig == null) { | ||
final IdpConfig idpConfig = AuthenticationIdpBeanUtil.toIdpConfig(authenticationIdpBean); | ||
final IdpConfig addedIdpConfig = idpConfigService.addIdpConfig(idpConfig); | ||
return AuthenticationIdpBeanUtil.toAuthenticationIdpBean(addedIdpConfig); | ||
} | ||
|
||
final IdpConfig idpConfig = AuthenticationIdpBeanUtil.toIdpConfig(authenticationIdpBean, existingIdpConfig); | ||
final IdpConfig updatedIdpConfig = idpConfigService.updateIdpConfig(idpConfig); | ||
return AuthenticationIdpBeanUtil.toAuthenticationIdpBean(updatedIdpConfig); | ||
} | ||
|
||
@Override | ||
public AuthenticationSsoBean getAuthenticationSso() { | ||
return AuthenticationSsoBeanUtil.toAuthenticationSsoBean(ssoConfigService.getSsoConfig()); | ||
} | ||
|
||
@Override | ||
public AuthenticationSsoBean setAuthenticationSso(AuthenticationSsoBean authenticationSsoBean) { | ||
final SsoConfig existingSsoConfig = ssoConfigService.getSsoConfig(); | ||
final SsoConfig ssoConfig = AuthenticationSsoBeanUtil.toSsoConfig(authenticationSsoBean, existingSsoConfig); | ||
return AuthenticationSsoBeanUtil.toAuthenticationSsoBean(ssoConfigService.updateSsoConfig(ssoConfig)); | ||
} | ||
|
||
IdpConfig findIdpConfigByName( | ||
final String name) { | ||
|
||
final Map<String, IdpConfig> idpConfigsByName = idpConfigService.getIdpConfigs().stream().collect(Collectors.toMap( | ||
IdpConfig::getName, Function.identity(), (existing, replacement) -> { | ||
throw new IllegalStateException("Duplicate name key found: " + existing.getName()); | ||
} | ||
)); | ||
|
||
return idpConfigsByName.get(name); | ||
} | ||
|
||
static Comparator<AbstractAuthenticationIdpBean> authenticationIdpBeanComparator = (a1, a2) -> a1.getName().compareToIgnoreCase(a2.getName()); | ||
|
||
} |
Oops, something went wrong.