Friday, September 10, 2010

Custom endpoint for Alfresco remote access

It happen more than often that we want to perform actions in the repository that require custom authentication processes. Usually we need to define a This is a way to implement such a thing.

1. Customize webscripts-framework-config.xml (Alfresco <>or share-config-custom (Alfresco 3.2 >)

1.1. Define an Authenticator

 <authenticator> 
<id>alfresco-custom-ticket</id>
<name>Alfresco Authenticator</name>
<description>Alfresco Authenticator&lt;/description>
<class>com.westernacher.wps.share.authenticate.customAuthenticator</class>
</authenticator>

Where the customAuthenticator Class encloses the logic of our customized authentication.

1.2. Define a Connector

 <connector>  
<id>external-alfresco</id>
<name>Simple Http Connector</name>
<description>Simple Alfresco - HTTP Connector</description>
<class>org.alfresco.connector.AlfrescoConnector</class>
<authenticator-id>alfresco-custom-ticket</authenticator-id>
</connector>
Its however important to remind that in alfresco 3.2 > the classes for the connector were mostly ported to the spring framework package.

example:
the class org.alfresco.connector.AlfrescoConnector should be replaced with org.springframework.extensions.webscripts.connector.AlfrescoConnector in alfresco 3.2 and more.

1.3. Define the endpoint

 <endpoint>
<id>my-custom-end-point</id>
<name>Custom Endpoint</name>
<description>System account access to Alfresco</description>
<connector-id>http</connector-id>
<endpoint-url>url-tha-prefixes-the-scripts-to-be-called</endpoint-url>
<unsecure>true</unsecure>
</endpoint>

In alfresco by example the end point URL is standardly known as : http://localhost:8080/alfresco/s

1.4. Implement our CustomAuthenticator class


 public class CustomAuthenticator extends AbstractAuthenticator { 
public final static String CS_PARAM_ALF_TICKET = "alfTicket";
private static
Log logger = LogFactory.getLog(CustomAuthenticator.class);
@Override
public ConnectorSession authenticate(String endpoint, Credentials credentials, ConnectorSession connectorSession) throws AuthenticationException {
ConnectorSession cs = null;
if (credentials != null) {
//get a valid ticket from Alfresco via a standard or custom method
final
String url = endpoint + "/getTicket";
GetMethod get = new GetMethod(url);
// username and coockie
String aCoockie = (String) credentials.getProperty(Credentials.CREDENTIAL_PASSWORD);
get.setRequestHeader("Cookie", aCoockie);
HttpClient client = new HttpClient();
try {
int res = client.executeMethod(get);
// read back the ticket
if (res == 200) {
String ticket;
try {
ticket = get.getResponseBodyAsString();
} catch (
Throwable err) {
logger.error("Error to obtain ticket for custom authorization", err);
// the ticket that came back could not be parsed
// this will cause the entire handshake to fail

throw new
AuthenticationException("Unable to retrieve login ticket from Alfresco");
}
if (logger.isDebugEnabled()) {
logger.debug("
Parsed ticket: " + ticket);
}
// place the ticket back into the connector session
if (connectorSession != null) {
connectorSession.setParameter(
CS_PARAM_ALF_TICKET, ticket);
// signal that this succeeded
cs = connectorSession;
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("Authentication failed, received response code: " + res);
}
}
} catch (
Throwable e) {
logger.error("
Error to authenticate by custom Authentication", e);
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("
Authentication failed, no credentials provided");
}
}
return cs;
}
@Override
public
boolean isAuthenticated(String endpoint, ConnectorSession connectorSession) {
return (connectorSession.getParameter(
CS_PARAM_ALF_TICKET) != null);
}
}