!Workflow Name: amset1authentication

!Constituent Services: InitAuthentication; AuthenticationService

!Workflow Description

This is just about the simplest Alfresco workflow and forms the basis of the method by which Alfresco secures all its SOAP over HTTP Web services.  In short, the workflow is initialised by receiving a message that contains the username and password of an Alfresco administration account. These are used to call the {{startSession }}operation in the [Authentication Service|AuthenticationService] which returns three strings: the ''username ''submitted in the initialisation message, a ''security ticket'', and a Java ''sessionid''.  The security ticket is used to validate further calls to Alfresco Web services.  It is valid for a default period of 5 minutes or until cancelled by calling the {{endSession }} operation which takes the ticket string as a parameter.\\

Note that by default the initialisation Web service request goes over the wire completely unsecured. An HTTPS (SSL) link will have to be created to fill this teensy weensy security hole.

!Technical Notes

Platform: GlassFishESB V2, NetBeans IDE 6.1 (including BPEL Designer, implementing WS-BPEL 2.0)
Java: 1.6.0_10; Java HotSpot(TM) Client VM 11.0-b15
System: Windows XP version 5.1 running on x86; Cp1252; en_GB (nb).

Alfresco Labs 3.1 running on remote server, 64-bit Java 1.6.0_13, Tomcat 6 on Red Hat Enterprise Linux 5.


!The Process

__Figure 1.1. AuthenticationProcess.bpel Netbeans process diagram__ (elements labelled)\\

[{Image src='amset1authenticationprocess2.png' width='633' height='647' align='left'  }]
\\

A. InitAuthentication Web service: a 'myRole' partner link, messages posted into this service.\\
B. External Alfresco Authentication Service.\\
1. Message containing Alfresco admin username and password(!) sent to InitAuthentication, which initializes run.\\
2. Admin username and password from incoming InitAuthentication message assigned to corresponding variables in Authentication startSession() operation.\\
3. Invoke Authentication Service startSession() operation.\\
4. Assign value of ticket string to endSession() variable.\\
5. Invoke Authentication Service endSession().\\
6. Assign variables to InitAuthentication service reply variable.\\
7. Reply to InitAuthentication service.\\


!The BPEL Script

The workflow scripts will be available from the AMSeT SourceForge repository so they won't all be reproduced here on the wiki. This first one might help those interested in the NetBeans BPEL Designer to see how the process diagram relates to the BPEL script. \\

