How To

How are SAML2 tokens stored in the CTS in AM (All versions)?

Last updated Nov 2, 2020

The purpose of this article is to provide information on how SAML2 tokens are stored in the CTS in AM. Importantly, SAML2 tokens are only stored during SAML failover. This article also includes example token formats and details on performing LDAP searches to retrieve token details from the CTS.


Overview

SAML2 tokens are only saved to the CTS when SAML2 failover is enabled. SAML2 failover is enabled by default in AM 7; in previous versions, you must enable it manually as described in SAML v2.0 Guide › Configuring SAML v2.0 Providers for Failover

Depending on your setup, other SAML2 tokens may be saved:

  • Assertion - the assertion is saved to the CTS when the Assertion Cache is enabled for the IdP. See SAML v2.0 Guide › Assertion Cache for further information.
  • AuthnRequest - the AuthnRequest is saved as follows depending on whether AM is the IdP or SP:
    • IdP: the AuthnRequest is saved in the server’s cache (not the CTS), which means it cannot be recovered by another server. 
    • SP: the AuthnRequest is saved in the cache and the CTS.

The coreTokenObject can be either JSON or a base64 encoded string.

LDAP searches

You can query the CTS using ldapsearch. For example, if you want to list SAML2 tokens, you would filter on coreTokenType=SAML2:

  • DS 7 and later: $ ./ldapsearch --hostname ds1.example.com --port 1389 --bindDN uid=admin --bindPassword password --baseDN "ou=famrecords,ou=openam-session,ou=tokens,dc=openam,dc=forgerock,dc=org" coreTokenType=SAML2
  • Pre-DS 7: $ ./ldapsearch --hostname ds1.example.com --port 1389 --bindDN "cn=Directory Manager" --bindPassword password --baseDN "ou=famrecords,ou=openam-session,ou=tokens,dc=openam,dc=forgerock,dc=org" coreTokenType=SAML2

Example SAML2 Token

When SAML2 failover is enabled, SAML2 tokens are saved to the CTS, which makes them accessible to other servers.

An example token looks like this:

dn: coreTokenId=733237633231656432303961383835626662623039343434653564666532323964366632376466343032,ou=famrecords,ou=openam-session,ou=tokens,dc=openam,dc=forgerock,dc=org objectClass: top objectClass: frCoreToken coreTokenId: 733237633231656432303961383835626662623039343434653564666532323964366632376466343032 coreTokenType: SAML2 coreTokenExpirationDate: 20200617142726+0100 coreTokenObject:: eyJkb0xvZ291dEFsbCI6ZmFsc2UsIm1ldGFBbGlhcyI6Ii9pZHAiLCJuYW 1lSURhbmRTUHBhaXJzIjpbeyJuYW1lSUQiOnsiQGNsYXNzIjoiY29tLnN1bi5pZGVudGl0eS5zY W1sMi5hc3NlcnRpb24uaW1wbC5OYW1lSURJbXBsIiwiZm9ybWF0IjoidXJuOm9hc2lzOm5hbWVz OnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6cGVyc2lzdGVudCIsImlzTXV0YWJsZSI6dHJ1ZSw ibmFtZVF1YWxpZmllciI6Imh0dHA6Ly9pZHAuZXhhbXBsZS5uZXQ6ODA4MC9vcGVuYW0iLCJzcE 5hbWVRdWFsaWZpZXIiOiJodHRwOi8vb3BlbmFtLmV4YW1wbGUuY29tOjE4MDgwL29wZW5hbSIsI nNwUHJvdmlkZWRJRCI6bnVsbCwidmFsdWUiOiIreHh1dDFzcEJHSVZRYkswMkxscE1NSENLWWhX In0sInNwRW50aXR5SUQiOiJodHRwOi8vb3BlbmFtLmV4YW1wbGUuY29tOjE4MDgwL29wZW5hbSJ 9XSwib3JpZ2luYXRpbmdMb2dvdXRSZXF1ZXN0QmluZGluZyI6bnVsbCwib3JpZ2luYXRpbmdMb2 dvdXRSZXF1ZXN0SUQiOm51bGwsIm9yaWdpbmF0aW5nTG9nb3V0U1BFbnRpdHlJRCI6bnVsbCwic GVuZGluZ0xvZ291dFJlcXVlc3RJRCI6bnVsbCwic3NvVG9rZW5JRCI6IlVsTWNJblZVX0dVZ1hH R203cE0wNEdodVh3by4qQUFKVFNRQUNNRE1BQWxOTEFCeHZXWE5TZG0xNFNXMVVLM1J6TlZCS1Y xcHFORTgyWlRscWFqZzlBQVIwZVhCbEFBTkRWRk1BQWxNeEFBSXdNZy4uKiJ9 coreTokenString01: com.sun.identity.saml2.profile.IDPSessionCopy

If coreTokenObject is a string, you can decode it (for example, using base64decode.org) where this example decodes as follows:

{ "doLogoutAll":false, "metaAlias":"/idp", "nameIDandSPpairs":[ { "nameID":{ "@class":"com.sun.identity.saml2.assertion.impl.NameIDImpl", "format":"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent", "isMutable":true, "nameQualifier":"http://idp.example.net:8080/openam", "spNameQualifier":"http://openam.example.com:18080/openam", "spProvidedID":null, "value":"+xxut1spBGIVQbK02LlpMMHCKYhW" }, "spEntityID":"http://openam.example.com:18080/openam" } ], "originatingLogoutRequestBinding":null, "originatingLogoutRequestID":null, "originatingLogoutSPEntityID":null, "pendingLogoutRequestID":null, "ssoTokenID":"UlMcInVU_GUgXGGm7pM04GhuXwo.*AAJTSQACMDMAAlNLABxvWXNSdm14SW1UK3RzNVBKV1pqNE82ZTlqajg9AAR0eXBlAANDVFMAAlMxAAIwMg..*" }

