private void GetTickets(RequestSecurityTokenResponseType[] result, SecurityTokenService securService, MSNTicket msnticket) { if (securService.pp != null) { if (securService.pp.credProperties != null) { foreach (credPropertyType credproperty in securService.pp.credProperties) { if (credproperty.Name == "MainBrandID") { msnticket.MainBrandID = credproperty.Value; } if (credproperty.Name == "CID" && !String.IsNullOrEmpty(credproperty.Value)) { msnticket.OwnerCID = long.Parse(credproperty.Value, NumberStyles.HexNumber); } } } if (securService.pp.extProperties != null) { foreach (extPropertyType extproperty in securService.pp.extProperties) { if (extproperty.Name == "CID" && !String.IsNullOrEmpty(extproperty.Value)) { msnticket.OwnerCID = long.Parse(extproperty.Value, NumberStyles.HexNumber); } } } } foreach (RequestSecurityTokenResponseType token in result) { SSOTicketType ticketype = SSOTicketType.None; switch (token.AppliesTo.EndpointReference.Address.Value) { case "contacts.msn.com": ticketype = SSOTicketType.Contact; break; case "messengerclear.live.com": ticketype = SSOTicketType.Clear; break; case "storage.msn.com": ticketype = SSOTicketType.Storage; break; case "sup.live.com": ticketype = SSOTicketType.WhatsUp; break; case "directory.services.live.com": ticketype = SSOTicketType.Directory; break; case "rpstauth.live.com": ticketype = SSOTicketType.RPST; break; } SSOTicket ssoticket = new SSOTicket(ticketype); if (token.AppliesTo != null) ssoticket.Domain = token.AppliesTo.EndpointReference.Address.Value; if (token.RequestedSecurityToken.BinarySecurityToken != null) ssoticket.Ticket = token.RequestedSecurityToken.BinarySecurityToken.Value; if (token.RequestedProofToken != null && token.RequestedProofToken.BinarySecret != null) { ssoticket.BinarySecret = token.RequestedProofToken.BinarySecret.Value; } if (token.Lifetime != null) { ssoticket.Created = XmlConvert.ToDateTime(token.Lifetime.Created.Value, "yyyy-MM-ddTHH:mm:ssZ"); ssoticket.Expires = XmlConvert.ToDateTime(token.Lifetime.Expires.Value, "yyyy-MM-ddTHH:mm:ssZ"); } lock (msnticket.SSOTickets) { msnticket.SSOTickets[ticketype] = ssoticket; } } }
private bool ProcessError(SecurityTokenService secureService, SoapException exception, MSNTicket msnticket, EventHandler onSuccess, EventHandler<ExceptionEventArgs> onError) { string errFedDirectLogin = @"Direct login to WLID is not allowed for this federated namespace"; if (exception == null) return false; if (secureService.pp == null) return false; uint errorCode = uint.Parse(secureService.pp.reqstatus.Remove(0, "0x".Length), NumberStyles.HexNumber); if (errorCode == 0x800488ee) { if (exception.Detail.InnerXml.IndexOf(errFedDirectLogin) != -1) { string fedLoginURL = string.Empty; string fedAuthURL = string.Empty; string fedBrandName = string.Empty; foreach (extPropertyType extProperty in secureService.pp.extProperties) { switch (extProperty.Name) { case "STSAuthURL": //STS means Security Token Service. fedLoginURL = extProperty.Value; break; case "AuthURL": fedAuthURL = extProperty.Value; break; case "AllowFedUsersWLIDSignIn": //Is it allow to login by MSN ? Not all feduser can log in with a WLM client. if (!bool.Parse(extProperty.Value)) return false; break; case "FederationBrandName": fedBrandName = extProperty.Value; break; case "IsFederatedNS": if (!bool.Parse(extProperty.Value)) return false; break; } } if (fedLoginURL == string.Empty) return false; Uri fedLoginURI = new Uri(fedLoginURL); string strFedLoginURI = fedLoginURI.Scheme.ToUpperInvariant() + "://" + fedLoginURI.Host + (fedLoginURI.Scheme.ToLowerInvariant() == "https" ? ":443" : string.Empty) + "/" + fedLoginURI.PathAndQuery; SecurityTokenService fedSecureService = CreateSecurityTokenService(@"http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue", strFedLoginURI); fedSecureService.Url = fedLoginURL; RequestSecurityTokenType token = new RequestSecurityTokenType(); token.Id = "RST0"; token.RequestType = RequestTypeOpenEnum.httpschemasxmlsoaporgws200502trustIssue; AppliesTo appliesTo = new AppliesTo(); appliesTo.EndpointReference = new EndpointReferenceType(); appliesTo.EndpointReference.Address = new AttributedURIType(); appliesTo.EndpointReference.Address.Value = strFedLoginURI.Remove(0, @"HTTPS://".Length); token.AppliesTo = appliesTo; RequestSecurityTokenResponseType response = null; if (onSuccess != null && onError != null) { //Async request. fedSecureService.RequestSecurityTokenCompleted += delegate(object sender, RequestSecurityTokenCompletedEventArgs e) { if (!e.Cancelled) { if (e.Error != null) { MSNPSharpException sexp = new MSNPSharpException(e.Error.Message + ". See innerexception for detail.", e.Error); onError(this, new ExceptionEventArgs(sexp)); return; } response = e.Result; if (response.RequestedSecurityToken == null || response.RequestedSecurityToken.Assertion == null) return; AssertionType assertion = response.RequestedSecurityToken.Assertion; secureService = CreateSecurityTokenService(@"http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue", @"HTTPS://login.live.com:443//RST2.srf"); secureService.Security.Assertion = assertion; if (response.Lifetime != null) { secureService.Security.Timestamp.Created = response.Lifetime.Created; secureService.Security.Timestamp.Expires = response.Lifetime.Expires; } Authenticate(secureService, msnticket, onSuccess, onError); } }; fedSecureService.RequestSecurityTokenAsync(token, new object()); return true; } else { //Sync request. try { response = fedSecureService.RequestSecurityToken(token); } catch (Exception ex) { MSNPSharpException sexp = new MSNPSharpException(ex.Message + ". See innerexception for detail.", ex); throw sexp; } if (response.RequestedSecurityToken == null) return false; if (response.RequestedSecurityToken.Assertion == null) return false; AssertionType assertion = response.RequestedSecurityToken.Assertion; secureService = CreateSecurityTokenService(@"http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue", @"HTTPS://login.live.com:443//RST2.srf"); secureService.Security.Assertion = assertion; Authenticate(secureService, msnticket, onSuccess, onError); return true; } } } return false; }
private void Authenticate(SecurityTokenService securService, MSNTicket msnticket, EventHandler onSuccess, EventHandler<ExceptionEventArgs> onError) { if (user.Split('@').Length > 1) { if (user.Split('@')[1].ToLower(CultureInfo.InvariantCulture) == "msn.com") { securService.Url = @"https://msnia.login.live.com/RST2.srf"; } } else { AuthenticationException authenticationException = new AuthenticationException("Invalid account. The account must contain @ char"); if (onError != null && onSuccess != null) onError(this, new ExceptionEventArgs(authenticationException)); else throw authenticationException; } RequestMultipleSecurityTokensType mulToken = new RequestMultipleSecurityTokensType(); mulToken.Id = "RSTS"; mulToken.RequestSecurityToken = auths.ToArray(); // ASYNC if (onSuccess != null && onError != null) { securService.RequestMultipleSecurityTokensCompleted += delegate(object sender, RequestMultipleSecurityTokensCompletedEventArgs e) { if (!e.Cancelled) { if (e.Error != null) { SoapException sex = e.Error as SoapException; if (sex != null && ProcessError(securService, sex, msnticket, onSuccess, onError)) return; MSNPSharpException sexp = new MSNPSharpException(e.Error.Message + ". See innerexception for detail.", e.Error); if (securService.pp != null) sexp.Data["Code"] = securService.pp.reqstatus; //Error code onError(this, new ExceptionEventArgs(sexp)); } else if (e.Result != null) { GetTickets(e.Result, securService, msnticket); onSuccess(this, EventArgs.Empty); } else { // Is this possible? Answer: No. } } }; securService.RequestMultipleSecurityTokensAsync(mulToken, new object()); } else { try { RequestSecurityTokenResponseType[] result = securService.RequestMultipleSecurityTokens(mulToken); if (result != null) { GetTickets(result, securService, msnticket); } } catch (SoapException sex) { if (ProcessError(securService, sex, msnticket, onSuccess, onError)) return; throw sex; } catch (Exception ex) { MSNPSharpException sexp = new MSNPSharpException(ex.Message + ". See innerexception for detail.", ex); if (securService.pp != null) sexp.Data["Code"] = securService.pp.reqstatus; //Error code throw sexp; } } }