__Code snippet 1.1. AuthenticationProcess.bpel__
%%prettify 
{{{
<?xml version="1.0" encoding="UTF-8"?>
<process
    name="AuthenticationProcess"
    targetNamespace="http://enterprise.netbeans.org/bpel/Amset2Authentication/AuthenticationProcess"
    xmlns="http://docs.oasis-open.org/wsbpel/2.0/process/executable"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:sxt="http://www.sun.com/wsbpel/2.0/process/executable/SUNExtension/Trace" 
    xmlns:sxed="http://www.sun.com/wsbpel/2.0/process/executable/SUNExtension/Editor"
    xmlns:tns="http://enterprise.netbeans.org/bpel/Amset2Authentication/AuthenticationProcess" xmlns:ns0="http://j2ee.netbeans.org/wsdl/Amset2Authentication/InitAuthenticationWS" xmlns:ns1="http://enterprise.netbeans.org/bpel/AuthenticationServiceWrapper" xmlns:ns2="http://www.alfresco.org/ws/service/authentication/1.0">
    <import namespace="http://j2ee.netbeans.org/wsdl/Amset2Authentication/InitAuthenticationWS" location="InitAuthenticationWS.wsdl" importType="http://schemas.xmlsoap.org/wsdl/"/>
    <import namespace="http://enterprise.netbeans.org/bpel/AuthenticationServiceWrapper" location="AuthenticationServiceWrapper.wsdl" importType="http://schemas.xmlsoap.org/wsdl/"/>
    <import namespace="http://www.alfresco.org/ws/service/authentication/1.0" location="AuthenticationService.wsdl" importType="http://schemas.xmlsoap.org/wsdl/"/>
    <partnerLinks>
        <!--[B]--><partnerLink name="AuthenticationServicePL" partnerLinkType="ns1:AuthenticationServiceSoapPortLinkType" partnerRole="AuthenticationServiceSoapPortRole"/>
        <!--[A]--><partnerLink name="InitAuthenticationPL" partnerLinkType="ns0:InitAuthenticationWS" myRole="InitAuthenticationWSPortTypeRole"/>
    </partnerLinks>
    <variables>
        <variable name="EndSessionOut" messageType="ns2:endSessionResponse"/>
        <variable name="EndSessionIn" messageType="ns2:endSessionRequest"/>
        <variable name="InitAuthenticationWSOperationOut" messageType="ns0:InitAuthenticationWSOperationResponse"/>
        <variable name="StartSessionOut" xmlns:auth="http://www.alfresco.org/ws/service/authentication/1.0" messageType="auth:startSessionResponse"/>
        <variable name="StartSessionIn" xmlns:auth="http://www.alfresco.org/ws/service/authentication/1.0" messageType="auth:startSessionRequest"/>
        <variable name="InitAuthenticationWSOperationIn" messageType="ns0:InitAuthenticationWSOperationRequest"/>
    </variables>
    <sequence>
        <!--[1]--><receive name="Receive1" createInstance="yes" partnerLink="InitAuthenticationPL" operation="InitAuthenticationWSOperation" portType="ns0:InitAuthenticationWSPortType" variable="InitAuthenticationWSOperationIn"/>
        <!--[2]--><assign name="Assign1">
            <copy>
                <from variable="InitAuthenticationWSOperationIn" part="username"/>
                <to>$StartSessionIn.parameters/ns2:username</to>
            </copy>
            <copy>
                <from variable="InitAuthenticationWSOperationIn" part="password"/>
                <to>$StartSessionIn.parameters/ns2:password</to>
            </copy>
        </assign>
        <!--[3]--><invoke name="Invoke1" partnerLink="AuthenticationServicePL" operation="startSession" xmlns:auth="http://www.alfresco.org/ws/service/authentication/1.0" portType="auth:AuthenticationServiceSoapPort" inputVariable="StartSessionIn" outputVariable="StartSessionOut"/>
        <!--[4]--><assign name="Assign2">
            <copy>
                <from>$StartSessionOut.parameters/ns2:startSessionReturn/ns2:ticket</from>
                <to>$EndSessionIn.parameters/ns2:ticket</to>
            </copy>
        </assign>
        <!--[5]--><invoke name="Invoke2" partnerLink="AuthenticationServicePL" operation="endSession" portType="ns2:AuthenticationServiceSoapPort" inputVariable="EndSessionIn" outputVariable="EndSessionOut"/>
        <!--[6]--><assign name="Assign3">
            <copy>
                <from>$StartSessionOut.parameters/ns2:startSessionReturn/ns2:username</from>
                <to variable="InitAuthenticationWSOperationOut" part="username"/>
            </copy>
            <copy>
                <from>$StartSessionOut.parameters/ns2:startSessionReturn/ns2:ticket</from>
                <to variable="InitAuthenticationWSOperationOut" part="ticket"/>
            </copy>
            <copy>
                <from>$StartSessionOut.parameters/ns2:startSessionReturn/ns2:sessionid</from>
                <to variable="InitAuthenticationWSOperationOut" part="sessionId"/>
            </copy>
            
        </assign>
        <!--[7]--><reply name="Reply1" partnerLink="InitAuthenticationPL" operation="InitAuthenticationWSOperation" portType="ns0:InitAuthenticationWSPortType" variable="InitAuthenticationWSOperationOut"/>
    </sequence>
</process>
}}}
/%

!Input/Output

__Code snippet 1.2. InitAuthenticationWS SOAP Request__\\


%%prettify 
{{{
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Body>
        <ns1:startSession
            xmlns:msgns="http://www.alfresco.org/ws/service/authentication/1.0" xmlns:ns1="http://www.alfresco.org/ws/service/authentication/1.0">
            <ns1:username>admin</ns1:username>
            <ns1:password>adminpassword</ns1:password>
        </ns1:startSession>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
}}}
/%

__Code snippet 1.3. InitAuthenticationWS SOAP Response__\\


