Skip to Content

Java AS has a nice capability of using a custom logon module. This allows you to use alternative methods to authenticate users. A nice technical example is to use Facebook Connect as an alternative method for authentication. Check this blog for more information on how to do it on Java stack.

Unfortunately, ABAP AS does not have this capability. I hit this limitation many times before. You can have a custom HTTP handler running under service user but there is no way of switching from service user to different user. One workaround is redirecting to Java AS, perform authentication there, generate a SSO cookie and then redirect back to ABAP AS. I was still hoping for a solution that does not require Java AS. You could use same trick on ABAP AS stack if you could generate SSO cookie for any user. You can get a cookie only for current user. SAP does not provide library for generating SSO cookies. There is a library called SAPSSOEXT that gives you capability of validating SSO cookies. So you can use SAP SSO cookies in external apps for authentication.

Recipe

It’s really funny that it’s never occurred to me that it should not be hard to reconstruct SSO ticket structure. I knew that each cookie is digitally signed. Finally, I tried it this week and it wasn’t hard at all. SAP SSO ticket has a simple structure and now when I think about it it’s obvious. It’s just a list of values that are digitally signed. Basically, it is composed of a ticket header and multiple pairs: field header and field value.  Here is my recipe for it.

SSO Structure:

Ticket Header

Field Header

Field Value

Field Header

Field Value

……

Field Header

Field Value

Note that the following examples of field values are in hexadecimal format and this is not a full spec of SSO format.

The ticket header has only two fields: version and code page used for the field values.

Field Name

Length

Description

Version

1 byte

Always x02 (even cookie is called MYSAPSSO2)

Code page

4 bytes

Unicode systems seem to use code page 4102 that corresponds to UTF-16BE. It means that there will be two bytes for each character. Hence you can see value x34313032

The field header has two fields: field ID and length of value.

Field Name

Length

Description

Field ID

1 byte

  1. E.g. ID x01 corresponds to field username

Length

2 bytes

  1. E.g. x0018 is a length for field username. Username in ABAP AS is 12 characters long and UTF16 has 2 bytes for each character. Hence for this field there will be 24 bytes (x18).

The field value is just a stream of bytes with length defined in corresponding field header. The field ID is only one byte. Therefore we can have 256 different field IDs. I’ve seen various field IDs. I haven’t figured out meaning of all of them. Also a cookie generated by Java AS has more fields than one generated by ABAP AS. But not all fields are mandatory. Here is a list of required fields for generating a valid SSO ticket that is accepted by ABAP AS.

Field ID

Length (code page 4102)

Description

1

24 bytes

Username

2

6 bytes

Client of issuing system

3

16 bytes

Issuing system ID

4

24 bytes

UTC Creation date and time without seconds

5

4 bytes

Validity in hours

255

Variable, length of digital signature.

Digital signature of all cookie in PKCS#7 format

It’s quite easy to generate SSO cookie in any programming language.  You just need to have a crypto library that can sign binary data using PCKS#7 format.

Here is SSO cookie generation in 3 simple steps:

  1. Generate binary data in format described above (do not include field 255 – digital signature)
  2. Sign generated data with private key of certificate that is used for validating SSO tickets
  3. Append field 255 with value set to digital signature to binary data.

Don’t forget that creation date and time must be in UTC. Otherwise it can drive you crazy when something works ½ day and it does not the other half (ratio of working/not working depends on your time zone).

I wrote my own implementation in ABAP (I told you that I wanted to have implementation without Java and using OS commands is not a nice solution). It’s hosted on Code Exchange as Project Biscuit. It’s a simple ABAP class but I could not find a better place for it than Code Exchange. Usage of this class is dead simple. It takes only 5 lines including variable definitions to get a valid cookie.

DATA: biscuit TYPE REF TO zcl_biscuit,
     ticket
TYPE string.

biscuit = zcl_biscuit=>get_biscuit( ).
ticket
= biscuit->get_ticket( ‘MARTIN’ ).

Some final thoughts

What was my motivation to figure this out? Just recently I’ve seen a presentation about new Mozilla Persona. I really like this solution of distributed identity providers. The presenter claimed that you can include Mozilla Persona into your application in less than 4 hours. I wanted to test if it’s also true for ABAP AS. I knew that I really needed to solve this authentication issue first. If anybody is wondering, yes it takes less than 4 hours to build a Mozilla Persona prototype in ABAP AS.

Why SAP does not provide a library to generate SSO cookies? I don’t know. My guess is that as usual it’s a mix of various reasons. Inexperienced developers can cause lots of harm by implementing custom logon procedures. You can also do lots of shady things to avoid licensing cost with this.

Final note about name: I was told that here in Australia we don’t have cookies, we have biscuits. Hence the names of class, project and this blog post.

To report this post you need to login first.

16 Comments

