MSDN > 論壇首頁 > Live Framework > Live ID with Active STS / WS-Trust
發問發問
 

已答覆Live ID with Active STS / WS-Trust

  • Sunday, 28 June, 2009 4:12Dean Ward 使用者勳章使用者勳章使用者勳章使用者勳章使用者勳章
     包含代碼
    Hi all,

    I'm attempting to use Geneva's WSTrustClient to retrieve a token from Live ID that is subsequently passed to a WCF service hosted in Azure, using .NET Access Control Services as its STS.

    Whenever I execute an Issue request from WSTrustClient to the endpoint at https://dev.login.live.com/wstlogin.srf, I get an Internal Server Error 500 with no other information

    Looking at the outgoing traffic using fiddler shows the following SOAP envelope (names changed to protect the innocent!):

    <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
      <s:Header>
        <a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>
        <ClientInfo xmlns="http://schemas.microsoft.com/wlid">
          <ApplicationID>1234567890</ApplicationID>
        </ClientInfo>
        <a:MessageID>urn:uuid:dbc9fbc5-e051-41e4-8700-037cb6809de9</a:MessageID>
        <a:ReplyTo>
          <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
        </a:ReplyTo>
        <a:To s:mustUnderstand="1">https://dev.login.live.com/wstlogin.srf</a:To>
        <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
          <u:Timestamp u:Id="_0">
            <u:Created>2009-06-28T03:53:28.052Z</u:Created>
            <u:Expires>2009-06-28T03:58:28.052Z</u:Expires>
          </u:Timestamp>
          <o:UsernameToken u:Id="uuid-617af7d6-fd7e-496c-8828-e32323c58018-1">
            <o:Username>username@domain.com</o:Username>
            <o:Password o:Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</o:Password>
          </o:UsernameToken>
        </o:Security>
      </s:Header>
      <s:Body>
        <t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
          <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
            <a:EndpointReference>
              <a:Address>http://solutionname.accesscontrol.windows.net/issued_for_certificate</a:Address>
            </a:EndpointReference>
          </wsp:AppliesTo>
          <t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
        </t:RequestSecurityToken>
      </s:Body>
    </s:Envelope>
    

    The ApplicationID was retrieved from the project settings in the Azure development portal. Am I doing something wrong here? It looks as though it should work?! The code I'm using is:
    class Program
    {
        static void Main(string[] args)
        {
            SecurityToken securityToken;
            using (WSTrustClient wsTrustClient = CreateWSTrustClient())
            {
                wsTrustClient.ClientCredentials.UserName.UserName = "username@domain.com";
                wsTrustClient.ClientCredentials.UserName.Password = "password";
                RequestSecurityToken requestToken = new RequestSecurityToken(RequestTypeConstants.Issue);
                requestToken.AppliesTo = new EndpointAddress("http://solutionname.accesscontrol.windows.net/issued_for_certificate");
                using (new OperationContextScope(wsTrustClient.InnerChannel))
                {
                    OperationContext.Current.OutgoingMessageHeaders.Add(
                        new LiveClientInfoHeader
                        {
                            ApplicationId = "1234567890"
                        });
    
                    RequestSecurityTokenResponse requestTokenResponse;
                    securityToken = wsTrustClient.Issue(requestToken, out requestTokenResponse);
                }
            }
        }
    
        private static WSTrustClient CreateWSTrustClient()
        {
            WSHttpBinding wsHttpBinding = new WSHttpBinding(SecurityMode.TransportWithMessageCredential);
            wsHttpBinding.Security.Message.EstablishSecurityContext = false;
            wsHttpBinding.Security.Message.NegotiateServiceCredential = false;
            wsHttpBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
            wsHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
    
            return new WSTrustClient(
                wsHttpBinding,
                new EndpointAddress("https://dev.login.live.com/wstlogin.srf"),
                TrustVersion.WSTrustFeb2005,
                new ClientCredentials());
        }
    }
    
    private class LiveClientInfoHeader : MessageHeader
    {
        public override string Name
        {
            get { return "ClientInfo"; }
        }
    
        public override string Namespace
        {
            get { return "http://schemas.microsoft.com/wlid"; }
        }
    
        public string ApplicationId
        {
            get;
            set;
        }
    
        protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
        {
            writer.WriteStartElement("ApplicationID", this.Namespace);
            writer.WriteValue(this.ApplicationId);
            writer.WriteEndElement();
        }
    }
    
    Any help would be greatly appreciated!

    Thanks & Regards,

    Dean Ward
    Developer
    iPrinciples Ltd

解答

  • Sunday, 28 June, 2009 19:30Dean Ward 使用者勳章使用者勳章使用者勳章使用者勳章使用者勳章
     已答覆
    Turns out that the SOAP envelope is in fact valid - if I send directly using WebRequest / WebResponse it works just fine. Appears that WSTrustClient is forcing the HttpWebRequest.SendChunked property to true causing the HTTP request to be sent using chunked encoding! This doesn't work so well with the Live ID STS.

    One for the Geneva team methinks!

    Cheers,

    Dean

    UPDATE: After a brief play with Reflector it seems that chunking is not easy to switch off - it's quite deep down in the plumbing and required for any HTTPS bindings! Hacky workaround for the moment is to use a custom Binding / ChannelFactory / IRequestChannel implementation that eats any GetProperty<T> requests for IChannelBindingProvider. I have no idea what knock-on effects it might have, but I can now successfully obtain tokens from the Live ID WS-Trust endpoint!
    • 已標示為解答Dean Ward Sunday, 28 June, 2009 19:30
    •  

所有回覆

  • Sunday, 28 June, 2009 19:30Dean Ward 使用者勳章使用者勳章使用者勳章使用者勳章使用者勳章
     已答覆
    Turns out that the SOAP envelope is in fact valid - if I send directly using WebRequest / WebResponse it works just fine. Appears that WSTrustClient is forcing the HttpWebRequest.SendChunked property to true causing the HTTP request to be sent using chunked encoding! This doesn't work so well with the Live ID STS.

    One for the Geneva team methinks!

    Cheers,

    Dean

    UPDATE: After a brief play with Reflector it seems that chunking is not easy to switch off - it's quite deep down in the plumbing and required for any HTTPS bindings! Hacky workaround for the moment is to use a custom Binding / ChannelFactory / IRequestChannel implementation that eats any GetProperty<T> requests for IChannelBindingProvider. I have no idea what knock-on effects it might have, but I can now successfully obtain tokens from the Live ID WS-Trust endpoint!
    • 已標示為解答Dean Ward Sunday, 28 June, 2009 19:30
    •  
  • Wednesday, 25 November, 2009 15:51greatwhitenorth 使用者勳章使用者勳章使用者勳章使用者勳章使用者勳章
     
    Hey Dean,

    Ok, I stuck my toe in and little did I realize just where this was going!  All I wanted to do is use the Live ID STS to authenticate a user from my SilverLight application.  On a vertical learning curve right now, purely in the design stage right now,  but have things changed in this scenario after the PDC 09?  Any thoughts on authorization technique after authentication?

    Regards,
    Richard