OpenID support contributed by Robin Bramley
Todo: * Improve Test Coverage * Replace Servlet with Filter * Add support for providers other than JanRain as it may be dead
This commit is contained in:
parent
6bfff55da3
commit
d81a806405
3
pom.xml
3
pom.xml
|
@ -199,6 +199,9 @@
|
|||
<contributor>
|
||||
<name>Mike Perham</name>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Robin Bramley</name>
|
||||
</contributor>
|
||||
</contributors>
|
||||
|
||||
<dependencies>
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security-sandbox</artifactId>
|
||||
<version>1.0.2</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-openid</artifactId>
|
||||
<name>Acegi Security System for Spring - OpenID support</name>
|
||||
<description>Acegi Security System for Spring - Support for OpenID</description>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>AcegiMaven</id>
|
||||
<name>Acegi 3rd party repository</name>
|
||||
<url>http://acegisecurity.sourceforge.net/maven</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<scm>
|
||||
<connection>scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity/sandbox/openid
|
||||
</connection>
|
||||
<developerConnection>
|
||||
scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity/sandbox/openid
|
||||
</developerConnection>
|
||||
<url>http://svn.sourceforge.net/viewcvs.cgi/acegisecurity/trunk/acegisecurity/sandbox/openid/</url>
|
||||
</scm>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-mock</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.janrain</groupId>
|
||||
<artifactId>Janrain-Openid</artifactId>
|
||||
<version>20070226</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>gnu</groupId>
|
||||
<artifactId>libidn</artifactId>
|
||||
<version>0.6.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.geronimo.specs</groupId>
|
||||
<artifactId>geronimo-servlet_2.4_spec</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>2.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
-->
|
||||
</dependencies>
|
||||
|
||||
<!--This doesn't even exist...-->
|
||||
<!--
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>jalopy-maven-plugin</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<configuration>
|
||||
<convention>../../jalopy.xml</convention>
|
||||
<failOnError>false</failOnError>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
-->
|
||||
</project>
|
|
@ -0,0 +1,36 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.providers.openid;
|
||||
|
||||
import org.acegisecurity.AuthenticationException;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates that OpenID authentication was cancelled
|
||||
*
|
||||
* @author Robin Bramley, Opsera Ltd
|
||||
* @version $Id:$
|
||||
*/
|
||||
public class AuthenticationCancelledException extends AuthenticationException {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public AuthenticationCancelledException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public AuthenticationCancelledException(String msg, Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.providers.openid;
|
||||
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.AuthenticationException;
|
||||
import org.acegisecurity.AuthenticationServiceException;
|
||||
import org.acegisecurity.BadCredentialsException;
|
||||
|
||||
import org.acegisecurity.providers.AuthenticationProvider;
|
||||
import org.acegisecurity.providers.cas.CasAuthoritiesPopulator;
|
||||
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Finalises the OpenID authentication by obtaining local roles
|
||||
*
|
||||
* @author Robin Bramley, Opsera Ltd.
|
||||
*/
|
||||
public class OpenIDAuthenticationProvider implements AuthenticationProvider, InitializingBean {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private CasAuthoritiesPopulator ssoAuthoritiesPopulator;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(this.ssoAuthoritiesPopulator, "The ssoAuthoritiesPopulator must be set");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.acegisecurity.providers.AuthenticationProvider#authenticate(org.acegisecurity.Authentication)
|
||||
*/
|
||||
public Authentication authenticate(Authentication authentication)
|
||||
throws AuthenticationException {
|
||||
if (!supports(authentication.getClass())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (authentication instanceof OpenIDAuthenticationToken) {
|
||||
OpenIDAuthenticationToken response = (OpenIDAuthenticationToken) authentication;
|
||||
OpenIDAuthenticationStatus status = response.getStatus();
|
||||
|
||||
// handle the various possibilites
|
||||
if (status == OpenIDAuthenticationStatus.SUCCESS) {
|
||||
//String message = "Log in succeeded: ";// + savedId;
|
||||
|
||||
/* TODO: allow for regex for mapping URL
|
||||
* e.g. http://mydomain.com/username
|
||||
* or http://{username}.mydomain.com
|
||||
*/
|
||||
|
||||
// Lookup user details
|
||||
UserDetails userDetails = this.ssoAuthoritiesPopulator.getUserDetails(response.getIdentityUrl());
|
||||
|
||||
authentication = new OpenIDAuthenticationToken(userDetails.getAuthorities(), response.getStatus(),
|
||||
response.getIdentityUrl());
|
||||
|
||||
return authentication;
|
||||
} else if (status == OpenIDAuthenticationStatus.CANCELLED) {
|
||||
throw new AuthenticationCancelledException("Log in cancelled");
|
||||
} else if (status == OpenIDAuthenticationStatus.ERROR) {
|
||||
throw new AuthenticationServiceException("Error message from server: " + response.getMessage());
|
||||
} else if (status == OpenIDAuthenticationStatus.FAILURE) {
|
||||
throw new BadCredentialsException("Log in failed - identity could not be verified");
|
||||
} else if (status == OpenIDAuthenticationStatus.SETUP_NEEDED) {
|
||||
throw new AuthenticationServiceException(
|
||||
"The server responded setup was needed, which shouldn't happen");
|
||||
} else {
|
||||
throw new AuthenticationServiceException("Unrecognized return value " + status.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setSsoAuthoritiesPopulator(CasAuthoritiesPopulator ssoAuthoritiesPopulator) {
|
||||
this.ssoAuthoritiesPopulator = ssoAuthoritiesPopulator;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.acegisecurity.providers.AuthenticationProvider#supports(java.lang.Class)
|
||||
*/
|
||||
public boolean supports(Class authentication) {
|
||||
if (OpenIDAuthenticationToken.class.isAssignableFrom(authentication)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.providers.openid;
|
||||
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* Based on JanRain status codes
|
||||
*
|
||||
* @author JanRain Inc.
|
||||
* @author Robin Bramley, Opsera Ltd
|
||||
*/
|
||||
public class OpenIDAuthenticationStatus implements Serializable {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final long serialVersionUID = -998877665544332211L;
|
||||
private static int nextOrdinal = 0;
|
||||
|
||||
/** This code indicates a successful authentication request */
|
||||
public static final OpenIDAuthenticationStatus SUCCESS = new OpenIDAuthenticationStatus("success");
|
||||
|
||||
/** This code indicates a failed authentication request */
|
||||
public static final OpenIDAuthenticationStatus FAILURE = new OpenIDAuthenticationStatus("failure");
|
||||
|
||||
/** This code indicates the server reported an error */
|
||||
public static final OpenIDAuthenticationStatus ERROR = new OpenIDAuthenticationStatus("error");
|
||||
|
||||
/** This code indicates that the user needs to do additional work to prove their identity */
|
||||
public static final OpenIDAuthenticationStatus SETUP_NEEDED = new OpenIDAuthenticationStatus("setup needed");
|
||||
|
||||
/** This code indicates that the user cancelled their login request */
|
||||
public static final OpenIDAuthenticationStatus CANCELLED = new OpenIDAuthenticationStatus("cancelled");
|
||||
private static final OpenIDAuthenticationStatus[] PRIVATE_VALUES = {SUCCESS, FAILURE, ERROR, SETUP_NEEDED, CANCELLED};
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private String name;
|
||||
private final int ordinal = nextOrdinal++;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
private OpenIDAuthenticationStatus(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
private Object readResolve() throws ObjectStreamException {
|
||||
return PRIVATE_VALUES[ordinal];
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.providers.openid;
|
||||
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
|
||||
import org.acegisecurity.providers.AbstractAuthenticationToken;
|
||||
|
||||
|
||||
/**
|
||||
* OpenID Authentication Token
|
||||
*
|
||||
* @author Robin Bramley, Opsera Ltd
|
||||
*/
|
||||
public class OpenIDAuthenticationToken extends AbstractAuthenticationToken {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private OpenIDAuthenticationStatus status;
|
||||
private String identityUrl;
|
||||
private String message;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public OpenIDAuthenticationToken(OpenIDAuthenticationStatus status, String identityUrl, String message) {
|
||||
super(new GrantedAuthority[0]);
|
||||
this.status = status;
|
||||
this.identityUrl = identityUrl;
|
||||
this.message = message;
|
||||
setAuthenticated(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Created by the OpenIDAuthenticationProvider on successful authentication.
|
||||
* <b>Do not use directly</b>
|
||||
*
|
||||
* @param authorities
|
||||
* @param status
|
||||
* @param identityUrl
|
||||
*/
|
||||
public OpenIDAuthenticationToken(GrantedAuthority[] authorities, OpenIDAuthenticationStatus status,
|
||||
String identityUrl) {
|
||||
super(authorities);
|
||||
this.status = status;
|
||||
this.identityUrl = identityUrl;
|
||||
|
||||
setAuthenticated(true);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.acegisecurity.Authentication#getCredentials()
|
||||
*/
|
||||
public Object getCredentials() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getIdentityUrl() {
|
||||
return identityUrl;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.acegisecurity.Authentication#getPrincipal()
|
||||
*/
|
||||
public Object getPrincipal() {
|
||||
return identityUrl;
|
||||
}
|
||||
|
||||
public OpenIDAuthenticationStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
<html>
|
||||
<body>
|
||||
An authentication provider that can process <a href="http://openid.net">OpenID</a>
|
||||
Authentication Tokens as created by implementations of the OpenIDConsumer interface.
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,26 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.ui.openid;
|
||||
|
||||
/**
|
||||
* Constants required by OpenID classes
|
||||
*
|
||||
* @author Robin Bramley, Opsera Ltd
|
||||
*/
|
||||
public class OpenIDConstants {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
public static final String OPENID_SESSION_MAP_KEY = "openid.session";
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.ui.openid;
|
||||
|
||||
import org.acegisecurity.providers.openid.OpenIDAuthenticationToken;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
|
||||
/**
|
||||
* An interface for OpenID library implementations
|
||||
*
|
||||
* @author Robin Bramley, Opsera Ltd
|
||||
*
|
||||
*/
|
||||
public interface OpenIDConsumer {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Start the authentication process
|
||||
*
|
||||
* @param req
|
||||
* @param identityUrl
|
||||
*
|
||||
* @return redirection URL
|
||||
*
|
||||
* @throws OpenIDConsumerException
|
||||
*/
|
||||
public String beginConsumption(HttpServletRequest req, String identityUrl)
|
||||
throws OpenIDConsumerException;
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @param req
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws OpenIDConsumerException
|
||||
*/
|
||||
public OpenIDAuthenticationToken endConsumption(HttpServletRequest req)
|
||||
throws OpenIDConsumerException;
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @param returnToUrl
|
||||
*/
|
||||
public void setReturnToUrl(String returnToUrl);
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.ui.openid;
|
||||
|
||||
/**
|
||||
* Thrown by an OpenIDConsumer if it cannot process a request
|
||||
*
|
||||
* @author Robin Bramley, Opsera Ltd
|
||||
*/
|
||||
public class OpenIDConsumerException extends Exception {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public OpenIDConsumerException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public OpenIDConsumerException(String message, Throwable t) {
|
||||
super(message, t);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.ui.openid;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
/**
|
||||
* This servlet starts the OpenID authentication process.
|
||||
* <br/>
|
||||
* <br/>Sample web.xml configuration:
|
||||
* <br/>
|
||||
* <br/> <servlet>
|
||||
* <br/> <servlet-name>openid</servlet-name>
|
||||
* <br/> <servlet-class>org.acegisecurity.ui.openid.OpenIDLoginInitiationServlet</servlet-class>
|
||||
* <br/> <load-on-startup>1</load-on-startup>
|
||||
* <br/> <init-param>
|
||||
* <br/> <description>The error page - will receive error "message"</description>
|
||||
* <br/> <param-name>errorPage</param-name>
|
||||
* <br/> <param-value>index.jsp</param-value>
|
||||
* <br/> </init-param>
|
||||
* <br/> </servlet>
|
||||
* <br/> <servlet-mapping>
|
||||
* <br/> <servlet-name>openid</servlet-name>
|
||||
* <br/> <url-pattern>/j_acegi_openid_start</url-pattern>
|
||||
* <br/> </servlet-mapping>
|
||||
* <br/>
|
||||
* <br/>Sample login form:
|
||||
* <br/><form method="POST" action="j_acegi_openid_start">
|
||||
* <br/> <input type="text" name="j_username" />
|
||||
* <br/> <input type="password" name="j_password" />
|
||||
* <br/> <input type="submit" value="Verify" />
|
||||
* <br/></form>
|
||||
* <br/>
|
||||
* <br/>Usage notes:
|
||||
* <li>Requires an <code>openIDConsumer</code> Spring bean implementing the {@link OpenIDConsumer} interface</li>
|
||||
* <li>It will pass off to standard form-based authentication if appropriate</li>
|
||||
* (note that <code>AuthenticationProcessingFilter</code> requires j_username, j_password)
|
||||
* <br/>
|
||||
* <br/>Outstanding items:
|
||||
* TODO: config flag for whether OpenID only or dual mode?
|
||||
* TODO: username matching logic
|
||||
*
|
||||
* @author Robin Bramley, Opsera Ltd
|
||||
* @version $Id:$
|
||||
*/
|
||||
public class OpenIDLoginInitiationServlet extends HttpServlet {
|
||||
final static long serialVersionUID = -997766L;
|
||||
private static final Log logger = LogFactory.getLog(OpenIDLoginInitiationServlet.class);
|
||||
private static final String passwordField = "j_password";
|
||||
|
||||
/**
|
||||
* Servlet config key for looking up the the HttpServletRequest parameter name
|
||||
* containing the OpenID Identity URL from the Servlet config.
|
||||
* <br/><b>Only set the identityField servlet init-param if you are not using</b> <code>j_username</code>
|
||||
* <br/>
|
||||
* <br/> <init-param>
|
||||
* <br/> <description>The identity form field parameter</description>
|
||||
* <br/> <param-name>identityField</param-name>
|
||||
* <br/> <param-value>/openid_url</param-value>
|
||||
* <br/> </init-param>
|
||||
*/
|
||||
public static final String IDENTITY_FIELD_KEY = "identityField";
|
||||
|
||||
/**
|
||||
* Servlet config key for the return to URL
|
||||
*/
|
||||
public static final String ERROR_PAGE_KEY = "errorPage";
|
||||
|
||||
/**
|
||||
* Servlet config key for looking up the form login URL from the Servlet config.
|
||||
* <br/><b>Only set the formLogin servlet init-param if you are not using</b> <code>/j_acegi_security_check</code>
|
||||
* <br/>
|
||||
* <br/> <init-param>
|
||||
* <br/> <description>The form login URL - for standard authentication</description>
|
||||
* <br/> <param-name>formLogin</param-name>
|
||||
* <br/> <param-value>/custom_acegi_security_check</param-value>
|
||||
* <br/> </init-param>
|
||||
*/
|
||||
public static final String FORM_LOGIN_URL_KEY = "formLogin";
|
||||
|
||||
/**
|
||||
* Spring context key for the OpenID consumer bean
|
||||
*/
|
||||
public static final String CONSUMER_KEY = "openIDConsumer";
|
||||
private String errorPage = "index.jsp";
|
||||
private String identityField = "j_username";
|
||||
private String formLoginUrl = "/j_acegi_security_check";
|
||||
|
||||
/**
|
||||
* Check for init-params
|
||||
*
|
||||
* @Override
|
||||
*/
|
||||
public void init() throws ServletException {
|
||||
super.init();
|
||||
|
||||
String configErrorPage = getServletConfig()
|
||||
.getInitParameter(ERROR_PAGE_KEY);
|
||||
|
||||
if (StringUtils.hasText(configErrorPage)) {
|
||||
errorPage = configErrorPage;
|
||||
}
|
||||
|
||||
String configIdentityField = getServletConfig()
|
||||
.getInitParameter(IDENTITY_FIELD_KEY);
|
||||
|
||||
if (StringUtils.hasText(configIdentityField)) {
|
||||
identityField = configIdentityField;
|
||||
}
|
||||
|
||||
String configFormLoginUrl = getServletConfig()
|
||||
.getInitParameter(FORM_LOGIN_URL_KEY);
|
||||
|
||||
if (StringUtils.hasText(configFormLoginUrl)) {
|
||||
formLoginUrl = configFormLoginUrl;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the form post - all the work is done by the OpenIDConsumer.beginConsumption method
|
||||
*
|
||||
* @Override
|
||||
*/
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse res)
|
||||
throws ServletException, IOException {
|
||||
WebApplicationContext webApplicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
|
||||
OpenIDConsumer consumer = (OpenIDConsumer) webApplicationContext.getBean(CONSUMER_KEY);
|
||||
|
||||
// get the submitted id field
|
||||
String id = req.getParameter(identityField);
|
||||
|
||||
// assume page will validate?
|
||||
//TODO: null checking!
|
||||
|
||||
//TODO: pattern matching
|
||||
String password = req.getParameter(passwordField);
|
||||
|
||||
if ((password != null) && (password.length() > 0)) {
|
||||
logger.debug("Attempting to authenticate using username/password");
|
||||
|
||||
// forward to authenticationProcessingFilter (/j_acegi_security_check - depends on param names)
|
||||
req.getRequestDispatcher(formLoginUrl).forward(req, res);
|
||||
|
||||
} else {
|
||||
// send the user the redirect url to proceed with OpenID authentication
|
||||
try {
|
||||
String redirect = consumer.beginConsumption(req, id);
|
||||
logger.debug("Redirecting to: " + redirect);
|
||||
res.sendRedirect(redirect);
|
||||
} catch (OpenIDConsumerException oice) {
|
||||
logger.error("Consumer error!", oice);
|
||||
req.setAttribute("message", oice.getMessage());
|
||||
req.getRequestDispatcher(errorPage).forward(req, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.ui.openid;
|
||||
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.AuthenticationException;
|
||||
import org.acegisecurity.AuthenticationServiceException;
|
||||
|
||||
import org.acegisecurity.providers.openid.OpenIDAuthenticationToken;
|
||||
|
||||
import org.acegisecurity.ui.AbstractProcessingFilter;
|
||||
import org.acegisecurity.ui.webapp.AuthenticationProcessingFilter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
|
||||
/**
|
||||
* Process the response from the OpenID server to the returnTo URL.
|
||||
*
|
||||
* @author Robin Bramley, Opsera Ltd
|
||||
* @version $Id:$
|
||||
*/
|
||||
public class OpenIDResponseProcessingFilter extends AbstractProcessingFilter {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private OpenIDConsumer consumer;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.acegisecurity.ui.AbstractProcessingFilter#attemptAuthentication(javax.servlet.http.HttpServletRequest)
|
||||
* @Override
|
||||
*/
|
||||
public Authentication attemptAuthentication(HttpServletRequest req)
|
||||
throws AuthenticationException {
|
||||
OpenIDAuthenticationToken token;
|
||||
|
||||
try {
|
||||
token = consumer.endConsumption(req);
|
||||
} catch (OpenIDConsumerException oice) {
|
||||
throw new AuthenticationServiceException("Consumer error", oice);
|
||||
}
|
||||
|
||||
// delegate to the auth provider
|
||||
Authentication authentication = this.getAuthenticationManager().authenticate(token);
|
||||
|
||||
if (authentication.isAuthenticated()) {
|
||||
req.getSession()
|
||||
.setAttribute(AuthenticationProcessingFilter.ACEGI_SECURITY_LAST_USERNAME_KEY, token.getIdentityUrl());
|
||||
}
|
||||
|
||||
return authentication;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.acegisecurity.ui.AbstractProcessingFilter#getDefaultFilterProcessesUrl()
|
||||
* @Override
|
||||
*/
|
||||
public String getDefaultFilterProcessesUrl() {
|
||||
return "/j_acegi_openid_security_check";
|
||||
}
|
||||
|
||||
// dependency injection
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @param consumer The OpenIDConsumer to set.
|
||||
*/
|
||||
public void setConsumer(OpenIDConsumer consumer) {
|
||||
this.consumer = consumer;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.ui.openid.consumers;
|
||||
|
||||
import com.janrain.openid.consumer.AuthRequest;
|
||||
import com.janrain.openid.consumer.Consumer;
|
||||
import com.janrain.openid.consumer.ErrorResponse;
|
||||
import com.janrain.openid.consumer.Response;
|
||||
import com.janrain.openid.consumer.StatusCode;
|
||||
import com.janrain.openid.store.OpenIDStore;
|
||||
|
||||
import org.acegisecurity.providers.openid.OpenIDAuthenticationStatus;
|
||||
import org.acegisecurity.providers.openid.OpenIDAuthenticationToken;
|
||||
|
||||
import org.acegisecurity.ui.openid.OpenIDConstants;
|
||||
import org.acegisecurity.ui.openid.OpenIDConsumer;
|
||||
import org.acegisecurity.ui.openid.OpenIDConsumerException;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
|
||||
/**
|
||||
* OpenIDConsumer implementation using the JanRain OpenID library
|
||||
*
|
||||
* @author Robin Bramley, Opsera Ltd
|
||||
* @version $Id:$
|
||||
*/
|
||||
public class JanRainOpenIDConsumer implements OpenIDConsumer, InitializingBean {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final String SAVED_ID_SESSION_KEY = "savedId";
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private OpenIDStore store;
|
||||
private String returnToUrl = "j_acegi_openid_security_check";
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(this.store, "An OpenIDStore must be set on the store property");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.acegisecurity.ui.openid.OpenIDConsumer#beginConsumption(java.lang.String)
|
||||
*/
|
||||
public String beginConsumption(HttpServletRequest req, String identityUrl)
|
||||
throws OpenIDConsumerException {
|
||||
// fetch/create a session Map for the consumer's use
|
||||
HttpSession session = req.getSession();
|
||||
Map sessionMap = (Map) session.getAttribute(OpenIDConstants.OPENID_SESSION_MAP_KEY);
|
||||
|
||||
if (sessionMap == null) {
|
||||
sessionMap = new HashMap();
|
||||
session.setAttribute(OpenIDConstants.OPENID_SESSION_MAP_KEY, sessionMap);
|
||||
}
|
||||
|
||||
Consumer openIdConsumer = new Consumer(sessionMap, store);
|
||||
|
||||
// Create an Authrequest object from the submitted value
|
||||
AuthRequest ar;
|
||||
|
||||
try {
|
||||
ar = openIdConsumer.begin(identityUrl);
|
||||
} catch (IOException ioe) {
|
||||
req.getSession().setAttribute(SAVED_ID_SESSION_KEY, escapeAttr(identityUrl));
|
||||
throw new OpenIDConsumerException("Error on begin consumption for " + identityUrl, ioe);
|
||||
}
|
||||
|
||||
// construct trust root and return to URLs.
|
||||
String port = "";
|
||||
|
||||
if (req.getServerPort() != 80) {
|
||||
port = ":" + req.getServerPort();
|
||||
}
|
||||
|
||||
String trustRoot = req.getScheme() + "://" + req.getServerName() + port + "/";
|
||||
String cp = req.getContextPath();
|
||||
|
||||
if (!cp.equals("")) {
|
||||
cp = cp.substring(1) + "/";
|
||||
}
|
||||
|
||||
String returnTo = trustRoot + cp + returnToUrl;
|
||||
|
||||
// send the user the redirect url to proceed with OpenID authentication
|
||||
return ar.redirectUrl(trustRoot, returnTo);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.acegisecurity.ui.openid.OpenIDConsumer#endConsumption(javax.servlet.http.HttpServletRequest)
|
||||
*/
|
||||
public OpenIDAuthenticationToken endConsumption(HttpServletRequest req)
|
||||
throws OpenIDConsumerException {
|
||||
HttpSession session = req.getSession();
|
||||
Map sessionMap = (Map) session.getAttribute(OpenIDConstants.OPENID_SESSION_MAP_KEY);
|
||||
|
||||
if (sessionMap == null) {
|
||||
sessionMap = new HashMap();
|
||||
session.setAttribute(OpenIDConstants.OPENID_SESSION_MAP_KEY, sessionMap);
|
||||
}
|
||||
|
||||
// get a Consumer instance
|
||||
Consumer openIdConsumer = new Consumer(sessionMap, store);
|
||||
|
||||
// convert the argument map into the form the library uses with a handy
|
||||
// convenience function
|
||||
Map query = Consumer.filterArgs(req.getParameterMap());
|
||||
|
||||
// Check the arguments to see what the response was.
|
||||
Response response = openIdConsumer.complete(query);
|
||||
|
||||
String message = "";
|
||||
OpenIDAuthenticationStatus status;
|
||||
|
||||
StatusCode statusCode = response.getStatus();
|
||||
|
||||
if (statusCode == StatusCode.CANCELLED) {
|
||||
status = OpenIDAuthenticationStatus.CANCELLED;
|
||||
} else if (statusCode == StatusCode.ERROR) {
|
||||
status = OpenIDAuthenticationStatus.ERROR;
|
||||
message = ((ErrorResponse) response).getMessage();
|
||||
} else if (statusCode == StatusCode.FAILURE) {
|
||||
status = OpenIDAuthenticationStatus.FAILURE;
|
||||
} else if (statusCode == StatusCode.SETUP_NEEDED) {
|
||||
status = OpenIDAuthenticationStatus.SETUP_NEEDED;
|
||||
} else if (statusCode == StatusCode.SUCCESS) {
|
||||
status = OpenIDAuthenticationStatus.SUCCESS;
|
||||
} else {
|
||||
// unknown status code
|
||||
throw new OpenIDConsumerException("Unknown response status " + statusCode.toString());
|
||||
}
|
||||
|
||||
return new OpenIDAuthenticationToken(status, response.getIdentityUrl(), message);
|
||||
}
|
||||
|
||||
/*
|
||||
* This method escapes characters in a string that can cause problems in
|
||||
* HTML
|
||||
*/
|
||||
private String escapeAttr(String s) {
|
||||
if (s == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
StringBuffer result = new StringBuffer();
|
||||
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char c = s.charAt(i);
|
||||
|
||||
if (c == '<') {
|
||||
result.append("<");
|
||||
} else if (c == '>') {
|
||||
result.append(">");
|
||||
} else if (c == '&') {
|
||||
result.append("&");
|
||||
} else if (c == '\"') {
|
||||
result.append(""");
|
||||
} else if (c == '\'') {
|
||||
result.append("'");
|
||||
} else if (c == '\\') {
|
||||
result.append("\");
|
||||
} else {
|
||||
result.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public void setReturnToUrl(String returnToUrl) {
|
||||
this.returnToUrl = returnToUrl;
|
||||
}
|
||||
|
||||
// dependency injection
|
||||
public void setStore(OpenIDStore store) {
|
||||
this.store = store;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<html>
|
||||
<body>
|
||||
Implementations of the OpenIDConsumer interface using 3rd party libraries.
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,5 @@
|
|||
<html>
|
||||
<body>
|
||||
Authenticates standard web browser users via <a href="http://openid.net">OpenID</a>.
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,40 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.providers.openid;
|
||||
|
||||
import org.acegisecurity.AuthenticationException;
|
||||
import org.acegisecurity.GrantedAuthority;
|
||||
import org.acegisecurity.GrantedAuthorityImpl;
|
||||
|
||||
import org.acegisecurity.providers.cas.CasAuthoritiesPopulator;
|
||||
|
||||
import org.acegisecurity.userdetails.User;
|
||||
import org.acegisecurity.userdetails.UserDetails;
|
||||
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @author Robin Bramley, Opsera Ltd
|
||||
*/
|
||||
public class MockAuthoritiesPopulator implements CasAuthoritiesPopulator {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public UserDetails getUserDetails(String ssoUserId)
|
||||
throws AuthenticationException {
|
||||
return new User(ssoUserId, "password", true, true, true, true,
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_A"), new GrantedAuthorityImpl("ROLE_B")});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,194 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.providers.openid;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.AuthenticationServiceException;
|
||||
import org.acegisecurity.BadCredentialsException;
|
||||
|
||||
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link OpenIDAuthenticationProvider}
|
||||
*
|
||||
* @author Robin Bramley, Opsera Ltd
|
||||
*/
|
||||
public class OpenIDAuthenticationProviderTests extends TestCase {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final String USERNAME = "user.acegiopenid.com";
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/*
|
||||
* Test method for 'org.acegisecurity.providers.openid.OpenIDAuthenticationProvider.authenticate(Authentication)'
|
||||
*/
|
||||
public void testAuthenticateCancel() {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
provider.setSsoAuthoritiesPopulator(new MockAuthoritiesPopulator());
|
||||
|
||||
Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.CANCELLED, USERNAME, "");
|
||||
|
||||
assertFalse(preAuth.isAuthenticated());
|
||||
|
||||
try {
|
||||
provider.authenticate(preAuth);
|
||||
fail("Should throw an AuthenticationException");
|
||||
} catch (AuthenticationCancelledException expected) {
|
||||
assertEquals("Log in cancelled", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for 'org.acegisecurity.providers.openid.OpenIDAuthenticationProvider.authenticate(Authentication)'
|
||||
*/
|
||||
public void testAuthenticateError() {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
provider.setSsoAuthoritiesPopulator(new MockAuthoritiesPopulator());
|
||||
|
||||
Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.ERROR, USERNAME, "");
|
||||
|
||||
assertFalse(preAuth.isAuthenticated());
|
||||
|
||||
try {
|
||||
provider.authenticate(preAuth);
|
||||
fail("Should throw an AuthenticationException");
|
||||
} catch (AuthenticationServiceException expected) {
|
||||
assertEquals("Error message from server: ", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for 'org.acegisecurity.providers.openid.OpenIDAuthenticationProvider.authenticate(Authentication)'
|
||||
*/
|
||||
public void testAuthenticateFailure() {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
provider.setSsoAuthoritiesPopulator(new MockAuthoritiesPopulator());
|
||||
|
||||
Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.FAILURE, USERNAME, "");
|
||||
|
||||
assertFalse(preAuth.isAuthenticated());
|
||||
|
||||
try {
|
||||
provider.authenticate(preAuth);
|
||||
fail("Should throw an AuthenticationException");
|
||||
} catch (BadCredentialsException expected) {
|
||||
assertEquals("Log in failed - identity could not be verified", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for 'org.acegisecurity.providers.openid.OpenIDAuthenticationProvider.authenticate(Authentication)'
|
||||
*/
|
||||
public void testAuthenticateSetupNeeded() {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
provider.setSsoAuthoritiesPopulator(new MockAuthoritiesPopulator());
|
||||
|
||||
Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SETUP_NEEDED, USERNAME, "");
|
||||
|
||||
assertFalse(preAuth.isAuthenticated());
|
||||
|
||||
try {
|
||||
provider.authenticate(preAuth);
|
||||
fail("Should throw an AuthenticationException");
|
||||
} catch (AuthenticationServiceException expected) {
|
||||
assertEquals("The server responded setup was needed, which shouldn't happen", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for 'org.acegisecurity.providers.openid.OpenIDAuthenticationProvider.authenticate(Authentication)'
|
||||
*/
|
||||
public void testAuthenticateSuccess() {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
provider.setSsoAuthoritiesPopulator(new MockAuthoritiesPopulator());
|
||||
|
||||
Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, USERNAME, "");
|
||||
|
||||
assertFalse(preAuth.isAuthenticated());
|
||||
|
||||
Authentication postAuth = provider.authenticate(preAuth);
|
||||
|
||||
assertNotNull(postAuth);
|
||||
assertTrue(postAuth instanceof OpenIDAuthenticationToken);
|
||||
assertTrue(postAuth.isAuthenticated());
|
||||
assertNotNull(postAuth.getPrincipal());
|
||||
assertEquals(preAuth.getPrincipal(), postAuth.getPrincipal());
|
||||
assertNotNull(postAuth.getAuthorities());
|
||||
assertTrue(postAuth.getAuthorities().length > 0);
|
||||
assertTrue(((OpenIDAuthenticationToken) postAuth).getStatus() == OpenIDAuthenticationStatus.SUCCESS);
|
||||
assertTrue(((OpenIDAuthenticationToken) postAuth).getMessage() == null);
|
||||
}
|
||||
|
||||
public void testDetectsMissingAuthoritiesPopulator() {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
|
||||
try {
|
||||
provider.afterPropertiesSet();
|
||||
fail("Should have thrown Exception");
|
||||
} catch (Exception expected) {
|
||||
assertEquals("The ssoAuthoritiesPopulator must be set", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for 'org.acegisecurity.providers.openid.OpenIDAuthenticationProvider.supports(Class)'
|
||||
*/
|
||||
public void testDoesntSupport() {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
provider.setSsoAuthoritiesPopulator(new MockAuthoritiesPopulator());
|
||||
|
||||
assertFalse(provider.supports(UsernamePasswordAuthenticationToken.class));
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for 'org.acegisecurity.providers.openid.OpenIDAuthenticationProvider.authenticate(Authentication)'
|
||||
*/
|
||||
public void testIgnoresUserPassAuthToken() {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
provider.setSsoAuthoritiesPopulator(new MockAuthoritiesPopulator());
|
||||
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(USERNAME, "password");
|
||||
assertEquals(null, provider.authenticate(token));
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for 'org.acegisecurity.providers.openid.OpenIDAuthenticationProvider.supports(Class)'
|
||||
*/
|
||||
public void testSupports() {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
provider.setSsoAuthoritiesPopulator(new MockAuthoritiesPopulator());
|
||||
|
||||
assertTrue(provider.supports(OpenIDAuthenticationToken.class));
|
||||
}
|
||||
|
||||
public void testValidation() throws Exception {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
provider.setSsoAuthoritiesPopulator(new MockAuthoritiesPopulator());
|
||||
provider.afterPropertiesSet();
|
||||
|
||||
provider.setSsoAuthoritiesPopulator(null);
|
||||
|
||||
try {
|
||||
provider.afterPropertiesSet();
|
||||
fail("IllegalArgumentException expected, ssoAuthoritiesPopulator is null");
|
||||
} catch (IllegalArgumentException e) {
|
||||
//expected
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.ui.openid;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.acegisecurity.AbstractAuthenticationManager;
|
||||
import org.acegisecurity.Authentication;
|
||||
import org.acegisecurity.AuthenticationException;
|
||||
import org.acegisecurity.BadCredentialsException;
|
||||
|
||||
import org.acegisecurity.providers.cas.CasAuthoritiesPopulator;
|
||||
import org.acegisecurity.providers.openid.MockAuthoritiesPopulator;
|
||||
import org.acegisecurity.providers.openid.OpenIDAuthenticationStatus;
|
||||
import org.acegisecurity.providers.openid.OpenIDAuthenticationToken;
|
||||
|
||||
import org.acegisecurity.ui.openid.consumers.MockOpenIDConsumer;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link OpenIDResponseProcessingFilter}
|
||||
*
|
||||
* @author Robin Bramley, Opsera Ltd
|
||||
*/
|
||||
public class OpenIDResponseProcessingFilterTests extends TestCase {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final String USERNAME = "user.acegiopenid.com";
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/*
|
||||
* Test method for 'org.acegisecurity.ui.openid.OpenIDResponseProcessingFilter.attemptAuthentication(HttpServletRequest)'
|
||||
*/
|
||||
public void testAttemptAuthenticationFailure() {
|
||||
// set up mock objects
|
||||
MockOpenIDAuthenticationManager mockAuthManager = new MockOpenIDAuthenticationManager(false);
|
||||
|
||||
OpenIDAuthenticationToken token = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.FAILURE, USERNAME, "");
|
||||
MockOpenIDConsumer mockConsumer = new MockOpenIDConsumer();
|
||||
mockConsumer.setToken(token);
|
||||
|
||||
MockHttpServletRequest req = new MockHttpServletRequest();
|
||||
|
||||
OpenIDResponseProcessingFilter filter = new OpenIDResponseProcessingFilter();
|
||||
filter.setConsumer(mockConsumer);
|
||||
filter.setAuthenticationManager(mockAuthManager);
|
||||
|
||||
// run test
|
||||
try {
|
||||
filter.attemptAuthentication(req);
|
||||
fail("Should've thrown exception");
|
||||
} catch (BadCredentialsException expected) {
|
||||
assertEquals("MockOpenIDAuthenticationManager instructed to deny access", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for 'org.acegisecurity.ui.openid.OpenIDResponseProcessingFilter.attemptAuthentication(HttpServletRequest)'
|
||||
*/
|
||||
public void testAttemptAuthenticationHttpServletRequest() {
|
||||
// set up mock objects
|
||||
MockOpenIDAuthenticationManager mockAuthManager = new MockOpenIDAuthenticationManager(true);
|
||||
|
||||
OpenIDAuthenticationToken token = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, USERNAME, "");
|
||||
MockOpenIDConsumer mockConsumer = new MockOpenIDConsumer();
|
||||
mockConsumer.setToken(token);
|
||||
|
||||
MockHttpServletRequest req = new MockHttpServletRequest();
|
||||
|
||||
OpenIDResponseProcessingFilter filter = new OpenIDResponseProcessingFilter();
|
||||
filter.setConsumer(mockConsumer);
|
||||
filter.setAuthenticationManager(mockAuthManager);
|
||||
|
||||
// run test
|
||||
Authentication authentication = filter.attemptAuthentication(req);
|
||||
|
||||
// assertions
|
||||
assertNotNull(authentication);
|
||||
assertTrue(authentication.isAuthenticated());
|
||||
assertTrue(authentication instanceof OpenIDAuthenticationToken);
|
||||
assertNotNull(authentication.getPrincipal());
|
||||
assertEquals(USERNAME, authentication.getPrincipal());
|
||||
assertNotNull(authentication.getAuthorities());
|
||||
assertTrue(authentication.getAuthorities().length > 0);
|
||||
assertTrue(((OpenIDAuthenticationToken) authentication).getStatus() == OpenIDAuthenticationStatus.SUCCESS);
|
||||
assertTrue(((OpenIDAuthenticationToken) authentication).getMessage() == null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for 'org.acegisecurity.ui.openid.OpenIDResponseProcessingFilter.getDefaultFilterProcessesUrl()'
|
||||
*/
|
||||
public void testGetDefaultFilterProcessesUrl() {
|
||||
OpenIDResponseProcessingFilter filter = new OpenIDResponseProcessingFilter();
|
||||
assertEquals("/j_acegi_openid_security_check", filter.getDefaultFilterProcessesUrl());
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
// private mock AuthenticationManager
|
||||
private class MockOpenIDAuthenticationManager extends AbstractAuthenticationManager {
|
||||
private CasAuthoritiesPopulator ssoAuthoritiesPopulator;
|
||||
private boolean grantAccess = true;
|
||||
|
||||
public MockOpenIDAuthenticationManager(boolean grantAccess) {
|
||||
this.grantAccess = grantAccess;
|
||||
ssoAuthoritiesPopulator = new MockAuthoritiesPopulator();
|
||||
}
|
||||
|
||||
public MockOpenIDAuthenticationManager() {
|
||||
super();
|
||||
ssoAuthoritiesPopulator = new MockAuthoritiesPopulator();
|
||||
}
|
||||
|
||||
public Authentication doAuthentication(Authentication authentication)
|
||||
throws AuthenticationException {
|
||||
if (grantAccess) {
|
||||
return new OpenIDAuthenticationToken(ssoAuthoritiesPopulator.getUserDetails(USERNAME).getAuthorities(),
|
||||
OpenIDAuthenticationStatus.SUCCESS, USERNAME);
|
||||
} else {
|
||||
throw new BadCredentialsException("MockOpenIDAuthenticationManager instructed to deny access");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.acegisecurity.ui.openid.consumers;
|
||||
|
||||
import org.acegisecurity.providers.openid.OpenIDAuthenticationToken;
|
||||
|
||||
import org.acegisecurity.ui.openid.OpenIDConsumer;
|
||||
import org.acegisecurity.ui.openid.OpenIDConsumerException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @author Robin Bramley, Opsera Ltd
|
||||
*/
|
||||
public class MockOpenIDConsumer implements OpenIDConsumer {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private OpenIDAuthenticationToken token;
|
||||
private String redirectUrl;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.acegisecurity.ui.openid.OpenIDConsumer#beginConsumption(javax.servlet.http.HttpServletRequest, java.lang.String)
|
||||
*/
|
||||
public String beginConsumption(HttpServletRequest req, String identityUrl)
|
||||
throws OpenIDConsumerException {
|
||||
return redirectUrl;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.acegisecurity.ui.openid.OpenIDConsumer#endConsumption(javax.servlet.http.HttpServletRequest)
|
||||
*/
|
||||
public OpenIDAuthenticationToken endConsumption(HttpServletRequest req)
|
||||
throws OpenIDConsumerException {
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the redirectUrl to be returned by beginConsumption
|
||||
*
|
||||
* @param redirectUrl
|
||||
*/
|
||||
public void setRedirectUrl(String redirectUrl) {
|
||||
this.redirectUrl = redirectUrl;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.acegisecurity.ui.openid.OpenIDConsumer#setReturnToUrl(java.lang.String)
|
||||
*/
|
||||
public void setReturnToUrl(String returnToUrl) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the token to be returned by endConsumption
|
||||
*
|
||||
* @param token
|
||||
*/
|
||||
public void setToken(OpenIDAuthenticationToken token) {
|
||||
this.token = token;
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
<modules>
|
||||
<module>webwork</module>
|
||||
<module>openid</module>
|
||||
<module>other</module>
|
||||
</modules>
|
||||
|
||||
|
|
Loading…
Reference in New Issue