Requesting Delegation (ActAs) Tokens using WSTrustChannel (as opposed to Configuration Madness)

Delegation using the ActAs approach has some interesting security features

  • A security token service can make authorization and validation checks before issuing the ActAs token.
  • Combined with proof keys you get non-repudiation features.
  • The ultimate receiver sees the original caller as direct caller and can optionally traverse the delegation chain.
  • Encryption and audience restriction can be tied down

Most samples out there (including the SDK sample) use the CreateChannelActingAs extension method from WIF to request ActAs tokens. This method builds on top of the WCF binding configuration which may not always be suitable for your situation.

You can also use the WSTrustChannel to request ActAs tokens. This allows direct and programmatic control over bindings and configuration and is my preferred approach.

The below method requests an ActAs token based on a bootstrap token. The returned token can then directly be used with the CreateChannelWithIssued token extension method.

private SecurityToken GetActAsToken(SecurityToken bootstrapToken)
{
   
var factory = new WSTrustChannelFactory
(
       
new UserNameWSTrustBinding(SecurityMode
.TransportWithMessageCredential),
       
new EndpointAddress
(_stsAddress));
    factory.TrustVersion =
TrustVersion
.WSTrust13;

    factory.Credentials.UserName.UserName =
"middletier"
;
    factory.Credentials.UserName.Password =
"abc!123"
;


   
var rst = new RequestSecurityToken
    {
        AppliesTo =
new EndpointAddress
(_serviceAddress),

        RequestType =
RequestTypes
.Issue,
        KeyType =
KeyTypes
.Symmetric,
        ActAs =
new SecurityTokenElement
(bootstrapToken)
    };

   
var
channel = factory.CreateChannel();
   
var
delegationToken = channel.Issue(rst);

   
return delegationToken;
}

 

HTH

This entry was posted in IdentityModel. Bookmark the permalink.

20 Responses to Requesting Delegation (ActAs) Tokens using WSTrustChannel (as opposed to Configuration Madness)

  1. scott mcfadden says:

    In WIF 1.0, we have a config settings for saveBootStrapToken

    Where has the saveBootstrapTokens setting gone in 4.5?

  2. Morad Aktam says:

    I am using similair code to get an actas token from ADFS 2.0 in order to use it for accessing a WebApi. How even I get an exception saying that no private Key is present in the X509Certificate:

    System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +14799942
    System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) +622
    System.ServiceModel.Security.IWSTrustContract.Issue(Message message) +0
    System.ServiceModel.Security.WSTrustChannel.Issue(RequestSecurityToken rst, RequestSecurityTokenResponse& rstr) +66
    System.ServiceModel.Security.WSTrustChannel.Issue(RequestSecurityToken rst) +37
    CS.Intern.HulpModule.Helpers.moduledebugger.GetActAsToken(SecurityToken bootstrapToken) +963
    CS.Intern.HulpModule.Helpers.moduledebugger.handleSecurityToken(Object sender, EventArgs e) +281
    Microsoft.SharePoint.IdentityModel.SPFederationAuthenticationModule.OnSignedIn(EventArgs eventArgs) +171
    Microsoft.IdentityModel.Web.WSFederationAuthenticationModule.SignInWithResponseMessage(HttpRequest request) +802
    Microsoft.IdentityModel.Web.WSFederationAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs args) +521
    Microsoft.SharePoint.IdentityModel.SPFederationAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs eventArgs) +205
    System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +92
    System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +165

  3. oneil says:

    Hi I am using Thinktecture STS to validate web user using wstrust. I am using wstrust because the website needs our own login page. So webserver is passing credentials to STS using wstrust protocol. It works fine the only error I have is identity.BootstrapContext is null. I want to further use the bootstrap token to request for ACT as token (as mentioned in above example).

    In my config I have savebootsrapcontext = true.

    Any idea why bootsrapcontext is null?

    • You need to set the bootstrap context manually – can’t remember how that works – but probably somewhere on either ClaimsIdentity or the session security token.

      • oneil says:

        Hi thanks for repoly.

        I did following

        currentIdentity.boostrapcontext = new BootstrapContext(jwtToken.RawData);

        but still the securitytoken is null

        {System.IdentityModel.Tokens.BootstrapContext}
        SecurityToken: null
        SecurityTokenHandler: null
        Token: “xxxxxx”
        TokenBytes: null

  4. Thats OK – you need to read the token back with the handler.

    • oneil says:

      That works perfect. I get security token from bootstrapcontext
      But now when generating a actas token request using above code I am getting error

      {System.InvalidOperationException: ID4010: A SecurityTokenHandler is not registered for token type ‘System.IdentityModel.Tokens.JwtSecurityToken’.

      Any config entries I am missing on website side or sts side?

      I have following in sts web.config:

  5. yea – don’t know – would need to try myself.

  6. oneil says:

    yeah i have that handler mentioned under “ActAs” like this

    type=”System.IdentityModel.Tokens.JwtSecurityTokenHandler, System.IdentityModel.Tokens.Jwt, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″

  7. Christian says:

    Hi Dominick

    Love your tutorials! I have an ASP.net Web API (middle tier) that authenticates users via an external ADFS. The middle tier has successfully retrieved a new security token by using the bootstrap token to perform an ActAs request. I am able to call the external back-end service with this token so every thing is fine.

    I obviously want to cache this newly requested security token, but I am very confused by where to do that and how. I don not think that the token should be stored in a cookie because this is for the middle tier only. Is it possible to cache the token in a “per-user session” or similar using the the built-in Federation Authentication methods, e.g. when the WSFederationAuthenticationModule_SignedIn event is triggered?

    Thanks in advance! :)
    Christian

  8. valentinortiz says:

    I’m getting a “generic XML” token and it only contains a reference to the Assertion but the asertion does not exists and neither the claims. I only get something like this: “ExternalTokenReference = {SamlAssertionKeyIdentifierClause(AssertionId = ‘_7c8b3c48-dd65-47ca-892d-46f5404c13a1’)}”. I’m using ADFS on Windows Server 2016. Any idea why STS is sending the token without the original claims?. I’m using your exact same rst parameters.

    • valentinortiz says:

      I found this reference from the book “Programming Windows Identity Foundation” that states the following:
      “The STS then goes ahead and signs the bits with its own private triangle key and encrypts the token with the RP’s round public key. The encryption makes the token opaque to everybody but the RP”. So in theory, the WS Consumer will never see the claims because only the WS Provider has the key to decrypt the token.

      Now my question is: Is there a way to disable encryption at message level and use only digital signatures?. That way the WS Consumer should be able to see the security token contents (including the claims), but I haven’t find a way to do so.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s