Thursday, June 3, 2010

Impersonation and OES

When it rains it pours! I had three separate customers asking me basically the exact same question today - Can OES help me with impersonation?

So, for starters, let's define the use case. A user is logged in and wants to act as another user for some brief period of time - like for a few minutes to troubleshoot an issue. Once the impersonation is established all of the authorization should be calculated against the impersonatee (person being impersonated). In the audit logs, you should see both the impersonator and impersonatee. Optionally, there may be rules that are additionally calculated for the impersonator - example: DENY policies that are enforced even if the user is impersonating, like PII.

Just to clarify, this use case is different than delegation - which is similar except that delegation (in my vocabulary) has a longer duration than impersonation. The classic delegation use case is vacation - example: during the week I'm away, let Bob perform this privilege that I have. OES supports this type of model OOTB.

Impersonation is really more about tokens than it is about authorization, but there are some services that OES exposes that can be pretty helpful in this regard. The CredentialMappingService can be used to generate a token for a given user. You need a custom credential mapper that does two things:

1. Check if the current Subject is authroized to impersonate the other user. Looking at the signature of the getCredentials method, you can see that the actual CredentialMapper is going to get passed the Subject, the alias of the user to create, and then the RuntimeAction and RuntimeResource. This makes it pretty easy from inside of the CM to make a call to the AuthorizationService to check and see if the impersonation is allowed. I'd probably use the action "impersonate" and add the passed in Action to the AppContext.
2. Generate a token that the user can then use to impersonate. This is a little trick but basically you need to create an encrypted token that contains the name of the user - or a reference to a session - that has the name of the user. You also want to - either in the token or by reference - has access to the name of the person that is the impersonator - the Subject passed the CredentialMapperService.

So, now that you have the token, the next step is when the token is presented, to establish a JAAS Subject for the user being impersonated. This is a custom identity asserter. This identity asserter needs to be able to decrypt the token and set up the user name and the impersonator as callbacks. Since impersonator is not a standard callback, you need to pair the identity asserter with a custom login module that will make the callbacks. The user is added as a regular WLSUser. As for the impersonator, I would add them as a custom principal that extends WLSUser...like ImpersonatorUser.

With both of these added to the JAAS Subject, OES can perform authorization, and will use the regular user. If you want to have access to the impersonator, you'll need a custom attribute retriever - getImpersonator that basically pulls the ImpersonatorPrincipal from the JAAS Subject, and returns the name. Since the JAAS subect contains the impersonator name as well as the user, Audit logs will have access to both.

When the user is done impersonating, just have them logout, and log back in as themselves. There are more advanced cases when you can actually stop the impersonation. In that case, you have to extend the solution in a few ways. The first is that you need to persist the original JAAS Subject - either in the token or by reference - so that it can be restored. The second - is to have the identity asserter be able to establish the JAAS Subject of that impersonator. The third is to be able to generate either a token for the impersonator or the impersonatee based on the token type passed in the CredentialMapperService.

This is the mechanics of using the OES services, but these are just API calls. How would you get these APIs called? I think it depends on the context that you're attempting to impersonate. If this is a web-application, then this looks like a good fit for a ServletAuthenticationFilter. The tokens can be passed as HTTP cookies. For a services environment, this looks like a good use case for a custom STS and WS-Trust - wst:onBehalfOf - seems to fit very nicely here.

I left out a lot of the nitty gritty details (read: no sample), but I think this is enough to get people started. You'll have to apologize - my flight out of Atlanta (via Philadelphia) to Boston - is getting ready to board. Let me know if you like this approach and are interested in more details.

P.S.

BEAT LA
BEAT LA
BEAT LA

Take that Wayne!

1 comment:

  1. Thanks to Tim for spotting the typo in this post. I've corrected Delegation is really more about tokens... to read Impersonation is really more about tokens...

    ReplyDelete

Note: Only a member of this blog may post a comment.