Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member

Hi folks.
Just recently I had to implement SSO to a tomcat-based JSP application, so that a portal user doesn't have to logon twice. As you all know, SAP's standard technology to implement SSO is the use of a cookie called SAP Logonticket. You may also know, that there are two supported ways to implement SSO to Non-SAP applications, using a native library for ticket verification or using a web server filter. (help.sap.com )

I decided to use the library SAPSSOEXT. On my search for documentation, I found out, that the guide I knew from SDN disappeared and the rest of the official documentation is,.. uh, let's say a bit rudimental.


So, here is a brief instruction from my side, maybe some of you will need it as well.

1. Get the required dynamic link libraries.

Go to http://service.sap.com/patches -> Entry by Application Group -> Additional Components
Get the versions of SAPSECULIB and com.mysap.sso.SSO2Ticket

package com.mysap.sso;

import java.util.ArrayList;

import java.util.List;

import javax.servlet.http.Cookie;

import javax.servlet.http.HttpServletRequest;

public class SSO2Ticket {

     public static final int ISSUER_CERT_SUBJECT = 0;

     public static final int ISSUER_CERT_ISSUER = 1;

     public static final int ISSUER_CERT_SERIALNO = 2;

     private static boolean initialized = false;

     public static String SECLIBRARY;

     public static String SSO2TICKETLIBRARY = "sapssoext";

     

     private static List pseudoACL;

     static {

          pseudoACL = new ArrayList();

          pseudoACL.add("EP7|000|OU=J2EE, CN=S1D|OU=J2EE, CN=EP7|00");

          

          if (System.getProperty("os.name").startsWith("Win")) {

               SECLIBRARY = "sapsecu.dll";

          } else {

               SECLIBRARY = "libsapsecu.so";

          }

          try {

               System.loadLibrary(SSO2TICKETLIBRARY);

               System.out.println("SAPSSOEXT loaded.");

          } catch (Throwable e) {

               System.out.println("Error during initialization of SSO2TICKET:\n"+ e.getMessage());

          }

     }

     /**

     

  • Initialization

     

     

  • @param seclib location of ssf-implemenation

     

     

  • @return true/false whether initailisation was ok

      */

     protected static native synchronized boolean init(String seclib);

     /**

     

  • Returns internal version.

     

     

  • @return version

      */

     public static native synchronized String getVersion();

     /**

     

  • eval ticket

     

     

  • @param ticket        the ticket

     

  • @param pab           location of pab

     

  • @param pab_password  password for access the pab

     

     

  • @return Object array with:

     

  •         = (String)user, = (String)sysid, = (String)client , = (byte[])certificate

     

  •         = (String)portalUser, = (String)authSchema, = validity

     

      */

     public static native synchronized Object[] evalLogonTicket(String ticket,String pab,String pab_password) throws Exception;

     /**

     

  • Parse certificate

     

  • @param cert                Certificate received from evalLogonTicket

     

  • @param info_id       One of the requst id´s

     

     

  • @return Info string from certificate

     

      */

     public static native synchronized String parseCertificate(byte[] cert,int info_id);

     

     /**

     

  • @param request          HttpServletRequest

     

  • @param pathToPSE          Path to PSE

     

  • @return String array with:

     

  •                                SAP system user

     

  •                                Id of the issuing system

     

  •                                Client of the issuing system

     

  •                                Portal user

     

  •                                Authscheme

     

  •                                Validity in seconds

     

  •                                Subject

     

  •                                Issuer

     

  •                                Serial number

     

  • @throws LogonTicketException

      */

     public static synchronized String[] verify(HttpServletRequest request, String pathToPSE) throws LogonTicketException

