Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Login to Box Using a Windows Dialog

5.00/5 (1 vote)
21 Dec 2012CPOL5 min read 23.1K   496  
This article shows how to login to a cloud storage like Box by entering the credentials in a dialog window rather than in a Web page.

Introduction

Many cloud storage providers like www.box.com use an authentication mechanism that directs you to a WEB page to enter your credential. If you develop a Web based application this is a natural way to do that, but in the case of a desktop application or a windows store App you would want to provide your own login screen that would be a windows form if you are writing a desktop application.

I have searched the forums for a solution to that problem but I failed to find an end to end solution. However some posts guided me to the solution I'm presenting in this article.

The method I describe is valid with the version 1 of the Box API. They have just release a V2 where the authentication mechanism is now using OAuth 2.0, but the current mechanism I describe is still valid.

Remark: You will need to register as a developer with Box.com as this code needs an API_KEY that you obtain after registering. This is a free process. This code uses the discontinued free library BoxSync that implements in C# the Box API v1.

WEB form submission with WebClient

My first solution to enter the credentials in a windows dialog was to put a IE control in a dialog box and pass it the URL of the Box login screen. The drawback of that solution is that once the WEB page displays the successful login, you still need to press the OK button of the dialog box.

The support of Box told me that they don't have any API to authenticate a user with its username/password, so I looked for a solution that would be to automate the login by submitting the authentication form from a C# program. After all, a browser is built on top of HTTP protocols that are accessible to a program using classes like WebRequest or WebClient.

I could find some useful posts that demonstrate how to submit a form using the WebClient client but there is more than just passing the data to the submit call, in the case of a real authentication protocol like the one of Box you need to understand exactly what data they submit to the server when you click Login.

The final code to submit the login form to Box is the following.

public bool AuthenticateUser(string ticket, string userName, string password, out string requestToken)
{
    bool authSuccess = false;
    requestToken = string.Empty;
    string url = string.Format("http://www.box.net/api/1.0/auth/{0}", ticket);

    // Use a WebRequest to process the login
    Stream respStream = ExecuteREST_Request(url, Method.GET);
    StreamReader reader = new StreamReader(respStream);

    string responseText = reader.ReadToEnd();

    requestToken = ExtractRequestToken(responseText);

    using (WebClient webClient = new WebClient())
    {
        try
        {
            NameValueCollection formFields = new NameValueCollection();
            formFields.Add("login", userName);
            formFields.Add("password", password);
            formFields.Add("_pw_sql", "");
            formFields.Add("remember_login", "on");
            formFields.Add("__login", "1");
            formFields.Add("dologin", "1");
            formFields.Add("reg_step", "");
            formFields.Add("submit1", "1");
            formFields.Add("folder", "");
            formFields.Add("skip_framework_login", "1");
            formFields.Add("login_or_register_mode", "login");
            formFields.Add("new_login_or_register_mode", "");
            formFields.Add("request_token", requestToken);

            webClient.Proxy = null;
            string actionUrl = string.Format("https://www.box.net/api/1.0/auth/{0}", ticket);
            byte[] result = webClient.UploadValues(actionUrl, METHOD_POST, formFields);
            string htmlText = ASCIIEncoding.ASCII.GetString(result);

            if (CheckAuthenticated(htmlText))
            {
                authSuccess = true;
            }
            else
            {
                requestToken = ExtractRequestToken(htmlText);
                authSuccess = false;
            }
        }
        catch (WebException ex)
        {
            Trace.WriteLine(ex.Message);
        }
    }

    return authSuccess;
}

If you look at this code, and especially at the part that is preparing the parameters for the submit request, you will notice that there are many more parameters than the user name and password.

That's the interesting part of the problem, when you want to submit a particular form using WebClient for instance, you need to know what the submit request contains exactly when you press the submit button!

Analyzing the submit request

The first step you need to do is to analyze the source of the WEB that contains the Login form. From that source you will extract the URL where to post the data. You'll find this URL in the Action of the form. In the case of Box, the URL is the following one.

https://www.box.net/api/1.0/auth/<ticket>

The ticket is an identification string that you get when initializing the authentication process with Box.

Once you have the URL where to submit the form, you need to identify all the parameters that need to be passed with the request. You can identify them by looking at the source of the page but it may not be easy to rebuild the request and in the case of an authentication, only one bit is enough to fail it.

I used a HTTP debugging tool to see the exact request which is sent to the server. The tool I found is Fiddler Web Debugger that you can download on their web page. This tool proved very useful as it is able to monitor an https request which is what I needed to do as the Box login url is on https.

Using Fiddler configured to monitor the https traffic I could see the exact content of the requested submitted to the Box server for the authentication. I could see that there were many other fields than the user/password and one particularly attracted my attention. This field is request_token and its value is a string token that is different for every login.

Fortunately I could easily find in the source of the page where the value was set and it is in a piece of script. I wrote a simple method to extract that value from the login page and used it to build the parameters.

The last step of this authentication method is to check whether the authentication was successful or not. Once again you need to analyze the response from the request submission in order to know the outcome. In the page that is returned when the operation is successful I found the following string that gives me the proper information: api_auth_success.

So when I submit the form I simply check if that string is present in the response page and I can decide if it is successful or not.

Conclusion

This code only works with the Box login form, however you can apply this method to any form that you need to submit by program. There is no simple way to make this code generic because you need to analyze the source code of the form and even if in some cases it could be totally automated, in the case of Box it would be difficult because of that field that is set by the execution of a script. Another limitation of that method is that it depends on the method used by the builders of the page. If they change something in their page, this code won't work any more. So if suddenly the login doesn't work anymore, the chances are high that they would have changed something in the format of the submit request.

Points of Interest

It took me some time to gather all the knowledge to do this simple login window to authenticate to a Box account, so I think that many readers of CodeProject will find this simple code useful.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)