Modifying the SL/WIF Integration Bits to support Issued Token Credentials
- by Your DisplayName here!
The SL/WIF integration code that ships with the Identity Training Kit only supports
Windows and UserName credentials to request tokens from an STS. This is fine for simple
single STS scenarios (like a single IdP). But the more common pattern for claims/token
based systems is to split the STS roles into an IdP and a Resource STS (or whatever
you wanna call it).
In this case, the 2nd leg requires to present the issued token from the 1st leg –
this is not directly supported by the bits. But they can be easily modified to accomplish
this.
The Credential
Fist we need a class that represents an issued token credential. Here we store the
RSTR that got returned from the client to IdP request:
public class IssuedTokenCredentials : IRequestCredentials
{
public string IssuedToken
{ get; set; }
public RequestSecurityTokenResponse RSTR
{ get; set; }
public IssuedTokenCredentials(RequestSecurityTokenResponse rstr)
{
RSTR = rstr;
IssuedToken = rstr.RequestedSecurityToken.RawToken;
}
}
The Binding
Next we need a binding to be used with issued token credential requests.
This assumes you have an STS endpoint for mixed mode security with SecureConversation
turned off.
public class WSTrustBindingIssuedTokenMixed : WSTrustBinding
{
public WSTrustBindingIssuedTokenMixed()
{
this.Elements.Add( new HttpsTransportBindingElement()
);
}
}
WSTrustClient
The last step is to make some modifications to WSTrustClient to make it issued
token aware. In the constructor you have to check for the credential type, and if
it is an issued token, store it away.
private RequestSecurityTokenResponse _rstr;
public WSTrustClient( Binding binding, EndpointAddress remoteAddress,
IRequestCredentials credentials )
: base( binding, remoteAddress
)
{
if ( null ==
credentials )
{
throw new ArgumentNullException( "credentials" );
}
if (credentials is UsernameCredentials)
{
UsernameCredentials usernname
= credentials as UsernameCredentials;
base.ChannelFactory.Credentials.UserName.UserName
= usernname.Username;
base.ChannelFactory.Credentials.UserName.Password
= usernname.Password;
}
else if (credentials is IssuedTokenCredentials)
{
var issuedToken
= credentials as IssuedTokenCredentials;
_rstr = issuedToken.RSTR;
}
else if (credentials is WindowsCredentials)
{ }
else
{
throw new ArgumentOutOfRangeException("credentials", "type
was not expected");
}
}
Next – when WSTrustClient constructs the RST message to the STS, the issued
token header must be embedded when needed:
private Message BuildRequestAsMessage( RequestSecurityToken request
)
{
var message = Message.CreateMessage(
base.Endpoint.Binding.MessageVersion ?? MessageVersion.Default,
IssueAction,
(BodyWriter) new WSTrustRequestBodyWriter(
request ) );
if (_rstr != null)
{
message.Headers.Add(new IssuedTokenHeader(_rstr));
}
return message;
}
HTH