views:

37

answers:

2

I can't find any examples of using DotNetOpenAuth to refresh an expired Access Token. Most providers don't use expiring tokens, however Yahoo is a big one that expires their tokens in one hour.

Thanks!

A: 

If you're talking about OAuth 1.0(a), I don't believe renewing expired access tokens is part of the spec at all, so I suspect you just can't do it regardless of the OAuth library you use.

If you're talking about OAuth 2.0, then yes the ClientBase.RefreshToken method will do that for you. DotNetOpenAuth even automatically renews nearly expired tokens when you call ClientBase.AuthorizeRequest.

Andrew Arnott
A: 

Yahoo does use OAuth 1.0, so I figured out how to do it manually:

First, I try to use the token I have saved in my database. If I get a 401 Unauthorized error, I call my RefreshYahooAccessToken() method, and try again.

Note: I have my own implementation of a TokenManager that stores my access tokens in a database, as well as any extra data associated with the token (YahooGUID, and oauth_session_handle) which is given to me in Yahoo's get_token Response Parameters, but you can easily modify it to work with a different TokenManager implementation.

Here's my working version:

try
{
    request = yahoo.PrepareAuthorizedRequest(YahooContactsAPIEndpoint, TokenManager.currentToken.Token, extraData);
    response = yahoo.Channel.WebRequestHandler.GetResponse(request);
    body = response.GetResponseReader().ReadToEnd();
}
catch (DotNetOpenAuth.Messaging.ProtocolException ex)
{
    //is token expired?
    if (ex.InnerException is WebException
        && ((WebException)ex.InnerException).Response is HttpWebResponse
        && ((HttpWebResponse)((WebException)ex.InnerException).Response).StatusCode == HttpStatusCode.Unauthorized)
    {
        RefreshYahooAccessToken();
        request = yahoo.PrepareAuthorizedRequest(YahooContactsAPIEndpoint, TokenManager.currentToken.Token, extraData);
        response = yahoo.Channel.WebRequestHandler.GetResponse(request);
        body = response.GetResponseReader().ReadToEnd();
    }
}


private static void RefreshYahooAccessToken()
{
    var request = (HttpWebRequest)WebRequest
        .Create("https://api.login.yahoo.com/oauth/v2/get_token"
            + "?oauth_consumer_key=" + TokenManager.ConsumerKey
            + "&oauth_nonce=" + (new Random()).Next(123400, 9999999).ToString()
            + "&oauth_session_handle=" + TokenManager.GetExtraData("oauth_session_handle") //this value is given to you in the get_token Response Parameters
            + "&oauth_signature=" + TokenManager.ConsumerSecret + "%26" + TokenManager.currentToken.Secret
            + "&oauth_signature_method=PLAINTEXT"
            + "&oauth_timestamp=" + (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds.ToString().Split(new char[] { '.' })[0]
            + "&oauth_token=" + TokenManager.currentToken.Token
            + "&oauth_version=1.0");
    try
    {
        var response = (HttpWebResponse)request.GetResponse();
        var returnStr = new System.IO.StreamReader(response.GetResponseStream()).ReadToEnd();
        var returnData = System.Web.HttpUtility.ParseQueryString(returnStr ?? string.Empty);
        TokenManager.ExpireRequestTokenAndStoreNewAccessToken(null, null, returnData["oauth_token"], returnData["oauth_token_secret"]);
    }
    catch (Exception)
    {
        //User probably revoked token.  Clear the current token, and request authorization again
    }
}
mightytightywty