Calling On-prem Web Services from the Cloud

| | Comments (0) | TrackBacks (0)

As organizations begin using and deploying cloud applications, some of their services are left on-premises (for various reasons), resulting in a hybrid architecture. In such deployments, the on-prem services sometimes need to be invoked securely from the cloud. When doing so, an STS can be used to broker trust from the cloud into the organization. Unfortunately, the token issued by the IdP when authenticating end users isn't always available to the cloud-based caller due to restrictions/limitations of the cloud platform. In such cases, the on-prem STS can't be given a token asserted by a trusted issuer that it can validate and transform. As a result, the on-prem services do not have all the data needed to make authorization decisions, enforce licensing agreements, etc. One possible solution to this problem is to allow the cloud-based caller to specify in the message sent to the STS certain end-user-related data that should be put in the token that is minted. This will then be passed along to the on-prem services in a token asserted by the local STS. This idea is shown in the following figure:

At first, this may seem odd since the STS is the asserting party and it is being told what to assert. In cases where there is a trusted subsystem in place between the STS and the cloud app, however, it is safe IMO. Consider the alternative where the cloud app doesn't have the original security token. Since the interface of an STS is restricted to security tokens (by design), the client must create one using the identity attributes provided to it by the PaaS environment in which it's running. In other words, if the token asserted by the IdP isn't available, the cloud app has to cook one up. In this case, it is the asserter, resulting in the same sort of situation where it's the authority not the STS. The nice thing about passing the end user data in the message is that the caller needn't create a security token. There are tradeoffs w/ this approach, but there always are ;-)

The WS-Trust specification allows any XML to be included in the RST that the client sends to the STS. Ping Identity has used this extensibility point in the protocol to allow callers to include name/value pairs that PingFederate should include when minting security tokens. As a result, it is very easy using that STS to implement the sort of architecture described above. To do so, you would configure the STS w/ the attribute names that can be passed in the request, stipulate what to do if they are not (fault or do nothing), and include them in the RST. Totally simple.

To make this even simpler though, I extended WIF's RequestSecurityToken and WSTrustRequestSerializer classes to make the client-side programming model natural and easier for .NET developers. Using these, a cloud-based STS client could pass the end user's identity info in the request rather than having to create a security token. The result would look something like this:

private static RequestSecurityTokenResponse RequestSecurityToken(
UserData userData) { // Send a request parameter in the RST sent to the PingFederate // STS. These should be included in the security token that it
// mints and sends back in the RSTR. var factory = GetChannelFactory(); var requestParams = new RequestParameters("ShoeSize",
userData.ShoeSize, "HairColor", userData.HairColor); var rst = new TravisSpencer.IdentityModel.Protocols.
WSTrust.RequestSecurityToken {
RequestParameters = requestParams,
RequestType = WSTrust13Constants.RequestTypes.Issue, AppliesTo = new EndpointAddress(appliesTo), }; RequestSecurityTokenResponse rstr; var channel = factory.CreateChannel() as WSTrustChannel; var token = channel.Issue(rst, out rstr); return rstr; }

If you have questions about this or if you have this sort of problem and would like to talk, please let me know.