The anatomy of a LTPA2 token

What is a LTPA Token?

Lightweight Third Party Authentication (LTPA) is a single sign-on credential format.
IBM
The Lightweight Third Party Authentication (LTPA) token is a specific type of binary security token. The web services security implementation for WebSphere Application Server, Version 5 and later supports the LTPA Version 1 token. WebSphere Application Server Version 7 and later supports the LTPA Version 2 token using the JAX-WS runtime environment.
IBM
The LtpaToken2 cookie is encoded using enhanced security over the LtpaToken.
IBM
With LTPA, the user authenticates with the first server that is accessed, by using a user name and password. After authenticating, the user receives an LTPA token, which is only valid for one session. The token is used to identify the user on other servers within the same domain name system, where the servers are configured to use LTPA. Therefore, the user enters a user name and password only once, and the user directory is accessed only once to verify the identity of that user.
IBM
LTPA can be used with WebSphere® Application Server and Worklight®. The servers must all use the same LDAP server for user authentication.
IBM
token workflow in sso

Structure of a LTPA2 token

External Structure

How does such a token look like? Well, as mentioned above, it is binary and it is using some sort of security. Since it send over http as a cookie (named "LtpaToken"), it is base64 encoded. So here is an example.

encoded token
Wl3qcMXdvCZjScDwB18/5VYujKDYsptVWXwNVW2yKuZw6h5Kg4amiGDeQCh2xmtNVPgCkzyk66ZWrdY70+nQEe+gotHjJtrcoW/VnbbQAwrQE5GojqK+1RdjvnwmQ9QULqcYAItw4ggZ2JF3CRR5uZ3NSFgkZpzkcMbfuYSWipNXsqEUHKONUlrg0Oc6lNKqWknx87HoPKmTnkGD5gdecu1FJCKUXSk1tanAjN3RaEWY8woxMIJQEMw/yeOrA9Fe+1nWjGAR5ITgkm+whpXfzl3n3g7kWHaBJf8DUUlKRsww4oCe3+t85b1WqoTC6FZw2qovLwn3ioRm1eIBDPO+KQZD60Ps4f+QEOjFzkLQC2f6BlZKc8KMHhffRQRpBgOD6kYV/wGDRHuvkK5vMAeJtQ==

If we base64-decode it, it will look like this.

decoded token
00000000  5a 5d ea 70 c5 dd bc 26  63 49 c0 f0 07 5f 3f e5  |Z].p...&cI..._?.|
00000010  56 2e 8c a0 d8 b2 9b 55  59 7c 0d 55 6d b2 2a e6  |V......UY|.Um.*.|
00000020  70 ea 1e 4a 83 86 a6 88  60 de 40 28 76 c6 6b 4d  |p..J....`.@(v.kM|
00000030  54 f8 02 93 3c a4 eb a6  56 ad d6 3b d3 e9 d0 11  |T...<...V..;....|
00000040  ef a0 a2 d1 e3 26 da dc  a1 6f d5 9d b6 d0 03 0a  |.....&...o......|
00000050  d0 13 91 a8 8e a2 be d5  17 63 be 7c 26 43 d4 14  |.........c.|&C..|
00000060  2e a7 18 00 8b 70 e2 08  19 d8 91 77 09 14 79 b9  |.....p.....w..y.|
00000070  9d cd 48 58 24 66 9c e4  70 c6 df b9 84 96 8a 93  |..HX$f..p.......|
00000080  57 b2 a1 14 1c a3 8d 52  5a e0 d0 e7 3a 94 d2 aa  |W......RZ...:...|
00000090  5a 49 f1 f3 b1 e8 3c a9  93 9e 41 83 e6 07 5e 72  |ZI....<...A...^r|
000000a0  ed 45 24 22 94 5d 29 35  b5 a9 c0 8c dd d1 68 45  |.E$".])5......hE|
000000b0  98 f3 0a 31 30 82 50 10  cc 3f c9 e3 ab 03 d1 5e  |...10.P..?.....^|
000000c0  fb 59 d6 8c 60 11 e4 84  e0 92 6f b0 86 95 df ce  |.Y..`.....o.....|
000000d0  5d e7 de 0e e4 58 76 81  25 ff 03 51 49 4a 46 cc  |]....Xv.%..QIJF.|
000000e0  30 e2 80 9e df eb 7c e5  bd 56 aa 84 c2 e8 56 70  |0.....|..V....Vp|
000000f0  da aa 2f 2f 09 f7 8a 84  66 d5 e2 01 0c f3 be 29  |..//....f......)|
00000100  06 43 eb 43 ec e1 ff 90  10 e8 c5 ce 42 d0 0b 67  |.C.C........B..g|
00000110  fa 06 56 4a 73 c2 8c 1e  17 df 45 04 69 06 03 83  |..VJs.....E.i...|
00000120  ea 46 15 ff 01 83 44 7b  af 90 ae 6f 30 07 89 b5  |.F....D{...o0...|
00000130

Not so nice, isn’t it? Okay, then let’s decrypt it! The encryption algorithm is AES-128-CBC with PKCS5/7 padding and as such we need the shared secret key. Now it is not so binary anymore!

decrypted token
expire:1519043460000$u:user\:LdapRegistry/CN=fae6d87c-c642-45a6-9f09-915c7fd8b08c,OU=user,DC=foo,DC=bar%1519043460000%ipDldknyTbaSZluHTW3I/Dhh9veyi+QHoX3s4MPxvvTc09COCGGbOQLxiGoIqdBxDrv55WChFNDD6uUtnt74gNX2KTRQpbwY5zSMbNHkUrh/6X+OOqbvcR3fAmIBkTAyBwkX3u6T2WEoEq9FxOYpvlhqvygoJYrjM6JuQeGhvqA=

Internal structure

Let’s have closer look at the components of a LTPA token. A token consists of three parts: body, expire and signature. All parts are separated by a percent sign %.

token parts

Expire

The expire part is the unix timestamp of the last validity date …​ in milliseconds! I do not know why IBM did that. Maybe they thought seconds would not be precise enough? But that just makes the next point more funnier: the last three digits are always 000 thus they are back at the precision of seconds!

Body

The body contains the actual token payload. It consists of simple key-value pairs with each pair separated by a dollar sign $ while key and value are delimited by colon :. If a value contains one of those special characters it must be escaped by preceding a backslash \ (look at the word "user" in the example above). So, the body is nothing more than a Java properties file with : instead of = and $ instead of a line terminator character (e.g. \n).

The body can contain any property you want. The only required property is u - it contains the distinguished name (DN) of the authenticated user in the LDAP directory. This information is required to build up the security context in your application. The WebSphere Application Server (or your Spring application) will have to search for that user in the LDAP, assigns groups/roles and finally sets up the security context. That’s why the authentication gateway (e.g. IBM DataPower®) and application server must have access to the same LDAP directory. Another key-value in body is expire - while it is optional it should be part of the body and have the same value as the expire part of the token.

body parts

Signature

The signature part is a digital SHA1-RSA signature of the body part and is base64 encoded as well. It is created by the issuer of the token. You need the public key of the issuer to verify the integrity of the token body. But there is at least one flaw: the expire part is not covered by the signature and could be changed without notice! Thus it should be read from the content of the body, if present.

Difference between LTPA Version 1

Version 1 uses DES-3DES encryption and simple RSA signature without hashing.