Zimbra SOAP connection for AuthToken using WSDL

Have a great idea for extending Zimbra? Share ideas, ask questions, contribute, and get feedback.
SteliosPh
Posts: 1
Joined: Tue Apr 16, 2019 9:19 am

Zimbra SOAP connection for AuthToken using WSDL

Postby SteliosPh » Tue Apr 16, 2019 9:43 am

Hello,

I am currently trying to get the SOAP code to work.

I have downloaded the ZimbraUserService.wsdl and all the related xsd files.
From there i have automatically generated the java code using the apache-cxf-3.3.1 wsdl2java.

After stumbling a bit i wrote a custom AuthRequest to make sure that everything is working correcty

Code: Select all

package com.somewhere.swing.calendar;

import java.net.URL;

import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;

public class soap {

   private static String zimbra_user = "user";
   private static String zimbra_password = "passsssword;

   public static void main(String args[]) {
      connectWithRawSoap();
   }

   private static void connectWithRawSoap() {
      String soapEndpointUrl = "http://my-urlservice/soap";
      String soapAction = "http://my-url:443/service/soap/AuthRequest";

      callSoapWebService(soapEndpointUrl, soapAction);
   }

   private static void callSoapWebService(String soapEndpointUrl, String soapAction) {
      try {
         // Create SOAP Connection
         SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
         SOAPConnection soapConnection = soapConnectionFactory.createConnection();

         // Send SOAP Message to SOAP Server
         URL url = new URL(soapEndpointUrl);

         SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(soapAction), url);

         // Print the SOAP Response
         System.out.println("Response SOAP Message:");
         soapResponse.writeTo(System.out);
         System.out.println();

         soapConnection.close();
      } catch (Exception e) {
         System.err.println(
               "\nError occurred while sending SOAP Request to Server!\nMake sure you have the correct endpoint URL and SOAPAction!\n");
         e.printStackTrace();
      }
   }

   private static SOAPMessage createSOAPRequest(String soapAction) throws Exception {
      MessageFactory messageFactory = MessageFactory.newInstance();
      SOAPMessage soapMessage = messageFactory.createMessage();

      createSoapEnvelope(soapMessage);

      MimeHeaders headers = soapMessage.getMimeHeaders();
      headers.addHeader("SOAPAction", soapAction);

      soapMessage.saveChanges();

      /* Print the request message, just for debugging purposes */
      System.out.println("Request SOAP Message:");
      soapMessage.writeTo(System.out);
      System.out.println("\n");

      return soapMessage;
   }

   private static void createSoapEnvelope(SOAPMessage soapMessage) throws SOAPException {
      SOAPPart soapPart = soapMessage.getSOAPPart();

      // SOAP Envelope
      SOAPEnvelope envelope = soapPart.getEnvelope();
      Name context = envelope.createName("context", null, "urn:zimbra");
      Name xml = envelope.createName("format", "type", "xml");
      //context.

      Name authRequest = envelope.createName("AuthRequest", null, "urn:zimbraAccount");
      Name account = envelope.createName("account");
      Name password = envelope.createName("password");

      // SOAP Body
      SOAPHeader header = envelope.getHeader();
      //      header.addChildElement(context).addChildElement(xml);

      SOAPBody soapBody = envelope.getBody();
      SOAPBodyElement auth_body = soapBody.addBodyElement(authRequest);
      auth_body.addChildElement(account).addAttribute(envelope.createName("by"), "name").addTextNode(zimbra_user);
      auth_body.addChildElement(password).addTextNode(zimbra_password);
   }

}


This has validated that the connection works as expected.

Then i have started working on the wsdl code in order to get that to work.
After a few issues i.e Fixing the PKIX path in order to register the cacert, finding the correct code to send the SOAP command.

I have managed to come up with the following code correctly sends an authentication command and receives the AuthResp

Code: Select all

package com.something.calendar;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.PortInfo;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

import com.zimbra.wsdl.zimbraservice_wsdl.ZcsPortType;
import com.zimbra.wsdl.zimbraservice_wsdl.ZcsService;

import zimbra.AccountBy;
import zimbra.AccountSelector;
import zimbra.AuthTokenControl;
import zimbra.HeaderContext;
import zimbraaccount.AuthRequest;
import zimbraaccount.AuthResponse;
import zimbraaccount.AuthToken;
import zimbraaccount.GetAccountInfoRequest;
import zimbraaccount.GetAccountInfoResponse;
import zimbraaccount.ObjectFactory;

public class SoapTest {

   private static String zimbra_user = "user;
   private static String zimbra_password = "pass";

   static class HeaderHandlerResolver implements HandlerResolver {

      @Override
      public List<Handler> getHandlerChain(PortInfo portInfo) {
         List<Handler> handlerChain = new ArrayList<Handler>();
         HandlerHeader hh = new HandlerHeader();
         handlerChain.add(hh);
         return handlerChain;
      }
   }

   static class HandlerHeader implements SOAPHandler<SOAPMessageContext> {

      @Override
      public Set<QName> getHeaders() {
         return Collections.emptySet();
      }