If you use a non-default relay state parameter in the metadata, you will also get a token where the coreTokenObject equals the relay state parameter. 

Example Assertion Token

When SAML2 failover is enabled, the Assertion Cache is enabled and AM is acting as the IdP, assertions are saved to the CTS, which makes them accessible to other servers.

An example assertion looks like this:

dn: coreTokenId=4141514141465630674d52516d69643478435642777932316a714463507a5733566f62703738524a624b36523866755737303567545070624d44453d,ou=famrecords,ou=openam-session,ou=tokens,dc=openam,dc=forgerock,dc=org control: 1.3.6.1.4.1.36733.2.1.5.1 false: bcb3efeb-14a9-47be-8716-9c18918322c8-19593/8 changetype: add objectClass: frCoreToken objectClass: top coreTokenId: 4141514141465630674d52516d69643478435642777932316a714463507a5733566f62703738524a624b36523866755737303567545070624d44453d coreTokenExpirationDate: 20200523081647Z coreTokenType: SAML2 coreTokenObject: "<samlp:Response xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"s2d254cb2c6567979aa293a25d1e0c2c185c976524\" Version=\"2.0\" IssueInstant=\"2020-06-22T11:17:47Z\" Destination=\"http://sp.example.com:8080/openam/Consumer/metaAlias/sp\"><saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">IdP</saml:Issuer><samlp:Status xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\">\n<samlp:StatusCode xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\">\n</samlp:StatusCode>\n</samlp:Status><saml:Assertion xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" Version=\"2.0\" ID=\"s2f4d9640d71d59c81f145d17cdb738c8ff4d9e5fc\" IssueInstant=\"2020-06-22T11:17:47Z\">\n<saml:Issuer>IdP</saml:Issuer><saml:Subject>\n<saml:NameID NameQualifier=\"IdP\" SPNameQualifier=\"SP\" Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent\">L+OjhuzCtalCRDSox+F3eMcjxjt2</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\">\n<saml:SubjectConfirmationData NotOnOrAfter=\"2020-06-22T11:27:47Z\" Recipient=\"http://sp.example.com:8080/openam/Consumer/metaAlias/sp\" ></saml:SubjectConfirmationData></saml:SubjectConfirmation>\n</saml:Subject><saml:Conditions NotBefore=\"2020-06-22T11:27:47Z\" NotOnOrAfter=\"2020-06-22T11:27:47Z\">\n<saml:AudienceRestriction>\n<saml:Audience>SP</saml:Audience>\n</saml:AudienceRestriction>\n</saml:Conditions>\n<saml:AuthnStatement AuthnInstant=\"2020-06-22T11:17:47Z\" SessionIndex=\"s251a8cdd305404bdf8a4d493860732c2f75842f01\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement></saml:Assertion>\n</samlp:Response>" coreTokenString01: java.lang.String

Example AuthnRequest Token

When SAML2 failover is enabled and AM is acting as the SP, AuthnRequests are saved to the CTS, which makes them accessible to other servers.

An example AuthnRequest looks like this:

dn: coreTokenId=733230323466363833626637636133316239333932316532616263653035616164656531323931613964,ou=famrecords,ou=openam-session,ou=tokens,dc=openam,dc=forgerock,dc=org objectClass: frCoreToken objectClass: top coreTokenExpirationDate: 20200622180136+0100 coreTokenId: 733230323466363833626637636133316239333932316532616263653035616164656531323931613964 coreTokenObject: {"authnRequest":"<samlp:AuthnRequest  xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"s2024f683bf7ca31b93921e2abce05aadee1291a9d\" Version=\"2.0\" IssueInstant=\"2020-06-22T16:51:36Z\" Destination=\"http://idp.example.net:8080/openam/SSORedirect/metaAlias/idp\" ForceAuthn=\"false\" IsPassive=\"false\" ProtocolBinding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\" AssertionConsumerServiceURL=\"http://openam.example.com:18080/openam/Consumer/metaAlias/sp\">\n<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">http://openam.example.com:18080/openam</saml:Issuer>\n<samlp:NameIDPolicy  xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent\" SPNameQualifier=\"http://openam.example.com:18080/openam\" AllowCreate=\"true\"></samlp:NameIDPolicy>\n<samlp:RequestedAuthnContext xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" Comparison=\"exact\"><saml:AuthnContextClassRef xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></samlp:RequestedAuthnContext>\n</samlp:AuthnRequest>","idpEntityID":"http://idp.example.net:8080/openam","paramsMap":{"binding":["HTTP-POST"]},"realm":"/","relayState":null,"spEntityID":"http://openam.example.com:18080/openam"} coreTokenString01: com.sun.identity.saml2.profile.AuthnRequestInfoCopy coreTokenType: SAML2

See Also

Understanding CTS token types in AM/OpenAM

SAML Federation in AM/OpenAM

SAML v2.0 Guide

Related Training

N/A

Related Issue Tracker IDs

OPENAM-14995 (IdP Initiated single logout only performs local logout if IdP session cannot be found in cache)

OPENAM-1194 (Unable to get AuthnRequest error in multiserver setup)



Copyright and TrademarksCopyright © 2020 ForgeRock, all rights reserved.
Loading...