Skip to Content

Principal Propagation in SAP XI


When sending messages via SAP XI, technical users have to separately authenticate themselves at each involved component (Sender, AE, IS, Receiver), i.e. on each component you might have a different user. On the receiver side, for each user a separate communication channel has to be created where the user’s credentials are stored. Assuming, that you have to call the receiver system using different users in order to restrict their authority. Depending on the number of users, this could lead to huge maintenance effort.

On the other hand, Principal Propagation allows to propagate a user along the whole message flow, from sender to receiver. For each messaging component, an authentication has to be carried out, but the user keeps unchanged. The user context is passed to the next component by using an SAP assertion ticket. In this case, for the above mentioned scenario only one communication channel is necessary.

SAP assertion ticket is similar to SAP logon ticket. The sending system issues a ticket containing the server’s digital signature. The receiving system verifies the digital signature, checks if the ticket has been issued by a trusted server (i.e. a server that is listed in its ACL), and checks the ticket’s expiration time. In contrast to an SAP logon ticket, SAP assertion tickets are solely used for system to system connection, could only be used once (i.e. are deleted after verified), and have a very short validity period in the range of a few seconds.

Principal Propagation is available as of SAP XI3.0 SPS19 and SAP NetWeaver ’04s SPS10. It is supported for the following adapters: XI (for both ABAP and Java proxies), RFC, and SOAP.


The following scenario is considered: Sender and Receiver both communicate with SAP XI via RFC, communication within SAP XI is done by http. The different components act either as client or server, depending on the connection. The sender issues a ticket when calling SAP XI acting as client, whereas the Adapter Engine verifies the ticket, so acting as server. Each time a ticket is verified, it is deleted, hence a new ticket has to be created when posting the message to the next component. For each connection, a trust relationship has to be established. Since the RFC adapter resides on the Adapter Engine, 4 different connections have to be configured, see figure below.


Configuration Steps

Enable Principal Propagation on Integration Server

  • Call TX SXMB_ADM (Integration Engine – Administration), and run Configure Principal Propagation to activate principal propagation on the Integration Server. This will create a service user XIPPUSER, and an RFC destination SAPXIPP<Client No>. In case you get a warning that the user has no roles assigned, call TX SU01 and manually assign role SAP_XI_APPL_SERV_USER to the same.



  • The propagated users have to exist on the Integration Server with the same name as in the sender and receiver system, however passwords could differ. Call TX SU01 to maintain users to be propagated. Assign role SAP_XI_APPL_SERV_USER to the same.


Sender to Adapter Engine (connection 1)

  • ABAP Client (Sender)   
    • The assertion ticket has to be signed with the Sender’s digital signature. So, a private key, and a corresponding public key certificate have to be created. Call TX STRUST to maintain a system PSE, and export the certificate.


    • In order to issue tickets, change profile parameter login/create_sso2_ticket to either 1 (in case the certificate is signed by a CA) or 2 (in case the certificate is self-signed).


    • Call TX SM59 to create an RFC destination of type T pointing to the XI server. Switch to tab Logon & Security, and select check box Send SAP Logon Ticket in order to issue a ticket.


  • Java Server (AE)  
    • In order to verify the assertion ticket of the sender, import its public-key certificate into the J2EE Engine’s keystore view. In Visual Administrator, go to the Key Storage service, choose the TicketKeystore view, and load the beforehand exported server certificate.


    • When accessing the J2EE Engine, several login modules are carried out to authenticate a user. For assertion tickets, the EvaluateAssertionTicketLoginModule is processed. Maintain the ACL for module EvaluateAssertionTicketLoginModule, i.e. maintain list of accepted systems. In Visual Administrator, go to the Security Provider service, switch to tabs Runtime → User Management, and choose Manage User Stores → EvaluateAssertionTicketLoginModule → View/Change Properties.


      Maintain properties as follows:

      • trustedsys<n> = System ID and Client of Sender (syntax: “<SID>, <Client>“).
      • trusteddn<n> = Distinguished name of Sender system according to its server certificate.
      • trustediss<n> = Distinguished name of issuer according to Sender’s server certificate.
      • = true. This indicates that configuration of logon tickets is done in the UME property sheet.      


