1

I am trying to get OAuth working with the .NET library for Google Data API. Unfortunately, whenever I call GetUnauthorizedRequestToken, I get a 400 Bad Response error. Here is my code...

OAuthParameters parameters = new OAuthParameters() {
    ConsumerKey = DOMAIN_NAME,
    ConsumerSecret = SECRET_KEY,
    Scope = "https://docs.google.com/feeds/",
    Callback = Request.RawUrl,
    SignatureMethod = "HMAC-SHA1"
};

OAuthUtil.GetUnauthorizedRequestToken(parameters);

As far as I know I am correctly following the instructions here: http://code.google.com/apis/gdata/docs/auth/oauth.html

Any help with this problem would be much appreciated!

EDIT: 9/10/2011 11:56 PM PST

First of all, thank you so much for the comments!

So I've fiddled around a bit and got the Unauthorized Request Token working, but OAuth is still not really working... here is a more complete code dump :-\

string token = Request["oauth_token"];
if (!String.IsNullOrEmpty(token)) {
    OAuthParameters tParams = new OAuthParameters() {
        ConsumerKey = DOMAIN_NAME,
        ConsumerSecret = SECRET_KEY,
        Scope = S_SCOPE,
        Callback = S_CALLBACK,
        SignatureMethod = "HMAC-SHA1"
    };
    tParams.Verifier = Request["oauth_verifier"];
    tParams.Token = token;

    try {
        // http://code.google.com/apis/gdata/docs/auth/oauth.html

        // 1. Extract token from the callback URL
        //OAuthUtil.UpdateOAuthParametersFromCallback(Request.Url.Query, parameters);

        // 2. Upgrade to an access token
        OAuthUtil.GetAccessToken(tParams);
        string accessToken = tParams.Token;
        string accessTokenSecret = tParams.TokenSecret;

        Session["sp"] = tParams; // don't worry, we don't even get here yet
        return RedirectToAction("List");
    }
    catch (System.Net.WebException ex) {
        // print out tons of stuff (removed for sanity)
    }
    
    //... and start over again
}


try {
    OAuthParameters parameters = new OAuthParameters() {
        ConsumerKey = DOMAIN_NAME,
        ConsumerSecret = SECRET_KEY,
        Scope = S_SCOPE,
        Callback = S_CALLBACK,
        SignatureMethod = "HMAC-SHA1"
    };

    OAuthUtil.GetUnauthorizedRequestToken(parameters);
    string approvalPageUrl = OAuthUtil.CreateUserAuthorizationUrl(parameters);
    ViewBag.AuthUrl = approvalPageUrl;

}
catch (System.Net.WebException ex) {
    // print out more stuff
}

and this is the error I am seeing (slightly modified to remove sensitive data, however I left all the symbols as-is in case someone thinks this is an encoding error):

X-Content-Type-Options = nosniff
X-XSS-Protection = 1; mode=block
Content-Length = 386
Cache-Control = private, max-age=0
Content-Type = text/plain; charset=UTF-8
Date = Sun, 11 Sep 2011 06:53:26 GMT
Expires = Sun, 11 Sep 2011 06:53:26 GMT
Server = GSE

/accounts/OAuthGetAccessToken
signature_invalid
base_string:GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetAccessToken&oauth_consumer_key%3Dmydomain.com%26oauth_nonce%3D4432dc4bd59b4ea0b133ea52cb450062%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1315724016%26oauth_token%3D4%252FGeEWOLvQL_eGlj8zAdrzi7YPhmhS%26oauth_verifier%3DMkGYPy8qeZPRg7gLKKXsYIiM%26oauth_version%3D1.0


Callback = http://mydomain.com/auth
ConsumerKey = mydomain.com
ConsumerSecret = RxGavGhuXi92sy3F-Q3DKcY_
Nonce = 4430dc4bd59b4ea3b133ea52cb450062
Scope = https://docs.google.com/feeds
SignatureMethod = HMAC-SHA1
Timestamp = 1315724016
Token = 4/GeAWOLvQL_eGlj1zEerzi7YPhmhS
TokenSecret = 
Verifier = MkXLPy8qeZARq7aLKXKsYIiM
3
  • by the way, I have tried with both HTTP and HTTPS protocols Commented Sep 11, 2011 at 3:41
  • your consumer key and callback url's are on same domain? Commented Sep 11, 2011 at 3:53
  • Did you enable your domain in the application settings? Commented Sep 11, 2011 at 4:17

1 Answer 1

3

I struggled through this and was able to put together my own MVC2 class to handle this whole process. Take a look and let me know if this helps you out.

public class GoogleController : ApplicationController
{
    //
    // GET: /Google/

    public ActionResult Index()
    {
        return View();
    }

