Retrieving the OAM SessionID for Fun and Profit!

Introduction

I recently worked with a customer who needed to do some OAM session manipulation via custom code in order to implement a complex use case. While the focus of this post is not to go into details about a specific implementation, I did want to share some advice on a very necessary building block needed to do “out of band” session manipulation: retrieving the OAM Session ID.

What is the Session ID (used for)?

OAM 11g supports the concept of a server-side session (unlike previous versions where the only session state was represented by a browser cookie) and this architecture allows for a far richer set of functionality, including the ability to manipulate the server-side session through the addition of attribute values that can be considered during the evaluation of an OAM policy. Each session stored in the server session store (shared across the cluster using Coherence) is identified by a unique GUID known as the Session ID – that’s the long number you see in the folllowing screenshot, taken from the OAM Admin Console:

Session-ID

The reason this identifier is useful, though, comes when you start to look at the API Docs for the OAM Access SDK, which is the component you’ll need to use in order to do things like session manipulation from custom code. Looking specifically at the UserSession class, you’ll note that several of the utility methods require that you pass the SessionID as argument; this is a mandatory step in order to obtain a reference to an existing session in order to manipulate it.

Just a clarification at this point. Please do not interpret this post as a blanket endorsement of writing a custom Access Client as the solution to any and all problems. As always, work with your chosen OAM architect to carefully weigh up the pro’s and cons and various options available, with a strong preference for using out-of-the-box functionality, before concluding that custom code is the best way to solve your particular problem.

Assuming we’ve complied with the above caveat, done the necessary homework and concluded that the custom Access Client solution is what we have to do, what we then need is a way to obtain the Session ID from an existing authenticated user session in order to pass it to our custom code.

Using Identity Assertion to obtain the Session ID

Step 1 here is (perhaps obviously) to ensure that we place a WebGate in front of our custom code in order to ensure that there is actually a session in place and that we can use an authorization policy response to transfer information to that code via headers (the usual OAM approach). Now, for a number of very good reasons, the Session ID (a sensitive piece of information that needs to be protected) is not available as a direct policy response, in the same way that the user id, profile attributes or session attributes would be. As is perhaps clear from reading the AccessSDK documentation, you can do a lot of harm with this SessionID in your hands and, as such, it behoves you as an organization to take appropriate steps to protect this data within your code and over your network.

Treat the SessionID, in other words, just as you would a password. Do not write it into log files, do not send it over network links in clear text and take the necessary precautions to ensure that headers sent from your web tier to your app tier cannot be tampered with or spoofed. All the usual rules regarding safe and secure identity propagation apply, in other words.

With caveats and good practice advice out of the way, let’s talk about how to get this magical nugget of info into your custom code. The answer is to enable Identity Propagation for the Authorization policy protecting the URL, as per the following screenshot.

Assertion

Once you do this, you will find that a SAML assertion is sent from the WebGate to your app in a header called “OAM_IDENTITY_ASSERTION”. There’s a lot of info inside this assertion, but you’re looking for the following snippet within the XML body.

<saml:Assertion xmlns:saml=”urn:oasis:names:tc:SAML:2.0:assertion” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xs=”http://www.w3.org/2001/XMLSchema” Version=”2.0″ ID=”6714fd68-596c-4cfa-af61-91b43a5ecd2a” IssueInstant=”2015-10-23T09:34:23Z”>
<saml:Issuer>OAM User Assertion Issuer</saml:Issuer>
…..
<saml:AttributeStatement>
<saml:Attribute NameFormat=”urn:oasis:names:tc:SAML:2.0:attrname-format:uri” Name=”urn:oasis:names:tc:SAML:2.0:profiles:session:sessionId”>
<saml:AttributeValue xsi:type=”xs:string”>d8ccd738-522f-4700-a91c-fd630b70ff61|S+kAgs+tqO+Rblq6abFwllAo5J4=</saml:AttributeValue>
</saml:Attribute>
……
</saml:AttributeStatement>
</saml:Assertion>

Right there, in the bolded text, is your Session ID. Use it wisely – keep it secret, keep it safe.