      @Override
      public boolean handleMessage(SOAPMessageContext context) {
         Boolean outboundProperty = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
         if (outboundProperty.booleanValue()) {
            try {
               System.out.println("\nOutbound message:");
               System.out.println("******************");
               context.getMessage().writeTo(System.out);
               System.out.println("\n******************");
            } catch (SOAPException e) {
               e.printStackTrace();
            } catch (IOException e) {
               e.printStackTrace();
            }

         } else {
            try {
               System.out.println("\nInbound message:");
               SOAPMessage message = context.getMessage();
               System.out.println("\n******************");
               message.writeTo(System.out);
               System.out.println("\n******************");
            } catch (SOAPException e) {
               // TODO Auto-generated catch block
               e.printStackTrace();
            } catch (IOException e) {
               // TODO Auto-generated catch block
               e.printStackTrace();
            }
         }

         return true;
      }

      @Override
      public boolean handleFault(SOAPMessageContext context) {
         try {
            SOAPMessage message = context.getMessage();
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            message.writeTo(out);
            String strMsg = new String(out.toByteArray());
            System.err.println("FAULT:");
            System.err.println(strMsg);
         } catch (SOAPException | IOException ex) {
            ex.printStackTrace();
         }
         return true;
      }

      @Override
      public void close(MessageContext context) {
      }

   }

   public static void main(String args[]) {
      connectAndAuthenticate();
   }

   private static void connectAndAuthenticate() {
      ObjectFactory zimbraAccountFactory = new ObjectFactory();
      AuthRequest authRequest = zimbraAccountFactory.createAuthRequest();

      AccountSelector accountSelector = new AccountSelector();
      accountSelector.setBy(AccountBy.NAME);
      accountSelector.setValue(zimbra_user);

      authRequest.setAccount(accountSelector);
      authRequest.setPassword(zimbra_password);

      ZcsService service = new ZcsService();
      HeaderHandlerResolver handlerResolver = new HeaderHandlerResolver();
      service.setHandlerResolver(handlerResolver);

      ZcsPortType port = service.getZcsServicePort();

      AuthResponse response = port.authRequest(authRequest);
      JAXBElement<AuthResponse> response2 = zimbraAccountFactory.createAuthResponse(response);

      AuthToken token = zimbraAccountFactory.createAuthToken();
      String resp = response2.getValue().getAuthToken();
      long lifeTime = response2.getValue().getLifetime();
      token.setValue(resp);
      token.setLifetime(lifeTime);
      authRequest.setAuthToken(token);

      zimbra.ObjectFactory zimbraFactory = new zimbra.ObjectFactory();

      HeaderContext c = zimbraFactory.createHeaderContext();
      c.setAuthToken(resp);
      AuthTokenControl tokenControl = zimbraFactory.createAuthTokenControl();
      tokenControl.setVoidOnExpired(true);
      c.setAuthTokenControl(tokenControl);

      GetAccountInfoRequest infoRequest = zimbraAccountFactory.createGetAccountInfoRequest();
      infoRequest.setAccount(accountSelector);
      GetAccountInfoResponse getAccountInfoRequest = port.getAccountInfoRequest(infoRequest);

      zimbraAccountFactory.createGetAccountInfoResponse();
   }
}



I have been trying for hours how to send the AuthRespond on to the next Request in order to get the response but what ever i have tried it did not work.
I cant seem to add the authtoken in my commands.

Exception in thread "main" com.sun.xml.internal.ws.fault.ServerSOAPFaultException: Client received SOAP Fault from server: no valid authtoken present Please see the server log to find more detail regarding exact cause of the failure.


Does anyone have any ideas how i can proceed from here and add the AuthResponse into the next commands ?
I have tried to use the following code
[url]https://forums.zimbra.org/viewtopic.php?t=732
[/url]
But unfortunately the code there is old, and not entirely clear what needs to be done.


User avatar
rcardozo1987
Posts: 23
Joined: Tue Sep 10, 2019 9:14 pm
ZCS/ZD Version: NETWORK edition, Patch 8.8.15_P11

Re: Zimbra SOAP connection for AuthToken using WSDL

Postby rcardozo1987 » Thu Sep 19, 2019 1:44 am

Hello @SteliosPh, maybe I can help you.

I did something similar, but using PHP SoapClient object. Is it usefull for you?

Regards
viduc
Posts: 1
Joined: Wed Jan 06, 2021 2:48 pm

Re: Zimbra SOAP connection for AuthToken using WSDL

Postby viduc » Wed Jan 06, 2021 2:50 pm

Hi!

did someone find solution? i have the same probleme with soapclient in php. I try few solution but i always have message:

Code: Select all

SoapFault : no valid authtoken present
panimozhi
Posts: 2
Joined: Mon Dec 14, 2020 1:17 pm

Re: Zimbra SOAP connection for AuthToken using WSDL

Postby panimozhi » Mon Jan 11, 2021 10:50 am

Anybody found solution for no valid Auth token problem
User avatar
barrydegraaff
Zimbra Employee
Zimbra Employee
Posts: 102
Joined: Tue Jun 17, 2014 3:31 am
Contact:

Re: Zimbra SOAP connection for AuthToken using WSDL

Postby barrydegraaff » Mon Feb 01, 2021 7:19 am

This one works, used it a couple months back:

https://github.com/zimbra-api/zimbra-api

Also to debug you should send us all the headers you are sending in the requests does does not work. Most likely you are not sending the correct authentication. Try and debug using curl.
--
Barry de Graaff
Admin of Zimbra-Community Github: https://github.com/orgs/Zimbra-Community/
Developer of Zimbra OpenPGP Zimlet, Zimbra ownCloud Zimlet and more.
A Zetalliance Founder http://www.zetalliance.org/

Return to “Developers”

Who is online

Users browsing this forum: No registered users and 4 guests