Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Add ldap support via Spring profile #11

Merged
merged 3 commits into from

1 participant

@dsyer
Collaborator

No description provided.

dsyer added some commits
@dsyer dsyer [cfid-669] Add UsernamePasswordExtractingAuthenticationManager
[#45987701] Login server changes to support vmc and LDAP
d0b830e
@dsyer dsyer Remove vmc headers to prevent duplicates f1c5d3a
@dsyer dsyer [cfid-669] Add ldap profile and test case for context
The war now contains all the ldap dependencies and there is a
Spring profile cdalled "ldap" that switches it on for authentication
only. The LDAP query might need to be tweaked and there is a
URL externalized to `ldap.base.url`.

[Fixes #45987701] Login server changes to support vmc and LDAP
cb8c1f7
@dsyer dsyer merged commit cb8c1f7 into cloudfoundry:develop

1 check passed

Details default The Travis build passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 12, 2013
  1. @dsyer

    [cfid-669] Add UsernamePasswordExtractingAuthenticationManager

    dsyer authored
    [#45987701] Login server changes to support vmc and LDAP
Commits on Mar 14, 2013
  1. @dsyer
Commits on Mar 18, 2013
  1. @dsyer

    [cfid-669] Add ldap profile and test case for context

    dsyer authored
    The war now contains all the ldap dependencies and there is a
    Spring profile cdalled "ldap" that switches it on for authentication
    only. The LDAP query might need to be tweaked and there is a
    URL externalized to `ldap.base.url`.
    
    [Fixes #45987701] Login server changes to support vmc and LDAP
This page is out of date. Refresh to see the latest.
View
7 pom.xml
@@ -320,6 +320,13 @@
</dependency>
<dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-ldap</artifactId>
+ <version>${spring.security.version}</version>
+ <scope>runtime</scope>
+ </dependency>
+
+ <dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>${spring.security.oauth.version}</version>
View
10 src/main/java/org/cloudfoundry/identity/uaa/login/RemoteUaaController.java
@@ -74,6 +74,12 @@
private static final String CONTENT_LENGTH = "Content-Length";
+ private static final String CONTENT_TYPE = "Content-Type";
+
+ private static final String ACCEPT = "Accept";
+
+ private static final String AUTHORIZATION = "Authorization";
+
private static final String TRANSFER_ENCODING = "Transfer-Encoding";
private static final String HOST = "Host";
@@ -271,6 +277,7 @@ public ModelAndView startAuthorization(HttpServletRequest request, @RequestParam
if (principal != null) {
map.set("source", "login");
map.setAll(getLoginCredentials(principal));
+ map.remove("credentials"); // legacy vmc might break otherwise
}
else {
throw new BadCredentialsException("No principal found in authorize endpoint");
@@ -278,6 +285,9 @@ public ModelAndView startAuthorization(HttpServletRequest request, @RequestParam
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.putAll(getRequestHeaders(headers));
+ requestHeaders.remove(AUTHORIZATION.toLowerCase());
+ requestHeaders.remove(ACCEPT.toLowerCase());
+ requestHeaders.remove(CONTENT_TYPE.toLowerCase());
requestHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
requestHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
requestHeaders.remove(COOKIE);
View
60 .../org/cloudfoundry/identity/uaa/login/UsernamePasswordExtractingAuthenticationManager.java
@@ -0,0 +1,60 @@
+/*
+ * Cloud Foundry 2012.02.03 Beta
+ * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved.
+ *
+ * This product is licensed to you under the Apache License, Version 2.0 (the "License").
+ * You may not use this product except in compliance with the License.
+ *
+ * This product includes a number of subcomponents with
+ * separate copyright notices and license terms. Your use of these
+ * subcomponents is subject to the terms and conditions of the
+ * subcomponent's license, as noted in the LICENSE file.
+ */
+
+package org.cloudfoundry.identity.uaa.login;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+
+/**
+ * Authentication filter translating a generic Authentication into a UsernamePasswordAuthenticationToken.
+ *
+ * @author Dave Syer
+ *
+ */
+public class UsernamePasswordExtractingAuthenticationManager implements AuthenticationManager {
+
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private final AuthenticationManager delegate;
+
+ /**
+ * @param delegate
+ */
+ public UsernamePasswordExtractingAuthenticationManager(AuthenticationManager delegate) {
+ super();
+ this.delegate = delegate;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.security.authentication.AuthenticationManager#authenticate(org.springframework.security.core.Authentication)
+ */
+ @Override
+ public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+
+ if (authentication == null || authentication instanceof UsernamePasswordAuthenticationToken) {
+ return authentication;
+ }
+
+ UsernamePasswordAuthenticationToken output = new UsernamePasswordAuthenticationToken(authentication, authentication.getCredentials(), authentication.getAuthorities());
+ output.setAuthenticated(authentication.isAuthenticated());
+ output.setDetails(authentication.getDetails());
+ return delegate.authenticate(output);
+
+ }
+
+}
View
85 src/main/webapp/WEB-INF/spring-servlet.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<!-- Cloud Foundry 2012.02.03 Beta Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. This product is licensed to
- you under the Apache License, Version 2.0 (the "License"). You may not use this product except in compliance with the License.
- This product includes a number of subcomponents with separate copyright notices and license terms. Your use of these subcomponents
+<!-- Cloud Foundry 2012.02.03 Beta Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. This product is licensed to
+ you under the Apache License, Version 2.0 (the "License"). You may not use this product except in compliance with the License.
+ This product includes a number of subcomponents with separate copyright notices and license terms. Your use of these subcomponents
is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file. -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
@@ -33,7 +33,9 @@
<property name="requireHttps" value="${require_https:false}" />
<property name="dumpRequests" value="${dump_requests:false}" />
<property name="redirectToHttps">
- <list><value>uiSecurity</value></list>
+ <list>
+ <value>uiSecurity</value>
+ </list>
</property>
</bean>
@@ -103,8 +105,9 @@
</bean>
<!-- For backwards compatibility to the old way of posting credentials to /authorize endpoint -->
- <http name="oldAuthzEndpointSecurity" request-matcher-ref="oauthAuthorizeRequestMatcherOld" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint"
- authentication-manager-ref="remoteAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
+ <http name="oldAuthzEndpointSecurity" request-matcher-ref="oauthAuthorizeRequestMatcherOld" create-session="stateless"
+ entry-point-ref="oauthAuthenticationEntryPoint" authentication-manager-ref="remoteAuthenticationManager"
+ xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
<custom-filter ref="authzAuthenticationFilter" position="FORM_LOGIN_FILTER" />
<anonymous enabled="false" />
@@ -144,17 +147,17 @@
</bean>
<!-- Version of the /authorize endpoint for stateless clients such as VMC -->
- <http name="statelessAuthzEndpointSecurity" request-matcher-ref="oauthAuthorizeRequestMatcher" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint"
- authentication-manager-ref="remoteAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
+ <http name="statelessAuthzEndpointSecurity" request-matcher-ref="oauthAuthorizeRequestMatcher" create-session="stateless"
+ entry-point-ref="oauthAuthenticationEntryPoint" authentication-manager-ref="remoteAuthenticationManager"
+ xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
<custom-filter ref="authzAuthenticationFilter" position="FORM_LOGIN_FILTER" />
<anonymous enabled="false" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
- <http name="uiSecurity" xmlns="http://www.springframework.org/schema/security"
- authentication-manager-ref="remoteAuthenticationManager" disable-url-rewriting="true"
- entry-point-ref="loginEntryPoint">
+ <http name="uiSecurity" xmlns="http://www.springframework.org/schema/security" authentication-manager-ref="remoteAuthenticationManager"
+ disable-url-rewriting="true" entry-point-ref="loginEntryPoint">
<intercept-url pattern="/login*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/logout.do" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
@@ -176,10 +179,6 @@
<constructor-arg value="/login" />
</bean>
- <bean id="remoteAuthenticationManager" class="org.cloudfoundry.identity.uaa.login.RemoteUaaAuthenticationManager">
- <property name="loginUrl" value="${uaa.login.url:http://localhost:8080/uaa/authenticate}" />
- </bean>
-
<bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="UAA/oauth" />
</bean>
@@ -226,13 +225,13 @@
</bean>
<util:map id="links">
- <entry key="home" value="${links.home:https://www.cloudfoundry.com}"/>
- <entry key="passwd" value="${links.passwd:https://www.cloudfoundry.com/passwd}"/>
- <entry key="register" value="${links.signup:https://www.cloudfoundry.com/signup}"/>
+ <entry key="home" value="${links.home:https://www.cloudfoundry.com}" />
+ <entry key="passwd" value="${links.passwd:https://www.cloudfoundry.com/passwd}" />
+ <entry key="register" value="${links.signup:https://www.cloudfoundry.com/signup}" />
</util:map>
<bean id="homeController" class="org.cloudfoundry.identity.uaa.login.HomeController">
- <property name="links" ref="links"/>
+ <property name="links" ref="links" />
</bean>
<bean id="autologinController" class="org.cloudfoundry.identity.uaa.login.AutologinController">
@@ -247,10 +246,10 @@
<constructor-arg ref="uaa" />
</bean>
</property>
- <property name="links" ref="links"/>
+ <property name="links" ref="links" />
</bean>
- <bean id="healthzEndpoint" class="org.cloudfoundry.identity.uaa.web.HealthzEndpoint"/>
+ <bean id="healthzEndpoint" class="org.cloudfoundry.identity.uaa.web.HealthzEndpoint" />
<oauth:resource id="uaa" access-token-uri="${uaa.token.url:http://localhost:8080/uaa/oauth/token}"
client-id="login" client-secret="${LOGIN_SECRET:loginsecret}" type="client_credentials" />
@@ -272,4 +271,48 @@
<property name="links" ref="links" />
</bean>
+ <beans profile="default">
+ <bean id="remoteAuthenticationManager" class="org.cloudfoundry.identity.uaa.login.RemoteUaaAuthenticationManager">
+ <property name="loginUrl" value="${uaa.login.url:http://localhost:8080/uaa/authenticate}" />
+ </bean>
+ </beans>
+
+ <beans profile="ldap">
+
+ <sec:authentication-manager alias="ldapAuthenticationManager">
+ <sec:authentication-provider ref="ldapAuthProvider" />
+ </sec:authentication-manager>
+
+ <bean id="remoteAuthenticationManager" class="org.cloudfoundry.identity.uaa.login.UsernamePasswordExtractingAuthenticationManager">
+ <constructor-arg ref="ldapAuthenticationManager" />
+ </bean>
+
+ <bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
+ <constructor-arg value="${ldap.base.url:ldap://localhost:33389/dc=springframework,dc=org}" />
+ </bean>
+
+ <bean id="ldapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
+ <constructor-arg>
+ <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
+ <constructor-arg ref="contextSource" />
+ <property name="userDnPatterns">
+ <list>
+ <value>uid={0},ou=people</value>
+ </list>
+ </property>
+ </bean>
+ </constructor-arg>
+ <constructor-arg>
+ <bean class="org.springframework.security.ldap.authentication.NullLdapAuthoritiesPopulator" />
+ </constructor-arg>
+ <property name="authoritiesMapper">
+ <bean class="org.springframework.security.core.authority.mapping.SimpleAuthorityMapper">
+ <property name="defaultAuthority" value="ROLE_USER" />
+ </bean>
+ </property>
+ </bean>
+
+ </beans>
+
+
</beans>
View
6 src/test/java/org/cloudfoundry/identity/uaa/login/BootstrapTests.java
@@ -52,6 +52,12 @@ public void testRootContextDefaults() throws Exception {
assertNotNull(context.getBean("viewResolver", ViewResolver.class));
}
+ @Test
+ public void testLdapProfile() throws Exception {
+ context = getServletContext("ldap", "file:./src/main/webapp/WEB-INF/spring-servlet.xml");
+ assertNotNull(context.getBean("viewResolver", ViewResolver.class));
+ }
+
private GenericXmlApplicationContext getServletContext(String... resources) {
String profiles = null;
View
55 ...cloudfoundry/identity/uaa/login/UsernamePasswordExtractingAuthenticationManagerTests.java
@@ -0,0 +1,55 @@
+/*
+ * Cloud Foundry 2012.02.03 Beta
+ * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved.
+ *
+ * This product is licensed to you under the Apache License, Version 2.0 (the "License").
+ * You may not use this product except in compliance with the License.
+ *
+ * This product includes a number of subcomponents with
+ * separate copyright notices and license terms. Your use of these
+ * subcomponents is subject to the terms and conditions of the
+ * subcomponent's license, as noted in the LICENSE file.
+ */
+
+package org.cloudfoundry.identity.uaa.login;
+
+import static org.junit.Assert.assertSame;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.TestingAuthenticationToken;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.authority.AuthorityUtils;
+
+/**
+ * @author Dave Syer
+ *
+ */
+public class UsernamePasswordExtractingAuthenticationManagerTests {
+
+ private AuthenticationManager delegate = Mockito.mock(AuthenticationManager.class);
+
+ private UsernamePasswordExtractingAuthenticationManager manager = new UsernamePasswordExtractingAuthenticationManager(
+ delegate);
+
+ @Test
+ public void testAuthenticate() {
+ Authentication expected = new TestingAuthenticationToken("bar", "foo",
+ AuthorityUtils.commaSeparatedStringToAuthorityList("USER"));
+ Mockito.when(delegate.authenticate(Mockito.any(UsernamePasswordAuthenticationToken.class)))
+ .thenReturn(expected);
+ Authentication output = manager.authenticate(new TestingAuthenticationToken("foo", "bar"));
+ assertSame(expected, output);
+ }
+
+ @Test
+ public void testUsernamePassword() {
+ Authentication expected = new UsernamePasswordAuthenticationToken("bar", "foo",
+ AuthorityUtils.commaSeparatedStringToAuthorityList("USER"));
+ Authentication output = manager.authenticate(expected);
+ assertSame(expected, output);
+ }
+
+}
Something went wrong with that request. Please try again.