%%prettify 
{{{
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:Body>
        <startSessionResponse xmlns="http://www.alfresco.org/ws/service/authentication/1.0">
            <startSessionReturn>
                <username>admin</username>
                <ticket>TICKET_39410d7b4d91e85a78f896822f1ff9edd07d10d2</ticket>
                <sessionid>256C5F7B29C64291B5962519D122C485</sessionid>
            </startSessionReturn>
        </startSessionResponse>
    </soapenv:Body>
</soapenv:Envelope>
}}}
/%

!Faults

If an invalid set of credentials is received by Alfresco, then an exception is thrown in the Acegi security system and the following SOAP fault message is returned.\\

__Code snippet 1.4. AuthenticationFault SOAP response __\\
%%prettify 
{{{
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:Body>
        <soapenv:Fault>
            <faultcode>soapenv:Server.generalException</faultcode>
            <faultstring/>
            <detail>
                <ns1:AuthenticationFault xmlns:ns1="http://www.alfresco.org/ws/service/authentication/1.0">
                    <ns1:errorCode>100</ns1:errorCode>
                    <ns1:message>net.sf.acegisecurity.BadCredentialsException: Bad credentials presented
net.sf.acegisecurity.BadCredentialsException: Bad credentials presented
	at net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider.getUserFromBackend(DaoAuthenticationProvider.java:393)
	at net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider.authenticate(DaoAuthenticationProvider.java:225)
	at net.sf.acegisecurity.providers.ProviderManager.doAuthentication(ProviderManager.java:159)
	at net.sf.acegisecurity.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:49)
	at org.alfresco.repo.security.authentication.AuthenticationComponentImpl.authenticateImpl(AuthenticationComponentImpl.java:74)
	at org.alfresco.repo.security.authentication.AbstractAuthenticationComponent.authenticate(AbstractAuthenticationComponent.java:130)
	at org.alfresco.repo.security.authentication.AuthenticationServiceImpl.authenticate(AuthenticationServiceImpl.java:118)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:296)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:177)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:144)
	at net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:80)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)
	at org.alfresco.repo.security.permissions.impl.ExceptionTranslatorMethodInterceptor.invoke(ExceptionTranslatorMethodInterceptor.java:49)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)
	at org.alfresco.repo.audit.AuditComponentImpl.audit(AuditComponentImpl.java:275)
	at org.alfresco.repo.audit.AuditMethodInterceptor.invoke(AuditMethodInterceptor.java:69)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
	at $Proxy24.authenticate(Unknown Source)
	at org.alfresco.repo.webservice.authentication.AuthenticationWebService.startSession(AuthenticationWebService.java:83)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.apache.axis.providers.java.RPCProvider.invokeMethod(RPCProvider.java:397)
	at org.apache.axis.providers.java.RPCProvider.processMessage(RPCProvider.java:186)
	at org.apache.axis.providers.java.JavaProvider.invoke(JavaProvider.java:323)
	at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:32)
	at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118)
	at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83)
	at org.apache.axis.handlers.soap.SOAPService.invoke(SOAPService.java:454)
	at org.apache.axis.server.AxisServer.invoke(AxisServer.java:281)
	at org.apache.axis.transport.http.AxisServlet.doPost(AxisServlet.java:699)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
	at org.apache.axis.transport.http.AxisServletBase.service(AxisServletBase.java:327)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
	at java.lang.Thread.run(Thread.java:619)
</ns1:message>
                </ns1:AuthenticationFault>
                <ns2:exceptionName xmlns:ns2="http://xml.apache.org/axis/">org.alfresco.repo.webservice.authentication.AuthenticationFault</ns2:exceptionName>
                <ns3:stackTrace xmlns:ns3="http://xml.apache.org/axis/">
	at org.alfresco.repo.webservice.authentication.AuthenticationWebService.startSession(AuthenticationWebService.java:96)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.apache.axis.providers.java.RPCProvider.invokeMethod(RPCProvider.java:397)
	at org.apache.axis.providers.java.RPCProvider.processMessage(RPCProvider.java:186)
	at org.apache.axis.providers.java.JavaProvider.invoke(JavaProvider.java:323)
	at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:32)
	at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118)
	at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83)
	at org.apache.axis.handlers.soap.SOAPService.invoke(SOAPService.java:454)
	at org.apache.axis.server.AxisServer.invoke(AxisServer.java:281)
	at org.apache.axis.transport.http.AxisServlet.doPost(AxisServlet.java:699)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
	at org.apache.axis.transport.http.AxisServletBase.service(AxisServletBase.java:327)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
	at java.lang.Thread.run(Thread.java:619)