     {

          String[] ticketContent = null;

          if(!initialized) {

               init("sapsecu.dll");

               initialized = true;

          }

          String ticket = null;

          Cookie[] all_Cookies = request.getCookies();

          int i = 0;

          int j = 0;

          if (all_Cookies != null) j = all_Cookies.length;

          for (i = 0; i < j; i++) {

               //Get MYSAPSSO2 cookie from request context...

               if ("MYSAPSSO2".equals(all_Cookies[i].getName())) {

                    ticket = all_Cookies[i].getValue();

                    break;

               }

          }

          if(ticket==null) throw new LogonTicketException(LogonTicketException.NO_TICKET_FOUND); // mysapsso2 cookie not found

          Object[] o = null;

          try {

               o = SSO2Ticket.evalLogonTicket(ticket, pathToPSE, null);

               byte[] cert_ = (byte[]) o[3];

               ticketContent = new String[9];               

               ticketContent[0] = (String)o[0]; //First element is the SAP system user

               ticketContent[1] = (String)o[1]; //Second element is the id of the issuing system

               ticketContent[2] = (String)o[2]; //Third element is the client of the issuing system

               ticketContent[3] = (String)o[4]; //Portal user

               ticketContent[4] = (String)o[5]; //Authscheme

               ticketContent[5] = (String)o[6]; //Validity in seconds

               ticketContent[6] = SSO2Ticket.parseCertificate(cert_, SSO2Ticket.ISSUER_CERT_SUBJECT);

               ticketContent[7] = SSO2Ticket.parseCertificate(cert_, SSO2Ticket.ISSUER_CERT_ISSUER);

               ticketContent[8] = SSO2Ticket.parseCertificate(cert_, SSO2Ticket.ISSUER_CERT_SERIALNO);

               

               String aclStr = ticketContent[1]"|"ticketContent[2]"|"ticketContent[6]"|"ticketContent[7]"|"ticketContent[8];

               if(!pseudoACL.contains(aclStr)) throw new LogonTicketException(LogonTicketException.TICKET_ISSUER_NOT_TRUSTED);

          } catch (Exception e) {

               LogonTicketException ex = new LogonTicketException(LogonTicketException.TICKET_VERIFICATION_FAILED);

               ex.initCause(e);

               throw ex;

          }

          return ticketContent;

     }

}

>

com.mysap.sso.LogonTicketException

package com.mysap.sso;

/**

  • @author Karsten Geiseler

*/

public class LogonTicketException extends Exception {

public static final String NO_TICKET_FOUND = "No ticket found";

public static final String TICKET_VERIFICATION_FAILED = "Ticket verification failed";

public static final String TICKET_ISSUER_NOT_TRUSTED = "Ticket Issuer not trusted";

     public LogonTicketException() {

          super();

     }

     public LogonTicketException(String message) {

          super(message);

     }

     public LogonTicketException(Throwable cause) {

          super(cause);

     }

     public LogonTicketException(String message, Throwable cause) {

          super(message, cause);

     }

}

Now modify the SSO2Ticket class according to your needs.
I demonstrated a simple access control list to list trusted ticket issuers. Add your trusted issuers there or implement a more sophisticated solution.
Feel free to add your own logging implementation.
Do not move the classes to a different package!

4. Get your issuing portal's certificate in a pse file

Log on to your portal, go to System Administration -> System Configuration -> Keystore Administration and download the verify.pse file.

On your non-SAP system, put the file somewhere on the filesystem. The path to the file is an input variable for SSO2Ticket.verify(HttpServletRequest request, String pathToPSE). In my example the path will be C:
tmp
verify.pse
If you want to verify tickets of more than one issuing system, you have to store the X.509 certificates of each issuing system in a pse file. How this can be accomplished is described in SAP Note 722072.


5. Now you can call SSO2Ticket.verify(HttpServletRequest request, String pathToPSE)

Here is a jsp sniplet to show the usage of the classes:

               <%

          try

          {

               String[] ticketContent = com.mysap.sso.SSO2Ticket.verify(request,"C:
tmp
SAPSSOEXT
NTintel
ssosample
java
verify.pse");

               %>

               <%=ticketContent[0]%><br>
               <%=ticketContent[1]%><br>
               <%=ticketContent[2]%><br>
               <%=ticketContent[3]%><br>
               <%=ticketContent[4]%><br>
               <%=ticketContent[5]%><br>
               <%=ticketContent[6]%><br>
               <%=ticketContent[7]%><br>
               <%=ticketContent[8]%><br>
               <%
          } catch (com.mysap.sso.LogonTicketException e)
          { %>
               <%=e.getMessage()%>
          <% } %>

</textarea> <p>That's it. The verify method returns the ticket content as a String array, the portal's userId is ticketContent[3].</p><p>Cheers, Karsten</p>

13 Comments
Labels in this area