Merge branch 'stable-2.16' into stable-3.0 * stable-2.16: Create HTTP session only for login requests Change-Id: I432b5917224f4e56c6167384ba069d7976718aee
diff --git a/README.md b/README.md index bb9c949..0425eaf 100644 --- a/README.md +++ b/README.md
@@ -179,7 +179,14 @@ Default is `UserName` -**saml.serviceProviderEntityId**: Saml service provider entity id +**saml.serviceProviderEntityId**: SAML service provider entity id. + +Default is not set. + +**saml.identityProviderEntityId**: SAML identity provider entity id. When present +a `IDPSSODescriptor` is expected in the SAML metadata document. When absent a +saml service provider with its `SPSSODescriptor` is assumed. +This value takes precedence over the value in **saml.serviceProviderEntityId**. Default is not set.
diff --git a/src/main/java/com/googlesource/gerrit/plugins/saml/SamlConfig.java b/src/main/java/com/googlesource/gerrit/plugins/saml/SamlConfig.java index d5aae19..98f09ea 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/saml/SamlConfig.java +++ b/src/main/java/com/googlesource/gerrit/plugins/saml/SamlConfig.java
@@ -23,7 +23,7 @@ @Singleton public class SamlConfig { private static final String SAML_SECTION = "saml"; - + private final String identityProviderEntityId; private final String serviceProviderEntityId; private final String metadataPath; private final String keystorePath; @@ -42,6 +42,7 @@ @Inject SamlConfig(@GerritServerConfig Config cfg) { serviceProviderEntityId = getString(cfg, "serviceProviderEntityId"); + identityProviderEntityId = getString(cfg, "identityProviderEntityId"); metadataPath = getString(cfg, "metadataPath"); keystorePath = getString(cfg, "keystorePath"); privateKeyPassword = getString(cfg, "privateKeyPassword"); @@ -119,4 +120,8 @@ public boolean useNameQualifier() { return useNameQualifier; } + + public String getIdentityProviderEntityId() { + return identityProviderEntityId; + } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/saml/SamlWebFilter.java b/src/main/java/com/googlesource/gerrit/plugins/saml/SamlWebFilter.java index 7307910..2c6549f 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/saml/SamlWebFilter.java +++ b/src/main/java/com/googlesource/gerrit/plugins/saml/SamlWebFilter.java
@@ -25,6 +25,8 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collections; import java.util.Enumeration; import java.util.HashSet; import java.util.List; @@ -81,14 +83,23 @@ new SAML2Configuration( samlConfig.getKeystorePath(), samlConfig.getKeystorePassword(), samlConfig.getPrivateKeyPassword(), samlConfig.getMetadataPath()); - samlClientConfig.setMaximumAuthenticationLifetime(samlConfig.getMaxAuthLifetimeAttr()); - samlClientConfig.setServiceProviderMetadataPath( - ensureExists(sitePaths.data_dir).resolve("sp-metadata.xml").toString()); - if (!Strings.isNullOrEmpty(samlConfig.getServiceProviderEntityId())) { - samlClientConfig.setServiceProviderEntityId(samlConfig.getServiceProviderEntityId()); + + if (!Strings.isNullOrEmpty(samlConfig.getIdentityProviderEntityId())) { + if (!Strings.isNullOrEmpty(samlConfig.getServiceProviderEntityId())) { + log.warn( + "Both identityProviderEntityId as serviceProviderEntityId are set, ignoring serviceProviderEntityId."); + } + samlClientConfig.setIdentityProviderEntityId(samlConfig.getIdentityProviderEntityId()); + } else { + samlClientConfig.setServiceProviderMetadataPath( + ensureExists(sitePaths.data_dir).resolve("sp-metadata.xml").toString()); + if (!Strings.isNullOrEmpty(samlConfig.getServiceProviderEntityId())) { + samlClientConfig.setServiceProviderEntityId(samlConfig.getServiceProviderEntityId()); + } } samlClientConfig.setUseNameQualifier(samlConfig.useNameQualifier()); + samlClientConfig.setMaximumAuthenticationLifetime(samlConfig.getMaxAuthLifetimeAttr()); saml2Client = new SAML2Client(samlClientConfig); String callbackUrl = gerritConfig.getString("gerrit", null, "canonicalWebUrl") + SAML_CALLBACK; @@ -223,13 +234,28 @@ } private static String getAttribute(SAML2Profile user, String attrName) { - List<?> names = (List<?>) user.getAttribute(attrName); + // TODO(davido): Replace with the invocation from upstream method. + List<String> names = extractAttributeValues(user, attrName); if (names != null && !names.isEmpty()) { - return (String) names.get(0); + return names.get(0); } return null; } + // TODO(davido): Remove if getAttribute() uses the upstream method. + private static List<String> extractAttributeValues(SAML2Profile user, String attrName) { + final Object value = user.getAttribute(attrName); + if (value instanceof String) { + return Collections.singletonList((String) value); + } else if (value instanceof String[]) { + return Arrays.asList((String[]) value); + } else if (value instanceof List) { + return (List<String>) value; + } else { + return null; + } + } + private static String getAttributeOrElseId(SAML2Profile user, String attrName) { String value = getAttribute(user, attrName); if (value != null) {