Search code examples
oauthrestsharpkhan-academy

Get user authentication using browser with Restsharp and OAUTH


The API of Khan Academy requires that the user will authenticate using his/her web browser. Here is Khan Academy's authentication manual

When trying to getting a request token, the request fails because the user himself did not approve it.

Here's my code:

string _server_url = "http://www.khanacademy.org";
string _consumer_key = "key";
string _consumer_secret = "secret";

//Request token
RestClient client = new RestClient();
client.BaseUrl = _server_url;
client.Authenticator = OAuth1Authenticator.ForRequestToken(_consumer_key, _consumer_secret);
RestRequest request = new RestRequest("api/auth/request_token", Method.GET);

var response = client.Execute(request);

var qs = HttpUtility.ParseQueryString(response.Content);
var oauth_token = qs["oauth_token"];
var oauth_token_secret = qs["oauth_token_secret"];

both oauth_token and oauth_token_secret are returned as null.

Is there any way to start the browser and ask the user to authenticate while using RestSharp?


Solution

  • Eventually I used a WebBrowser object in WinForms to solve this issue. Here's my code:

        public Authenticate()
        {
            InitializeComponent();
            //Request token
            Client.BaseUrl = Server_url;
            Client.Authenticator = OAuth1Authenticator.ForRequestToken(Consumer_key, Consumer_secret);
            RestRequest request = new RestRequest("api/auth/request_token", Method.GET);
    
    
            //request response
            var response = Client.Execute(request);
    
            //pull out the google url out of the response (which is a HTML page)
            int index = response.Content.IndexOf("/api/auth/request_token_callback/google/") + "/api/auth/request_token_callback/google/".Length;
            string key = response.Content.Substring(index, 10);
            if (response.StatusDescription.Equals("OK"))
            {
                var url = response.ResponseUri.AbsoluteUri;
                webBrowser.Navigate(new Uri(url));
            }
            else
                throw new Exception();
        }
    

    And when the user finishes to authenticate through Google/Facebook/Email, I can pull out his oauth_token and oauth_token_secret using webBrowser.Url:

                string source = webBrowser.Url.ToString();
                var qs = HttpUtility.ParseQueryString(source);
                var oauth_token_secret = HttpUtility.ParseQueryString(source).Get(0);
    
                var oauth_token = qs["oauth_token"];
                Client.BaseUrl = Server_url;
                Client.Authenticator = OAuth1Authenticator.ForAccessToken(Consumer_key, Consumer_secret, oauth_token, oauth_token_secret);
    

    By the way, there's a bug with HttpUtility.ParseQueryString(source). see this post for a solution (that's also implemented here)