Comments

  1. Hi Rob,

    I think I’m in the same boat as Ramesh. I have sessionID only (and no sessionToken), but I need to somehow get the userID. Is there no way to get that if I only have the sessionID?

    Looking at the docs, and trying a bunch of stuff, I think that the answer to my/this question is “no, there is no way”, but I thought I’d ask.

    Thanks,
    Jim

    • Hi Jim. I’m confused. How did you get the sessionID in the first place? If it came from the SAML assertion, then the user ID will be in there as well. Since you are relying on a WebGate to send the assertion downstream to your app, the user ID will also always be available in the OAM_REMOTE_USER header set by the WebGate. I get the feeling there’s something about your use case that I’m not understanding here.

      Cheers
      Rob

      • Hi Rob,

        Thanks for responding, and my apologies that I wasn’t clear re. background.

        We are trying to implement some way to monitor the number of sessions for each user, and we are working/using the ASDK, so we get session IDs from the UserSession.getSessionIds() method call.

        The problem is that it doesn’t look like there is any way to figure out which user each of the session IDs we get back from the getSessionIds() are associated with, and we need to be able to do that in order to count the sessions for each user (FYI, we run the OAM with database persistence “off” so we cannot query the oam_session database for that information).

        Jim

        • Jim – this is off-topic for this post, so I won’t go into a lot of detail. I’m concerned that you may be misinterpreting the getSessionIDs() call, though. According to the API doc that I’ve just checked, you need to pass a userid to that call to retrieve sessions for just that user. I’m not aware of a call that will return every session ID.

          It sounds like you’re trying to recreate functionality that is already available in the OAM Console, though.

          Cheers
          Rob

          • Hi Rob,

            Actually, UserSession.getSessionIds(userid) is a static method, so it can be without instantiating a UserSession object, and from our testing, that getSessionIds(userid) *DOES* return a set of session IDs. The problem that we’re having is trying to find a way to determine the user ID if we’re only given a session ID (NOTE: a “session ID”, not a “session Token”). We have an SR on it, and what you said at the end is kind of exactly what gives us hope that there may be a way to do this. What I mean is, as you said, the OAM Console IS able to access a bunch of info associated with each session ID, e.g., the userid, the expiry instant, etc. And, it appears to do that without authenticating as each of the users that are associated with the session IDs.

            So, we know that OAM Console CAN do what we’re looking for, or at least it looks like OAM Console can do what we’re looking for, so now the question is “how does it do that?” and then “can we do that also?”…

  2. Mohammed Samiya says:

    Hello Rob,

    Customer has OAM-OAAM integrated scenario for their banking application.
    Now they want to encrypt the session id for avoiding any type of hacking issues.
    Could you please help me in understanding if this can be done on session id level.
    I understand that cookies can be encrypted in OAM but how about the session id?

    Highly appreciate your assistance on this.

    Regards,
    Samiya

    • Hi Samiya – hope you’re well today.

      I’m not sure I quite understand the concern here. The integration between OAM and OAAM is accomplished using encrypted tokens over the proprietary DAP protocol – as such, the session ID (whether encrypted or not) does not feature.

      The above mechanism only comes into play if you explicitly check the “Identity Assertion” checkbox on your AuthZ policy and even then, is only used to pass the Identity Assertion XML (including the session ID) from the WebGate to the back-end application server. If your customer does not require identity assertion for their use case (which sounds like the case) and are concerned about security, then the simplest thing to do is ensure the Identity Assertion checkbox remains unchecked in their policies.

      Cheers
      Rob

  3. Hi Rob,

    I am really need to validate the sessionid from asdk and just extract the userid only is my requirement after WG session creates and webserver handover the control to App server[wls or WAS].. your note is encouraging me to go this path! I tried using UserSession.object to initiate the instance with valid sessionid but not working..
    session = new UserSession( sessionId);
    session = new UserSession(ac, sessionId); [ac is the AccessClient obj to intitiate the AcessGate configurations]

    both statements not working in 11gMode..

    could you guide how to initiate the Session object with the available sessionid?

    • Hey Srinivas

      If you only requirement is to extract the userID, you should just pass that value as a header to your application. A lot simpler than messing around with the ASDK if you don’t need to.

      Cheers
      Rob

    • the reason your calls are failing, though, is because you are confusing sessionToken with sessionID. The constructors you are trying to call expect a sessionToken, not a sessionID:

      UserSession(java.lang.String sessionToken)
      Constructs a UserSession object with specified token
      UserSession(AccessClient aClient, java.lang.String sessionToken)
      Constructs a UserSession object with specified token and AccessClient object

      There is no constructor that take the sessionID as input, only the following static methods that allow you to get/set session attributes:

      getSessionAttributes(AccessClient aClient, java.lang.String sessionId)
      Get the attributes for the given sessionId using the specified AccessClient object.
      setSessionAttributes(java.lang.String sessionId, java.util.Hashtable sessionDetails)
      Set the session details for the given sessionId

  4. Thanks a lot for this great post.

    Could you please further explain how can we change sessionid obtained from this approach to java.lang.String sessionToken. The constructors in the SDK is asking for sessionToken. Great if you could point to the right direction.

    • hi Ramesh

      You cannot convert a sessionID into a session token. If you look at the API docs, though, there is a static method you can use to update attributes of a session based on the sessionID alone.

      Cheers
      Rob

Add Your Comment