</ns3:stackTrace>
                <ns4:hostname xmlns:ns4="http://xml.apache.org/axis/">myhost.leeds.ac.uk</ns4:hostname>
            </detail>
        </soapenv:Fault>
    </soapenv:Body>
</soapenv:Envelope>
}}}
/%

\\

Similar to exception handling in Java, it is possible to catch faults in the BPEL process and initiate appropriate faulthandler processes. As a simple example, if we add the following variable to the process above 

\\

__Code snippet 1.5.__ 

%%prettify 
{{{
<variable name="InvalidCredentialsFaultVar" messageType="ns0:InitAuthenticationFault"/>}}}
/%

\\

and add the following faulthandlers element after the variables block

\\

__Code snippet 1.6.__ 

%%prettify 
{{{
<faultHandlers>
        <catchAll>
            <sequence name="Sequence1">
                <assign name="Assign4">
                    <copy>
                        <from>'Authentication Fault of Indeterminate Nature'</from>
                        <to variable="InvalidCredentialsFaultVar" part="faultMessage"/>
                    </copy>
                </assign>
                <reply name="Reply2" partnerLink="InitAuthenticationPL" operation="InitAuthenticationWSOperation" portType="ns0:InitAuthenticationWSPortType" faultName="ns0:invalidCredentialsFault" variable="InvalidCredentialsFaultVar"/>
            </sequence>
        </catchAll>
    </faultHandlers>}}}
/%

\\

then we get the following process diagram

\\

__Figure 1.2 AuthenticationProcess plus catchall fault handler.__\\

[{Image src='amset1authenticationfaulthandler.png' width='662' height='584' align='left'  }]\\

\\

Now in response to receiving an invalid set of credentials the SOAP message received by the client is simply 

\\

__Code snippet 1.7.__ 

%%prettify 
{{{
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.xmlsoap.org/soap/envelope/ http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Body>
    <SOAP-ENV:Fault>
      <faultcode xmlns="">SOAP-ENV:Client</faultcode>
      <faultstring xmlns="">invalidCredentialsFault</faultstring>
      <detail xmlns="">
        <faultMessage>Authentication Fault of Indeterminate Nature</faultMessage>
      </detail>
    </SOAP-ENV:Fault>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>}}}
/%

\\

and the nasty stack trace from the native Alfresco exception is no longer visible.  The fault message code in the InitAuthenticationWS wsdl is 

\\

__Code snippet 1.8.__
 
%%prettify 
{{{
<wsdl>
...
...
<message name="InitAuthenticationFault">
        <part name="faultMessage" type="xsd:string" />
    </message>
    <portType name="InitAuthenticationWSPortType">
        <operation name="InitAuthenticationWSOperation">
            <input name="input1" message="tns:InitAuthenticationWSOperationRequest"/>
            <output name="output1" message="tns:InitAuthenticationWSOperationResponse"/>
            <fault name="invalidCredentialsFault" message="tns:InitAuthenticationFault"/>
        </operation>
    </portType>
    <binding name="InitAuthenticationWSBinding" type="tns:InitAuthenticationWSPortType">
        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="InitAuthenticationWSOperation">
            <soap:operation/>
            <input name="input1">
                <soap:body use="literal" namespace="http://j2ee.netbeans.org/wsdl/Amset2Authentication/InitAuthenticationWS"/>
            </input>
            <output name="output1">
                <soap:body use="literal" namespace="http://j2ee.netbeans.org/wsdl/Amset2Authentication/InitAuthenticationWS"/>
            </output>
            <fault name="invalidCredentialsFault">
                <soap:fault name="invalidCredentialsFault" namespace="http://j2ee.netbeans.org/wsdl/Amset2Authentication/InitAuthenticationWS" use="literal"/>
            </fault>
        </operation>
    </binding>
...
...
</wsdl>
}}}
/%