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
In WIF 1.0, we have a config settings for saveBootStrapToken
Where has the saveBootstrapTokens setting gone in 4.5?
It is now called SaveBootstrapContext.
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
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.
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
Thats OK – you need to read the token back with the handler.
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:
”
“
i have added
type=”System.IdentityModel.Tokens.JwtSecurityTokenHandler, System.IdentityModel.Tokens.Jwt, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″
yea – don’t know – would need to try myself.
do I need to add a section “Securitytokenhandlerconfigration” for validationissuernameregistry in sts webconfig under section “securityTokenHandlers name=”ActAs” “
sorry – can’t remember. You def need the JWT handler under “ActAs”
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″
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
Hey,
you would need to cache it in memory – or some distributed caching system in your backend.
Thanks for the quick reply! Do you have any .NET standard library cache in mind and do you know which event is the most appropriate for adding to the cache.
Thanks
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.
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.