locked
Return GenericXmlSecurityToken from a web service (or extract from RSTR) RRS feed

  • Question

  • I have an environment with passive and active scenarios, using ADFS as a Federating-STS and a customized StarterSTS as an IP. Most scenarios are working fine.

    I have one scenario where I wish to return a SecurityToken (or GenericXmlSecurityToken) from a web service so that a partner application can call my protected Wcf services using that token (and without having to know about ADFS or StarterSTS).

    The partner application is the active client in this scenario. It doesn't need to know anything about the contents of the token, it simply needs to pass it on to my service. I get the token with ChannelFactory.....Issue(rst, out rstr). All works well if I use this token just after it is issued.

    But, I haven't found a way to provide that token via a web service to the partner application. I see dozens of posts asking about serializing/deserializing a GenericXmlSecurityToken, with no usable responses.

    I also understand that the RSTR is supposed to contain the SecurityToken within. I could easily serialize the RSTR and pass it across the wire, but I've seen no way to extract the SecurityToken from the RSTR once it gets to the client.

    I've tried New GenericXmlSecurityToken(rstr.RequestedSecurityToken.SecurityTokenXml, null, ...) but the resulting token does not contain a SecurityKey, while the token produced by ChannelFactory.....Issue(rst, out rstr) does contain one InMemorySymmetricSecurityKey. I don't see anything like this SecurityKey in the RSTR, so don't understand how it can be said that the RSTR "contains the SecurityToken".

    It seems like this should be very simple and not require any handlers, keys or anything else on the client side (especially since I see comments that such tokens are handled as an "opaque structure" on the client side).

    In case it matters, I'm obtaining the token with the following code:

    			var idpBinding = new UserNameWSTrustBinding
    			         	{
    			         		SecurityMode = SecurityMode.TransportWithMessageCredential
    			         	};
    			var adfsBinding = new IssuedTokenWSTrustBinding(idpBinding, _idpEndpointAddress)
    			         	{
    			         		SecurityMode = SecurityMode.TransportWithMessageCredential,
    			         	};
    			var adfsChannelFactory = new WSTrustChannelFactory(adfsBinding, _adfsEndpointAddress);
    			adfsChannelFactory.Credentials.UserName.UserName = "test";
    			adfsChannelFactory.Credentials.UserName.Password = "p@ssword";
    			adfsChannelFactory.ConfigureChannelFactory();
    			var adfsChannel = (WSTrustChannel)adfsChannelFactory.CreateChannel();
    			var adfsRst = new RequestSecurityToken
    			       	{
    			       		AppliesTo = _serviceEndpointIdentifier,
    			       		RequestType = WSTrust13Constants.RequestTypes.Issue,
    			       		TokenType = Microsoft.IdentityModel.Tokens.SecurityTokenTypes.Saml2TokenProfile11,
    								//KeyType = KeyTypes.Bearer,
    			       	};
    
    			RequestSecurityTokenResponse rstr;
    			SecurityToken adfsToken = adfsChannel.Issue(adfsRst, out rstr);
    			adfsChannel.Close();
    
    			return adfsToken;
    
    
    Wednesday, October 13, 2010 12:15 AM

Answers

  • I think I got it. Hope this helps someone else.

    		private static GenericXmlSecurityToken GetTokenFromSerializedRstr(string serializedRstr)
    		{
    			RequestSecurityTokenResponse rstr = new WSFederationSerializer().CreateResponse(
    				new SignInResponseMessage(new Uri("http://foo.com"), serializedRstr),
    				new WSTrustSerializationContext());
    			return new GenericXmlSecurityToken(
    				rstr.RequestedSecurityToken.SecurityTokenXml,
    				new BinarySecretSecurityToken(rstr.RequestedProofToken.ProtectedKey.GetKeyBytes()),
    				DateTime.MinValue,
    				DateTime.MinValue,
    				rstr.RequestedAttachedReference,
    				rstr.RequestedUnattachedReference,
    				null);
    		}
    
    
    • Marked as answer by BillOverman Thursday, October 14, 2010 6:50 PM
    Thursday, October 14, 2010 6:50 PM

All replies

  • I think I got it. Hope this helps someone else.

    		private static GenericXmlSecurityToken GetTokenFromSerializedRstr(string serializedRstr)
    		{
    			RequestSecurityTokenResponse rstr = new WSFederationSerializer().CreateResponse(
    				new SignInResponseMessage(new Uri("http://foo.com"), serializedRstr),
    				new WSTrustSerializationContext());
    			return new GenericXmlSecurityToken(
    				rstr.RequestedSecurityToken.SecurityTokenXml,
    				new BinarySecretSecurityToken(rstr.RequestedProofToken.ProtectedKey.GetKeyBytes()),
    				DateTime.MinValue,
    				DateTime.MinValue,
    				rstr.RequestedAttachedReference,
    				rstr.RequestedUnattachedReference,
    				null);
    		}
    
    
    • Marked as answer by BillOverman Thursday, October 14, 2010 6:50 PM
    Thursday, October 14, 2010 6:50 PM
  • Just to complete the thought:

    		private static string SerializeRstr(RequestSecurityTokenResponse rstr)
    		{
    			return new WSFederationSerializer().GetResponseAsString(rstr, new WSTrustSerializationContext());
    		}
    
    
    
    Thursday, October 14, 2010 8:36 PM