    public ActionResult Authorize()
    {
        OAuthParameters parameters = BuildParameters();

        // build the token for unauthorized requests and generate the url
        GetUnauthorizedRequestToken(parameters);
        string authorizationUrl = OAuthUtil.CreateUserAuthorizationUrl(parameters);

        // store the parameters temporarily and redirect to google for authorization
        SaveParametersTokens(parameters);
        Response.Redirect(authorizationUrl);
        return View();
    }

    public ActionResult Oauth()
    {
        // retrieve and update the tokens for temporary authentication
        OAuthParameters parameters = BuildParameters();
        OAuthUtil.UpdateOAuthParametersFromCallback(Request.Url.Query, parameters);

        // finally, get the token we need b@#$!!!
        OAuthUtil.GetAccessToken(parameters);

        // save those tokens into the database
        SaveParametersTokens(parameters);

        // all the success in the world, return back
        return RedirectToAction("Index", "Admin");
    }

    public ActionResult DeleteParametersTokens()
    {
        var oldTokens = (from t in context.GO_GoogleAuthorizeTokens select t);

        // if there is a token, call google to remove it
        /*if (oldTokens.Count() > 0)
        {
            GO_GoogleAuthorizeToken tokens = oldTokens.First();
            AuthSubUtil.revokeToken(tokens.Token, null);
        }*/

        // delete the tokens from the database
        context.GO_GoogleAuthorizeTokens.DeleteAllOnSubmit(oldTokens);
        context.SubmitChanges();

        // redirect to the administrator homepage when the tokens are deleted
        return RedirectToAction("Index", "Admin");
    }

    #region private helper methods

    private void GetUnauthorizedRequestToken(OAuthParameters parameters)
    {
        String requestTokenUrl = "https://www.google.com/accounts/OAuthGetRequestToken";
        Uri requestUri = new Uri(string.Format("{0}?scope={1}", requestTokenUrl, OAuthBase.EncodingPerRFC3986(parameters.Scope)));

        // callback is only needed when getting the request token
        bool callbackExists = false;
        if (!string.IsNullOrEmpty(parameters.Callback))
        {
            parameters.BaseProperties.Add(OAuthBase.OAuthCallbackKey, parameters.Callback);
            callbackExists = true;
        }

        string headers = OAuthUtil.GenerateHeader(requestUri, "GET", parameters);
        System.Net.WebRequest request = System.Net.WebRequest.Create(requestUri);
        request.Headers.Add(headers);

        System.Net.WebResponse response = request.GetResponse();
        string result = "";
        if (response != null)
        {
            System.IO.Stream responseStream = response.GetResponseStream();
            System.IO.StreamReader reader = new System.IO.StreamReader(responseStream);
            result = reader.ReadToEnd();
        }

        if (callbackExists)
        {
            parameters.BaseProperties.Remove(OAuthBase.OAuthCallbackKey);
        }

        // split results and update parameters
        SortedDictionary<string, string> responseValues = OAuthBase.GetQueryParameters(result);
        parameters.Token = responseValues[OAuthBase.OAuthTokenKey];
        parameters.TokenSecret = responseValues[OAuthBase.OAuthTokenSecretKey];
    }

    private bool SaveParametersTokens(OAuthParameters parameters)
    {
        try
        {
            // first delete any old ones
            var oldTokens = (from t in context.GO_GoogleAuthorizeTokens select t);
            context.GO_GoogleAuthorizeTokens.DeleteAllOnSubmit(oldTokens);
            context.SubmitChanges();

            // now create a new one
            GO_GoogleAuthorizeToken newToken = new GO_GoogleAuthorizeToken
            {
                Token = parameters.Token,
                TokenSecret = parameters.TokenSecret
            };
            context.GO_GoogleAuthorizeTokens.InsertOnSubmit(newToken);
            context.SubmitChanges();
        }
        catch { return false; }

        return true;
    }

    private OAuthParameters BuildParameters()
    {
        // build the base parameters
        string scope = "https://www.google.com/calendar/feeds/ https://docs.google.com/feeds/ https://mail.google.com/mail/feed/atom/";
        string callback = String.Format("http://{0}/Google/Oauth", Request.Url.Authority);
        OAuthParameters parameters = new OAuthParameters
        {
            ConsumerKey = kConsumerKey,
            ConsumerSecret = kConsumerSecret,
            Scope = scope,
            Callback = callback,
            SignatureMethod = "HMAC-SHA1"
        };

        // check to see if we have saved tokens
        var tokens = (from a in context.GO_GoogleAuthorizeTokens select a);
        if (tokens.Count() > 0)
        {
            GO_GoogleAuthorizeToken token = tokens.First();
            parameters.Token = token.Token;
            parameters.TokenSecret = token.TokenSecret;
        }

        return parameters;
    }

    #endregion
}
Sign up to request clarification or add additional context in comments.

2 Comments

do you have the same for twitter and facebook?
I don't, but I images it's pretty similar.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.