private Uri GetAdfsAuthUrl() { Uri corpAdfsProxyUrl = null; Uri msoHrdUri = new Uri(msoHrdUrl); HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(msoHrdUri); // make a post request with the user's login name to // MSO HRD (Home Realm Discovery) service so it can find // out the url of the federation service (corporate ADFS) // responsible for authenticating the user byte[] response = HttpHelper.SendHttpRequest( new Uri(msoHrdUrl), "POST", Encoding.UTF8.GetBytes(String.Format("handler=1&login={0}", this.username)), // pass in the login name in the body of the form "application/x-www-form-urlencoded", request).Response; STSInfo info = Deserialize <STSInfo>(response); if (info != null && !String.IsNullOrEmpty(info.AuthURL)) { corpAdfsProxyUrl = new Uri(info.AuthURL); } return(corpAdfsProxyUrl); }
private SPOAuthCookies GetSPOAuthCookies(SamlSecurityToken stsToken) { // signs in to SPO with the security token issued by MSO STS and gets the fed auth cookies // the fed auth cookie needs to be attached to all SPO REST services requests SPOAuthCookies spoAuthCookies = new SPOAuthCookies(); Uri siteUri = this.spSiteUrl; Uri wsSigninUrl = new Uri(String.Format("{0}://{1}/{2}", siteUri.Scheme, siteUri.Authority, spowssigninUri)); HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(wsSigninUrl); request.CookieContainer = new CookieContainer(); byte[] responseData = HttpHelper.SendHttpRequest( wsSigninUrl, "POST", stsToken.Token, "application/x-www-form-urlencoded", request, null).Response; if (request != null && responseData != null) { using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { spoAuthCookies.FedAuth = (response.Cookies["FedAuth"] != null) ? response.Cookies["FedAuth"].Value : null; spoAuthCookies.RtFA = (response.Cookies["rtFA"] != null) ? response.Cookies["rtFA"].Value : null; spoAuthCookies.Expires = stsToken.Expires; spoAuthCookies.Host = wsSigninUrl; } } return(spoAuthCookies); }
private string GetAdfsSAMLTokenWinAuth() { // makes a seurity token request to the corporate ADFS proxy integrated auth endpoint. // If the user is logged on to a machine joined to the corporate domain with her Windows credentials and connected // to the corporate network Kerberos automatically takes care of authenticating the security token // request to ADFS. // The logon token is used to talk to MSO STS to get an O365 service token that can then be used to sign into SPO. string samlAssertion = null; HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(this.adfsIntegratedAuthUrl); request.UseDefaultCredentials = true; // use the default credentials so Kerberos can take care of authenticating our request byte[] responseData = HttpHelper.SendHttpRequest( this.adfsIntegratedAuthUrl, "GET", null, "text/html; charset=utf-8", request).Response; if (responseData != null) { try { StreamReader sr = new StreamReader(new MemoryStream(responseData), Encoding.GetEncoding("utf-8")); XPathNavigator nav = new XPathDocument(sr).CreateNavigator(); XPathNavigator wresult = nav.SelectSingleNode("/html/body/form/input[@name='wresult']"); if (wresult != null) { string RequestSecurityTokenResponseText = wresult.GetAttribute("value", ""); sr = new StreamReader(new MemoryStream(Encoding.UTF8.GetBytes(RequestSecurityTokenResponseText))); nav = new XPathDocument(sr).CreateNavigator(); XmlNamespaceManager nsMgr = new XmlNamespaceManager(nav.NameTable); nsMgr.AddNamespace("t", "http://schemas.xmlsoap.org/ws/2005/02/trust"); XPathNavigator requestedSecurityToken = nav.SelectSingleNode("//t:RequestedSecurityToken", nsMgr); // Ensure whitespace is reserved XmlDocument doc = new XmlDocument(); doc.LoadXml(requestedSecurityToken.InnerXml); doc.PreserveWhitespace = true; samlAssertion = doc.InnerXml; } } catch { // we failed to sign the user using integrated Windows Auth } } return(samlAssertion); }
private string GetAdfsSAMLTokenUsernamePassword() { // makes a seurity token request to the corporate ADFS proxy usernamemixed endpoint using // the user's corporate credentials. The logon token is used to talk to MSO STS to get // an O365 service token that can then be used to sign into SPO. string samlAssertion = null; // the corporate ADFS proxy endpoint that issues SAML seurity tokens given username/password credentials string stsUsernameMixedUrl = String.Format("https://{0}/adfs/services/trust/2005/usernamemixed/", adfsAuthUrl.Host); // generate the WS-Trust security token request SOAP message passing in the user's corporate credentials // and the site we want access to. We send the token request to the corporate ADFS proxy usernamemixed endpoint. byte[] requestBody = Encoding.UTF8.GetBytes(ParameterizeSoapRequestTokenMsgWithUsernamePassword( "urn:federation:MicrosoftOnline", // we are requesting a logon token to talk to the Microsoft Federation Gateway this.username, this.password, stsUsernameMixedUrl)); try { Uri stsUrl = new Uri(stsUsernameMixedUrl); HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(stsUrl); byte[] responseData = HttpHelper.SendHttpRequest( stsUrl, "POST", requestBody, "application/soap+xml; charset=utf-8", request, null).Response; if (responseData != null) { StreamReader sr = new StreamReader(new MemoryStream(responseData), Encoding.GetEncoding("utf-8")); XPathNavigator nav = new XPathDocument(sr).CreateNavigator(); XmlNamespaceManager nsMgr = new XmlNamespaceManager(nav.NameTable); nsMgr.AddNamespace("t", "http://schemas.xmlsoap.org/ws/2005/02/trust"); XPathNavigator requestedSecurityToken = nav.SelectSingleNode("//t:RequestedSecurityToken", nsMgr); // Ensure whitespace is reserved XmlDocument doc = new XmlDocument(); doc.LoadXml(requestedSecurityToken.InnerXml); doc.PreserveWhitespace = true; samlAssertion = doc.InnerXml; } } catch { // we failed to sign the user using corporate credentials } return(samlAssertion); }
private SamlSecurityToken GetMsoStsSAMLToken() { // Makes a request that conforms with the WS-Trust standard to // Microsoft Online Services Security Token Service to get a SAML // security token back so we can then use it to sign the user to SPO SamlSecurityToken samlST = new SamlSecurityToken(); byte[] saml11RTBytes = null; string logonToken = null; // find out whether the user's domain is a federated domain this.adfsAuthUrl = GetAdfsAuthUrl(); // get logon token using windows integrated auth when the user is connected to the corporate network if (this.adfsAuthUrl != null && this.useIntegratedWindowsAuth) { UriBuilder ub = new UriBuilder(); ub.Scheme = this.adfsAuthUrl.Scheme; ub.Host = this.adfsAuthUrl.Host; ub.Path = string.Format("{0}auth/integrated/", this.adfsAuthUrl.LocalPath); // specify in the query string we want a logon token to present to the Microsoft Federation Gateway // for the corresponding user ub.Query = String.Format("{0}&wa=wsignin1.0&wtrealm=urn:federation:MicrosoftOnline", this.adfsAuthUrl.Query.Remove(0, 1)). Replace("&username="******"&username={0}", this.username)); this.adfsIntegratedAuthUrl = ub.Uri; // get the logon token from the corporate ADFS using Windows Integrated Auth logonToken = GetAdfsSAMLTokenWinAuth(); if (!string.IsNullOrEmpty(logonToken)) { // generate the WS-Trust security token request SOAP message passing in the logon token we got from the corporate ADFS // and the site we want access to saml11RTBytes = Encoding.UTF8.GetBytes(ParameterizeSoapRequestTokenMsgWithAssertion( this.spSiteUrl.ToString(), logonToken, msoStsUrl)); } } // get logon token using the user's corporate credentials. Likely when not connected to the corporate network if (logonToken == null && this.adfsAuthUrl != null && !string.IsNullOrEmpty(password)) { logonToken = GetAdfsSAMLTokenUsernamePassword(); // get the logon token from the corporate ADFS proxy usernamemixed enpoint if (logonToken != null) { // generate the WS-Trust security token request SOAP message passing in the logon token we got from the corporate ADFS // and the site we want access to saml11RTBytes = Encoding.UTF8.GetBytes(ParameterizeSoapRequestTokenMsgWithAssertion( this.spSiteUrl.ToString(), logonToken, msoStsUrl)); } } if (logonToken == null && this.adfsAuthUrl == null && !string.IsNullOrEmpty(password)) // login with O365 credentials. Not a federated login. { // generate the WS-Trust security token request SOAP message passing in the user's credentials and the site we want access to saml11RTBytes = Encoding.UTF8.GetBytes(ParameterizeSoapRequestTokenMsgWithUsernamePassword( this.spSiteUrl.ToString(), this.username, this.password, msoStsUrl)); } if (saml11RTBytes != null) { Uri MsoSTSUri = new Uri(msoStsUrl); HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(MsoSTSUri); byte[] responseData = HttpHelper.SendHttpRequest( MsoSTSUri, "POST", saml11RTBytes, "application/soap+xml; charset=utf-8", request, null).Response; StreamReader sr = new StreamReader(new MemoryStream(responseData), Encoding.GetEncoding("utf-8")); XPathNavigator nav = new XPathDocument(sr).CreateNavigator(); XmlNamespaceManager nsMgr = new XmlNamespaceManager(nav.NameTable); nsMgr.AddNamespace("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); XPathNavigator binarySecurityToken = nav.SelectSingleNode("//wsse:BinarySecurityToken", nsMgr); if (binarySecurityToken != null) { string binaryST = binarySecurityToken.InnerXml; nsMgr.AddNamespace("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); XPathNavigator expires = nav.SelectSingleNode("//wsu:Expires", nsMgr); if (!String.IsNullOrEmpty(binarySecurityToken.InnerXml) && !String.IsNullOrEmpty(expires.InnerXml)) { samlST.Token = Encoding.UTF8.GetBytes(binarySecurityToken.InnerXml); samlST.Expires = DateTime.Parse(expires.InnerXml); } } else { // We didn't get security token } } return(samlST); }