diff --git a/pom.xml b/pom.xml index 56ceebb6e9a1ff027311105fe8b472891d1612b5..497e77a4ba7d3917ec3f9ebd174f4e2591d7b266 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>edu.wisc.uwss</groupId> <artifactId>uw-spring-security</artifactId> - <version>1.5.2-SNAPSHOT</version> + <version>1.6.0-SNAPSHOT</version> <packaging>pom</packaging> <name>UW Spring Security Parent</name> <description>Parent project for module to integrate Spring Security with UW authentication mechanism.</description> diff --git a/uw-spring-security-core/src/main/java/edu/wisc/uwss/preauth/PreauthenticatedUserDetailsAttributeMapper.java b/uw-spring-security-core/src/main/java/edu/wisc/uwss/preauth/PreauthenticatedUserDetailsAttributeMapper.java index d638e04075da426a5537d972219d220f7eb9ed8b..20bf725c149d3445327b18559c6a28c2c90a775e 100644 --- a/uw-spring-security-core/src/main/java/edu/wisc/uwss/preauth/PreauthenticatedUserDetailsAttributeMapper.java +++ b/uw-spring-security-core/src/main/java/edu/wisc/uwss/preauth/PreauthenticatedUserDetailsAttributeMapper.java @@ -60,6 +60,7 @@ public interface PreauthenticatedUserDetailsAttributeMapper { private String identityProviderHeader = "Shib-Identity-Provider"; private String customLogoutPrefix = "/Shibboleth.sso/Logout?return="; private String customLogoutSuffix = "/logout/"; + private String manifestHeader = "ismemberof"; private static final Logger logger = LoggerFactory.getLogger(Default.class); /** @@ -87,7 +88,12 @@ public interface PreauthenticatedUserDetailsAttributeMapper { uddsMembership = Collections.list(uddsHeaders); } String email = request.getHeader(emailAddressHeader); - UWUserDetailsImpl result = new UWUserDetailsImpl(pvi, uid, "", cn, email, uddsMembership); + Collection<String> manifestGroups = new ArrayList<>(); + Enumeration<String> manifestHeaders = request.getHeaders(manifestHeader); + if(manifestHeaders != null) { + manifestGroups = Collections.list(manifestHeaders); + } + UWUserDetailsImpl result = UWUserDetailsImpl.newInstance(pvi, uid, "", cn, email, uddsMembership, manifestGroups); result.setSource("edu.wisc.uwss.preauth"); result.setEppn(eppn); result.setIsisEmplid(emplid); @@ -280,5 +286,18 @@ public interface PreauthenticatedUserDetailsAttributeMapper { public void setLastNameHeader(String lastNameHeader) { this.lastNameHeader = lastNameHeader; } + /** + * @return the manifestHeader + */ + public String getManifestHeader() { + return manifestHeader; + } + /** + * @param manifestHeader the manifestHeader to set + */ + @Value("${preauth.manifestHeader:ismemberof}") + public void setManifestHeader(String manifestHeader) { + this.manifestHeader = manifestHeader; + } } } diff --git a/uw-spring-security-core/src/test/java/edu/wisc/uwss/preauth/PreauthenticatedUserDetailsAttributeMapperTest.java b/uw-spring-security-core/src/test/java/edu/wisc/uwss/preauth/PreauthenticatedUserDetailsAttributeMapperTest.java index 92b4b0d4ca80c85dd562739d70f4b2ae9572a8c0..d7e86ee3d85799291c92fe1cf05839634cdc428e 100644 --- a/uw-spring-security-core/src/test/java/edu/wisc/uwss/preauth/PreauthenticatedUserDetailsAttributeMapperTest.java +++ b/uw-spring-security-core/src/test/java/edu/wisc/uwss/preauth/PreauthenticatedUserDetailsAttributeMapperTest.java @@ -6,8 +6,10 @@ package edu.wisc.uwss.preauth; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import java.net.URL; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -15,6 +17,7 @@ import javax.servlet.http.HttpServletRequest; import org.junit.Test; import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.security.core.GrantedAuthority; import edu.wisc.uwss.UWUserDetails; import edu.wisc.uwss.preauth.PreauthenticatedUserDetailsAttributeMapper.Default; @@ -41,6 +44,7 @@ public class PreauthenticatedUserDetailsAttributeMapperTest { String email = "some.body@wisc.edu"; String emplid = "0000123456"; List<String> uddsMembership = Collections.singletonList("udds1234"); + List<String> manifestGroups = Collections.singletonList("uw:domain:something"); request.addHeader("eppn", eppn); request.addHeader("wiscedupvi", pvi); @@ -50,6 +54,7 @@ public class PreauthenticatedUserDetailsAttributeMapperTest { request.addHeader("wisceduudds", uddsMembership); request.addHeader("wisceduisisemplid", emplid); request.addHeader("Shib-Identity-Provider", "https://logintest.wisc.edu/idp/shibboleth"); + request.addHeader("ismemberof",manifestGroups); UWUserDetails result = filter.mapUser(request); @@ -62,8 +67,35 @@ public class PreauthenticatedUserDetailsAttributeMapperTest { assertEquals(uddsMembership, result.getUddsMembership()); assertEquals(emplid, result.getIsisEmplid()); assertEquals("/Shibboleth.sso/Logout?return=https://logintest.wisc.edu/logout/", result.getCustomLogoutUrl()); + assertEquals(1,result.getAuthorities().size()); + assertEquals(manifestGroups.toString(),result.getAuthorities().toString()); + } + + /** + * Verify that a user can have multiple Manifest groups in their {@link GrantedAuthority}s + */ + @Test + public void mapUser_multipleManifestGroups() { + MockHttpServletRequest request = new MockHttpServletRequest(); + + String uid = "somebody"; + ArrayList<String> manifestGroups = new ArrayList<>(); + manifestGroups.add("uw:domain:onegroup"); + manifestGroups.add("uw:domain:anothergroup"); + + request.addHeader("uid", uid); + request.addHeader("ismemberof",manifestGroups); + + UWUserDetails result = filter.mapUser(request); + + assertEquals(uid, result.getUsername()); + assertEquals(2,result.getAuthorities().size()); + + for (GrantedAuthority authority : result.getAuthorities()) { + assertTrue(manifestGroups.contains(authority.getAuthority())); + } + } - /** * Verify behavior of {@link Default#toCustomLogoutUrl(String)} for * null input. diff --git a/uw-spring-security-core/src/test/java/edu/wisc/uwss/preauth/UWUserDetailsAuthenticationFilterTest.java b/uw-spring-security-core/src/test/java/edu/wisc/uwss/preauth/UWUserDetailsAuthenticationFilterTest.java index 2ab93b5ec7d2eb614ee8cdf842f3d2b39c2ab0d5..52bb7f5a618e0efcbe9e52df4eacbbf2834b2ffe 100644 --- a/uw-spring-security-core/src/test/java/edu/wisc/uwss/preauth/UWUserDetailsAuthenticationFilterTest.java +++ b/uw-spring-security-core/src/test/java/edu/wisc/uwss/preauth/UWUserDetailsAuthenticationFilterTest.java @@ -32,12 +32,13 @@ public class UWUserDetailsAuthenticationFilterTest { public void getPreAuthenticatedPrincipal_control() { UWUserDetailsAuthenticationFilter filter = new UWUserDetailsAuthenticationFilter(); HttpServletRequest request = mock(HttpServletRequest.class); - - when(request.getHeader("uid")).thenReturn("bbadger"); + + when(request.getHeader("uid")).thenReturn("bbadger"); when(request.getHeader("eppn")).thenReturn("bbadger@wisc.edu"); when(request.getHeader("cn")).thenReturn("Bucky Badger"); when(request.getHeaders("wisceduudds")).thenReturn(Collections.enumeration(Arrays.asList("A061234"))); when(request.getHeader("mail")).thenReturn("foo@foo.wisc.edu"); + when(request.getHeaders("ismemberof")).thenReturn(Collections.enumeration(Arrays.asList("somegroup"))); UWUserDetails userDetails = filter.getPreAuthenticatedPrincipal(request); assertEquals("bbadger", userDetails.getUsername()); assertEquals("bbadger@wisc.edu", userDetails.getEppn()); @@ -45,6 +46,7 @@ public class UWUserDetailsAuthenticationFilterTest { assertEquals("foo@foo.wisc.edu", userDetails.getEmailAddress()); assertEquals(1, userDetails.getUddsMembership().size()); assertEquals("A061234", userDetails.getUddsMembership().iterator().next()); + assertEquals("somegroup", userDetails.getAuthorities().iterator().next().getAuthority()); } /** @@ -63,7 +65,24 @@ public class UWUserDetailsAuthenticationFilterTest { assertEquals("Bucky Badger", userDetails.getFullName()); assertTrue(userDetails.getUddsMembership().isEmpty()); } - /** + /** + * Verify behavior for {@link UWUserDetailsAuthenticationFilter#getPreAuthenticatedPrincipal(HttpServletRequest)} + * when no "manifest" header is present, which is commonly true unless an the application is designed + * specifically to consume a manifest group. + */ + @Test + public void getPreAuthenticatedPrincipal_no_manifestgroups() { + UWUserDetailsAuthenticationFilter filter = new UWUserDetailsAuthenticationFilter(); + HttpServletRequest request = mock(HttpServletRequest.class); + + when(request.getHeader("uid")).thenReturn("bbadger"); + when(request.getHeader("cn")).thenReturn("Bucky Badger"); + UWUserDetails userDetails = filter.getPreAuthenticatedPrincipal(request); + assertEquals("bbadger", userDetails.getUsername()); + assertEquals("Bucky Badger", userDetails.getFullName()); + assertTrue(userDetails.getAuthorities().isEmpty()); + } + /** * Verify behavior for {@link UWUserDetailsAuthenticationFilter#getPreAuthenticatedPrincipal(HttpServletRequest)} when * no "uid" header is present. This would represent a scenario where our pre-authentication (shib) environment isn't correctly * configured; we want to make sure attempts to login would fail and not accidentially leak people in.