Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does DotNetOpenAuth support refreshing Expired Access Tokens?

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!

like image 755
mightytightywty Avatar asked Oct 04 '10 17:10

mightytightywty


People also ask

Can you refresh an expired token?

Once they expire, client applications can use a refresh token to "refresh" the access token. That is, a refresh token is a credential artifact that lets a client application get new access tokens without having to ask the user to log in again.

How do I handle expired access tokens?

Token Refresh Handling: Method 1 convert expires_in to an expire time (epoch, RFC-3339/ISO-8601 datetime, etc.) store the expire time. on each resource request, check the current time against the expire time and make a token refresh request before the resource request if the access_token has expired.

What if access token is expired?

By default, access tokens are valid for 60 days and programmatic refresh tokens are valid for a year. The member must reauthorize your application when refresh tokens expire.

Does refresh token invalidate access token?

While refresh tokens are often long-lived, the authorization server can invalidate them. Some of the reasons a refresh token may no longer be valid include: the authorization server has revoked the refresh token. the user has revoked their consent for authorization.


2 Answers

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.

like image 107
Andrew Arnott Avatar answered Sep 20 '22 05:09

Andrew Arnott


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
    }
}
like image 35
mightytightywty Avatar answered Sep 19 '22 05:09

mightytightywty