You must be Logged on to comment or reply to a post.

  1. Jonathan Groll

    Impressive stuff. This will certainly come in handy at some stage.

    Please forgive the obvious question, why wasn’t the function SUSR_INTERNET_USERSWITCH a suitable option? In my testing it successfully pivots the service user to a regular dialogue user when supplied with username and password.

    Additonally, if you do need to supply the MYSAPSS02 ticket for future calls you can use function SUSR_CHECK_LOGON_DATA (with auth_method = ‘P’) to get access to the ticket.

    (0) 
    1. Martin Voros Post author

      Hi Jonathan,

      the problem with SUSR_INTERNET_USERSWITCH is that you need to know user’s password. So you can’t use this FM to implement an authentication mechanism. For example if you want to implement something like SAML where you get a digitally signed ticket from identity provider and you just validate this ticket. You never ask user for password. Now I am not sure how SUSR_CHECK_LOGON_DATA works and I don’t want to launch VPN to connect to one system but again I think you need to provide username and password. That is not going to help me with implementing different authentication mechanism than username and password. There is also FM that allows you to switch from service user to normal user but you need to provide username and SSO cookie. So with my code you can use this one to switch to different user.

      The main reason why I did this was that I wanted to implement Mozilla Persona. A user can log on to system without entering SAP username and password when it uses Mozilla Persona. I have a first draft of blog where I describe how I did it. I hope to publish it soon. There I used this class to generate SSO cookie when I validate assertion ticket from identity provider.

      There might be a way how to get a cookie for a particular user but I could not find it. Also the cookie structure is useful if you want to have SSO between non-SAP systems where you don’t want to authenticate against SAP with username and password. E.g. SAP does not support 2-factor auth at this moment. Actually, that’s not true anymore because you can implement 2FA using this class.

      Cheers,

      Martin

      (0) 
  2. Philip Keng Ping Tan

    Hi Martin,

    I have this requirement where users will be accessing payroll data of SAP ECC from SAP Success Factors from the payroll integration of the SF. So my understanding from this is that SF will be the IDP while SAP ECC (NW 7.31) would be the Service Provider. Is there anyway that I can configure the SAP ABAP to issue a logon ticket for SF when the service is called from SF?

    (0) 
    1. Martin Voros Post author

      Hi,

      this code allows you to create a SSO cookie for any user and I don’t think that it will be helpful for your problem.

      In your case a user will log on to SF and then she will be redirected to ECC. I don’t have any knowledge of this scenario but my guess is that SAML is used for this. So if you want to do it other way then ECC system must be able to issues SAML ticket (in other words ECC system needs to be SAML Identity provider). ECC can’t be SAML IdP so it’s not possible.

      Cheers,

      Martin              

      (0) 
  3. Martin Voros Post author

    Hi,

    4102 is utf16 big endian and 4103 is utf16 is little endian. Probably I did development on AIX machine and they should be big endian.

    I am not sure but I thin field 6 (right after validity in hours – field 5) can be used to set minutes but I do not remember length.

    Cheers

    (0) 
  4. Martin Voros Post author

    Hi Jan,

    actually, I should fix my code to use system variable instead of hard coded value. Glad to hear that somebody is using my code.

    Cheers

    (0) 
  5. Martin Voros Post author

    Hi everyone,

    SAP shut down Code Exchange and licensing seems to prevent publishing code somewhere else (really pissed off about SAP at this moment). I still have the code. So if anyone wants it then just let me know.

    Cheers

    (0) 
    1. Julius von dem Bussche

      It is a real pity. But I can understand that developers wanting to collaborate on code have a problem with the terms and NDA type conditions. Personally I never signed it nor put any code there.

      Everything in ABAP anyway belongs to SAP from a language perspective. I think the laywers still live in the belief that they wrote the language and the applications… ;-(

      Cheers,

      Julius

      (0) 
      1. Martin Voros Post author

        Hi Julius,

        to clarify myself. I wasn’t pissed off about shutting down Code Exchange. It was terrible so I am not surprised. I also don’t want to comment on licensing issue. I was really pissed off about 3 day notice. I got an email on Thursday and I could not access it on Sunday. The notice was displayed longer in Code Exchange space but I do not go there. BTW the notification email looked like written in Word. This is not how you shutdown service even unpopular one.

        Cheers,

        Martin

        (0) 
    2. Jonathan Groll

      Hi Martin

      I’d very much like a copy of your code. I tried sending you a direct message via this site, but wasn’t allowed to. I have now enabled emails from you by visiting your profile page so it may work if you contact me via direct message.

      Hope this message finds you,

      Jonathan.

      (0) 
    3. Eivind Mikkelsen

      I’m working on establishing SSO between an external Identity Provider (OpenAM) and an old version of SAP which unfortunately doesn’t support SAML.

      I had nearly given up when I came across your article. I’ll attempt to create a valid MYSAPSSO2 cookie from OpenAM, and it would be of great help if you could send me a copy of your code!

      Best regards

      Eivind M.

      (0) 
        1. Grant Peterson

          Hi Martin,

          Would it be possible to please get a copy of your code so I can understand the structure of the ticket? I am trying the CREATE_RFC_REENTRANCE_TICKET FM but the ticket is expiring after a few minutes, I think because it is a re-entrance or assertion ticket and I need to create a “normal” SSO ticket that lasts usually for 8 hours.

          Regards,

          Grant

          (0) 
  6. Chris Hesse

    This is something I’ve wanted to do for a long time, but from Java code.  Could I get a copy of your ABAP class?  Ever thought of putting it on github or something similar?

    I have some questions about the recipe – the system ID is length 16, but my understanding is that normally the system ID is the 3 character SID, e.g. NSP.  To fill up the rest of the length what do we do?  Pad with 0’s?  Pad with space?

    It would also be helpful if you could add to the recipe examples for each of the fields.  This would enable myself and others to have a known working final result to validate our own code against.

    E.g.

    Username ‘XX1234’:  HexString FieldHeader ‘010018’ Value ‘585831323334’

    Client ‘000’:  HexString FieldHeader ‘020006’ Value ‘303030’

    SystemId ‘NSP’:  HexString FieldHeader ‘030010’ Value ‘4E5350’

    UTC create time ‘201510210220’:  HexString FieldHeader ‘040018’ Value ‘323031353130323130323230’

    Validity in hours ‘8’:  HexString FieldHeader ‘050004’ Value ‘3030303030303038’

    Are these calculations correct?  How do I pad the SystemId field?  Should it be ‘30303030304E5350’ instead with padded zeros?

    I will edit this post with the final hex string which needs to be signed once I know that each individual field is correct.

    Chris

    (0) 

Leave a Reply