예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }