1
votes

I'm working on an application which has to connect to our O365 environment. We are federated with O365, so users access services with their normal network credentials.

The app allows users to connect using username / password or integrated windows authentication when they're connected to the local LAN. The username / password combination part works fine, however when I pass a web request to the ADFS server using default credentials, I get a response from ADFS in the form of a web page which says the web browser doesn't support JavaScript:

<div id="noScript" style="position:static; width:100%; height:100%; z-index:100">
    <h1>JavaScript required</h1>
    <p>JavaScript is required. This web browser does not support JavaScript or JavaScript in this web browser is not enabled.</p>
    <p>To find out if your web browser supports JavaScript or to enable JavaScript, see web browser help.</p>
</div>

I'm not sure why I'm getting this instead of being automatically authenticated. I've included the code for the method below:

    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);
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.adfsIntegratedAuthUrl);
        request.UseDefaultCredentials = true; // use the default credentials so Kerberos can take care of authenticating our request

        // TODO: This fails becuase the request doesn't support JavaScript... Need to find a way around this...
        byte[] responseData = HttpHelper.SendHttpRequest(
            this.adfsIntegratedAuthUrl,
            "GET",
            null,
            "text/html; charset=utf-8",
            request);

        if (responseData != null)
        {
            try
            {
                StreamReader sr = new StreamReader(new MemoryStream(responseData), Encoding.GetEncoding("utf-8"));
                integratedauthresponse = sr.ReadToEnd();
                XPathNavigator nav = new XPathDocument(sr).CreateNavigator();
                XPathNavigator wresult = nav.SelectSingleNode("/html/body/form/input[@name='wresult']");
                if (wresult != null)
                {
                    responsedata = true;
                    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... *sob*
            }
        }
        methodused = "Windows Authentication";
        return samlAssertion;
    }

Has anyone had a similar experience? If so, how did you work around it? I don't think I can spoof being JavaScript compatible, but it shouldn't matter.

1
I don't see any problem with authentication. Your message is JavaScript is required. This web browser does not support JavaScript - Eser
Hi Eser, thanks for that. Unfortunately I can't really use a web browser control on a form because of the what the application needs to do. If there's no way of coding around the JavaScript issue (i.e. crafting the web request in such a way as to tell the server I'm not bothered about JavaScript) I'm happy to entertain config changes to the ADFS box, as long as they don't break forms-base authentication for off-network users. - LordPupazz
Open fiddler. Watch the requests/responses while you're using a real browser and try to simulate them. - Eser

1 Answers

0
votes

I was able to get a token from ADFS using integrated authentication using the code below:

    public GenericXmlSecurityToken GetToken()
    {
        WS2007HttpBinding binding = new WS2007HttpBinding(SecurityMode.Transport);
        binding.Security.Message.EstablishSecurityContext = false;
        binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
        WSTrustChannelFactory factory = new WSTrustChannelFactory((binding), new EndpointAddress(stsEndpoint));
        factory.TrustVersion = TrustVersion.WSTrustFeb2005;
        factory.Credentials.SupportInteractive = false;
        var rst = new RequestSecurityToken
        {
            RequestType = RequestTypes.Issue,
            AppliesTo = new EndpointReference(realm),
            KeyType = KeyTypes.Bearer
        };
        IWSTrustChannelContract channel = factory.CreateChannel();
        return channel.Issue(rst) as GenericXmlSecurityToken;
    }