Adapter Engine to Integration Server (connection 2)

  • Java Client (AE)
    • To issue an assertion ticket, the module CreateAssertionTicketLoginModule has to be processed. In Visual Administrator, go to the Security Provider service, switch to tabs Runtime → User Management, choose Manage User Stores → CreateAssertionTicketLoginModule → View/Change Properties, and set parameter = true.


    • For SAP systems, system and client are included in the user’s assertion ticket. This information is required when comparing with the server’s ACL. The J2EE Engine does not have a client. However, to ensure that the issuing system is unique, a client has to be provided. For an add-in installation where the system IDs of both stacks are identical, the default client for the J2EE Engine has to be changed. In Visual Administrator, go to the Configuration Adapter service, and choose cluster_data → server → cfg → services. Change following parameters of property sheet


      • login.ticket_client = <unique client>.
      • login.ticket_keyalias = SAPLogonTicketKeypair.
      • login.ticket_keystore = TicketKeystore.
    • To sign the assertion ticket, a private/public key pair has to be created. In Visual Administrator, go to the Key Storage service, choose the TicketKeystore view, and create a private/public key pair. Set the distinguished name as system ID of the J2EE Engine. Export the public key certificate.


  • ABAP Server (IS)
    • In order to accept tickets, change profile parameter login/accept_sso2_ticket to 1.


    • In order to verify the assertion ticket of the J2EE Engine, import its public-key certificate into the Integration Server. Call TX STRUST, import the certificate, and add it to the System PSE’s certificate list.


    • Maintain the Integration Server’s ACL. Call TX STRUSTSSO2, and add the J2EE Engine’s certificate to the ACL. Specify the J2EE Engine’s system ID and client.


Integration Server to Adapter Engine (connection 3)

  • ABAP Client (IS)
    • Maintain the Integration Server’s system PSE, and export the certificate.         
    • Change profile parameter login/create_sso2_ticket, see above.
  • Java Server (AE)   
    • Import the Integration Server’s public-key certificate into the J2EE Engine’s keystore view.
    • Add the Integration Server into the J2EE Engine’s ACL for module EvaluateAssertionTicketLoginModule.

Adapter Engine to Receiver (connection 4)

  • Java Client (AE) 
    • Modify module CreateAssertionTicketLoginModule, already done.
    • Change client for the J2EE Engine, already done.
    • Create private/public key pair, already done.
  • ABAP Server (Receiver)
    • Change profile parameter login/accept_sso2_ticket, see above.
    • Import the J2EE Engine’s public-key certificate into the Receiver system’s PSE.
    • Add the J2EE Engine into the Receiver system’s ACL.

Integration Directory

In the sender and receiver agreement, select checkbox Propagate Principal to propagate user credentials.



Further Information

For more details about the functionality and configuration of Principal Propagation, please refer to  SAP Help Portal, and SAP Note 974873.

You must be Logged on to comment or reply to a post.
  • Its an excellent presentation of step by step. But i have some questions , in the sceanario you have considered RFC–RFC , In connection (1)is ABAP client u r referring, is the same XI system itself or the R/3 system which is sending the data ?

    Also how will this scenario change if a message sent from a soap client so initial connection (1) is soap instead of RFC. Plz advice.

    • Hi Bujji,

      in connection 1 the ABAP client is the backend system
      a mixed scenario like soap-rfc is possible as well, for details about which configuration steps you have to undertake please check the online help, see link below, however configuration is pretty much the same


  • I have one doubt regarding its Advantages.
    Q1. How is it different from simple RFC to RFC scenario ?
    Considering that same communication channel can be used in many interfaces by different users.

    Q2.If we have activated the PP in all components then why we need to mention user credentials again in receiver channel? It should pick up the source user credentials dynamically by the configuration of PP.

    Please clarify these queries.

    Please clarify .

    • Hi Anurag,

      wrt Q1, you are right, the same comm channel can be used within different scenarios, but w/o PP it’s always the same static user, i.e. the one that is maintained in the channel, that logs on to the receiver system. A use case could be here that you would like to check authority in the receiver system against the user in the sender system. W/o PP for each user you would have to maintain a channel, w/ PP you only need one channel, the user credentials are passed from sender to receiver via XI.
      wrt Q2, although we log on to the receiver system using the propagated user’s credentials, we still have to maintain a user in the channel. I’m not sure why this is the case. Maybe this user logs on and then changes the user context. Anyway, I traced the rfc call, and was able to verify that the rfc was carried out under the propagated user.

  • Hi Alex,

    We have done all the settings as per your blog. When we do not check Principal Propagation in Receiver agreement, we dont get any error, and we find that in SXMB_MONI the XIAFUSER is replaced by the Propagated user. But when we check Principal Propagtion in Receiver agreement, we get the HTTP error mentioned above. From this, we undertsand that our user is propagated till Integration server and that IS is not able to create its assertion ticket. We have set the parameter login/create_sso2_ticket to 2(self signed). Please help us to solve this problem.

    Thanks and regards,

    • Hi Sreehari,

      I would rather assume that the trusted relationship between PI and the receiver has not been set up correctly, and hence the ticket was rejected. Please check again if the trusted relationship is established, otherwise if you can’t solve it on your own raise a customer message.


  • we want to use PP within ccBPM-processes. In which way can we implement this, as we understand this is not yet possible in SAP NW 7.0/7.1.
    • Hi Erik,

      this is only supported in 7.1 regardless of the approach (logon ticket for SOAP, RFC, XI / SAML for WS-RM).
      However, limitation is that integration process must not contain any collerations.


  • Hi,
    Nice blog. How the sender system User ID and Password is being carried forward in this scenario? Lets say if the PP users have different passwords in the systems with same user ids, how the sending system would log on to the receiving system with a different password? Where do we mention this in the development?


    • Hi VJ,

      password is not part of the assertion ticket and hence can be different in different systems, only the user name is propagated. Authentication is based on the trusted relationship, i.e., the signature.


  • Hi Alex,

    thanks for your nice blog. I have questions about Principal Propagation – SOAP Sender Configuration (quotes are from

    “The SOAP client itself must be able to issue SAP assertion tickets.”

    Can this be implemented in non-SAP-systems? I couldn’t find any libaries like sapssoext (to verify SAP tickets) which can be used to create SAP assertion tickets. So do I need to use SAML and WS for principal propagation with non-SAP senders?

    “If the sender is a SOAP (receiver) adapter, simple principal propagation can be used.”

    What does simple principal propagation mean?


    • Hi Markus,

      yes, it can be implemented in non-SAP systems although I have to admit that I haven’t done this so far. As far as I know, the library sapssoext is the right one, you can use SAP logon tickets.
      Regarding the second quote, I never heard about this term, I guess it’s rather a translation issue. What the author obviously tries to say is that you simply have to configure principal propagation in the soap receiver adapter.


      • Hi Alex,

        I did some more research and downloaded sapssoext to read documentation. It is really only able to verify a ticket and not to create one. There has already been some discussion on this topic in this thread:

        Re: SSO Ticket content specification

        So it seems only possibility to use principal propagation with non-SAP senders is to use SAML.


        • Hi Markus,

          I’ve just double checked with development. You are right, there is no library for creating tickets, so the only way to send a ticket is indeed SAML.

  • Hi,

    Great blog!!!. It helped me a lot in configuring principal propagation.

    I do have a question on whether the users have exist in PI for this ? I do understand from your blog and other help documentation that the user has to exist in PI system as well with SAP_XI_APPL_SERV_USER role. But isnt it an additional overhead of maintaining so many users in PI, especially when they are business users and have no idea about PI. Other problem is we are using CUA for user maintenance, so if my user is a dialog user in ECC, I cannot create it as system in just PI, as it is a global config in CUA.

    Well long story short..Is there a way that my sender system authenticate to PI using a common ID, but passed the SAP Logon ticket in SOAP Header for the user and this ticket is used to authenticate against Receiver system (Thus eliminating the need to maintain all users in PI)

    • Hi Yomesh,

      unfortunately, there is no way to avoid creating all propagated users in PI. The assertion ticket that is created at the PI outbound uses the credentials of the user that is processing the message. This is how PP is implemented.


  • Alex,

    This is a Great Blog!!  I know managing mass users in XI/PI is a gigantic task. is there any way to avoid it?

    We had PP set up between SRM and ECC system. It works fine when there is no approval WF in SRM and doc creator’s name carried over from SRM till the ECC PO. But when approval WF triggers in SRM, WF-BATCH user name gets propagated and show up in ECC PO. This is strange, we do not understand why it happens. Can you throw some light on this one?


  • Hi Alexander,

       Very Nice Blog, But the images that you had attached to this blog are now no more visible may be because of new SDN outlook.

    Request you to kindly update it as it will of great help to me.




    Hi Alex,

    In most scenarios you want todo principal propagation without having the users in SAP PO/PI/XI.

    Sender -> (adapter) SAP PO (soap adapter XI3.0 protocol) -> SAP ABAP backend

    You rather want the sender system to send the useraccount to be used in the backend in the message-payload or in a http header for example.

    You must have a trust between the sender and sap po.


    When calling the ABAP backend the assertion ticket must be placed in the http header MYSAPSSO2. This is done using ASMA for the http_aae and SOAP XI3.0 adapter.

    You can create an assertion ticke in a sap po/pi mapping with this code

    It’s not recommended as this approach as it uses API:s that are internal to SAP. This code can’t be put in an adapter module as the depenedencies aren’t allowed. Unfortunate.


    String keyStoreAlias = "TicketKeystore";
    String keyStoreEntry = "SAPLogonTicketKeypair";
    ISsfProfile profile = getSsfProfileKeyStore(keyStoreAlias, keyStoreEntry);
    String ticket = createAssertionTicket(senderSID, senderClient, senderUser, profile.getPrivateKey(), profile.getCertificate(), recipientSID,recipientClient, recipientMappedUser);
    in.getDynamicConfiguration().put(dckTicket, ticket);
    // to create the http header MYSAPSSO2
    ISsfProfile getSsfProfileKeyStore(String keyStoreAlias, String keyStoreEntry) throws StreamTransformationException {
    		KeyStoreManager managerPriviliged = null;
    		try {
    			//String[] protection_domain = new String[1];
    			//protection_domain[0] = "";
    			managerPriviliged =;
    		} catch (KeyStoreException e) {
    			throw new StreamTransformationException("SAPSecurityResources", e);
    		KeyStore keyStore;
    		try {
    			traceAddDebug("managerPriviliged.getKeyStore(keyStoreAlias) " + keyStoreAlias);
    			keyStore = managerPriviliged.getKeyStore(keyStoreAlias);
    			traceAddDebug("managerPriviliged.getKeyStore(keyStoreAlias) " + keyStoreAlias + " fetched");
    		} catch (KeyStoreException e) {
    			throw new StreamTransformationException("managerPriviliged.getKeyStore " + keyStoreAlias, e);
    		ISsfProfile profile = null;
    		try {
    			traceAddDebug("new SsfProfileKeyStore " + keyStoreAlias + " " + keyStoreEntry);
    			profile = managerPriviliged.getISsfProfile(keyStore, keyStoreEntry, null);
    		} catch (KeyStoreException e) {
    			throw new StreamTransformationException("Failed to load SsfProfileKeyStore " + keyStoreAlias + " " + keyStoreEntry, e);
    		traceAddDebug("returning profile " + keyStoreAlias + " " + keyStoreEntry);
    		return profile;
    	String createAssertionTicket(String system, String client, String user, PrivateKey key, X509Certificate cert, String recipientSID, String recipientClient,
    			String mappeduser) throws StreamTransformationException {
    		Object recipientClientInfoUnit;
    		String strValid = null;
    		String strValidMin = null;
    		SAPAuthenticationAssertionTicket sapAssertionTicket = new SAPAuthenticationAssertionTicket();
    		traceAddDebug("SAPAuthenticationAssertionTicket instantiated ");
    		iaik.x509.X509Certificate iaikCert = (iaik.x509.X509Certificate) cert;
    		traceAddDebug("iaikCert typecasted X509Certificate");
    		sapAssertionTicket.setPrivateKeyPair(key, iaikCert);
    		traceAddDebug("KeyPair set ");
    		traceAddDebug("mode set to 1 ");
    		if (user != null) {
    			InfoUnit iuUserID;
    			String iUser = "portal:" + user;
    			try {
    				traceAddDebug("setting iuUserID " + iUser);
    				iuUserID = new InfoUnit(32, InfoUnit.jcharToUTF8((String) (iUser)));
    				traceAddDebug("iuUserID set");
    			} catch (UnsupportedEncodingException e) {
    				throw new StreamTransformationException("UnsupportedEncodingException iUser " + iUser, e);
    			} catch (IOException e) {
    				throw new StreamTransformationException("IOException iUser " + iUser, e);
    			try {
    				traceAddDebug("sapAssertionTicket.addInfoUnit(iuUserID) done ");
    			} catch (TicketException e) {
    				throw new StreamTransformationException("TicketException " + iUser, e);
    		} else {
    			traceAddDebug("user == null");
    			throw new StreamTransformationException("user == null");
    		Object object = null; 
    		InfoUnit iuAuthscheme = null;
    		String authSceheme = null;
    		try {
    			traceAddDebug("before iuAuthscheme");
    			// authentication methods "headervariable" "basicauthentication"
    			authSceheme = (String) (object == null ? "default" : (String) object);
    			traceAddDebug("authscheme " + authSceheme);
    			iuAuthscheme = new InfoUnit(136, InfoUnit.jcharToUTF8((String) (object == null ? "default" : (String) object)));
    			traceAddDebug("after iuAuthscheme");
    		} catch (UnsupportedEncodingException e) {
    			throw new StreamTransformationException("UnsupportedEncodingException iuAuthscheme", e);
    		} catch (IOException e) {
    			throw new StreamTransformationException("IOException iuAuthscheme", e);
    		try {
    			traceAddDebug("before sapAssertionTicket.addInfoUnit(iuAuthscheme);");
    		} catch (TicketException e) {
    			throw new StreamTransformationException("TicketException sapAssertionTicket.addInfoUnit authScheme" + authSceheme, e);
    		traceAddDebug("recipientSID " + recipientSID);
    		if (recipientSID != null) {
    			Object object1 = recipientSID;
    			try {
    				InfoUnit recipientSIDInfoUnit = new InfoUnit(16, InfoUnit.jcharToUTF8((String) ((String) object1)));
    			} catch (Exception e) {
    				throw new StreamTransformationException("Exception recipientSID " + recipientSID, e);
    		traceAddDebug("recipientClient " + recipientClient);
    		if (recipientClient != null) {
    			Object object1 = recipientClient;
    			try {
    				recipientClientInfoUnit = new InfoUnit(15, InfoUnit.jcharToUTF8((String) ((String) object1)));
    				sapAssertionTicket.addInfoUnit((InfoUnit) recipientClientInfoUnit);
    			} catch (Exception e) {
    				throw new StreamTransformationException("Exception recipientClient " + recipientClient, e);
    		if (mappeduser != null) {
    			traceAddDebug("mappeduser " + mappeduser);
    			try {
    			} catch (TicketException e) {
    				throw new StreamTransformationException("TicketException mappeduser " + mappeduser, e);
    		} else {
    			throw new StreamTransformationException("mappeduser == null");
    		traceAddDebug("SystemClient " + client);
    		try {
    		} catch (TicketException e) {
    			throw new StreamTransformationException("TicketException client " + client, e);
    		traceAddDebug("SystemID " + system);
    		try {
    		} catch (TicketException e) {
    			throw new StreamTransformationException("TicketException system " + system, e);
    		// Is inclcert needed?
    		// if (ticketProps.get("inclcert") != null) {
    		// sapAssertionTicket.setIncludeOwnCert(((String)ticketProps.get("inclcert")).equals("1"));
    		// }
    		// strValid = (String)ticketProps.get("validity");
    		// strValidMin = (String)ticketProps.get("validityMin");
    		// if (null != strValid) {
    		// sapAssertionTicket.setValidTime(Integer.parseInt(strValid));
    		// }
    		// if (null != strValidMin) {
    		// sapAssertionTicket.setValidTimeMin(Integer.parseInt(strValidMin));
    		// }
    		try {
    		} catch (TicketException e) {
    			throw new StreamTransformationException("TicketException setValidTimeMin " + 2, e);
    		try {
    		} catch (TicketException e) {
    			throw new StreamTransformationException("TicketException setDoNotCacheTicket true", e);
    		traceAddDebug("before sapAssertionTicket.create() ");
    		try {
    		} catch (Exception e) {
    			throw new StreamTransformationException("Exception sapAssertionTicket.create()", e);
    		traceAddDebug("sapAssertionTicket.create() done" + sapAssertionTicket.toString());
    		recipientClientInfoUnit = sapAssertionTicket;
    		traceAddDebug("copy to InfoUnit done");
    		String ticketString;
    		try {
    			ticketString = sapAssertionTicket.getTicket();
    		} catch (TicketException e) {
    			throw new StreamTransformationException("Exception sapAssertionTicket.getTicket()", e);
    		traceAddDebug("ticketString " + ticketString);
    		// unnecessary to create SAPAuthenticationAssertionTicketCredential
    		SAPAuthenticationAssertionTicketCredential sapcred = new SAPAuthenticationAssertionTicketCredential(ticketString, user);
    		String credString = sapcred.getTicketString();
    		traceAddDebug("credString " + credString);
    		// credstring and infostring seems to be the same
    		return ticketString;





  • Hi Alex,

    Regarding “Virtual user”


    Can you explain the concept of “virtual user”?

    Can it be used with Principal propagation?


    Someone else with some good ideas?


    scenario “NOT SAP web server” –> SAP PO –> SAP ABAP backend

    solution should work for async (one way) and synch (request-response)

    The users are authenticated at some “NOT SAP system” but with the same userid as they have in the backend SAP ABAP.

    On SAP PO we want to forward the call using iFlow to the SAP ABAP backend and execute with the userid they authenticated with at the NOT SAP system.

    We don’t want the userids to be present at the SAP PO system.

    Can virtual user be used to achive this?

    Anyone who has an example?







    After more research I found that virtual user can’t easily be used by customers when implementing custom jaas LoginModule.


    The APIs


    are not allowed to be used by customers. You are not allowed to set dependency to the DC/SC.

    If the APIs were open to customers it would be possible to implement LoginModule using JWT token without the need to have the users in the UME.