Youtube API Refresh Token with C# returns invalid_grant

1k Views Asked by At

I'm trying to get a refreshed access token using the Youtube API v2 with C#. I'm doing it like this:

string _url = "client_id=" + HttpUtility.UrlEncode(_clientID) + "&client_secret=" + HttpUtility.UrlEncode(_clientSecret) + "&refresh_token=" + HttpUtility.UrlEncode(_refreshToken) + "&grant_type=refresh_token";

public string RefreshYoutubeToken(string _url) {
    string _response = "";
    TcpClient _tcpClient = new TcpClient("accounts.google.com", 443);
    Stream _netStream = _tcpClient.GetStream();
    SslStream _sslStream = new SslStream(_netStream);
    _sslStream.AuthenticateAsClient("accounts.google.com");
    {
        byte[] _contentAsBytes = Encoding.ASCII.GetBytes(_url.ToString());

        StringBuilder _message = new StringBuilder();
        _message.AppendLine("POST /o/oauth2/token HTTP/1.1");
        _message.AppendLine("Host: accounts.google.com");
        _message.AppendLine("Content-Type: application/x-www-form-urlencoded");
        _message.AppendLine("Content-Length: " + _contentAsBytes.Length.ToString());
        _message.AppendLine("");

        byte[] _headerAsBytes = Encoding.ASCII.GetBytes(_message.ToString());
        _sslStream.Write(_headerAsBytes);
        _sslStream.Write(_contentAsBytes);
    }

    StreamReader _reader = new StreamReader(_sslStream);
    while(true) {  // Print the response line by line to the debug stream for inspection.
        string _line = _reader.ReadLine();
        if(_line == null) { break; }
        _response += _line;
        if(_line == "0") { break; }
    }
    return _response;
}

This works fine when I'm logging in and retrieving the access token for the first time, however, when I want to use the refresh token to retrieve a new access token, just like they describe at Google Developers - https://developers.google.com/youtube/2.0/developers_guide_protocol_oauth2#OAuth2_Refreshing_a_Token - I get an error returning invalid_grant.

I read somwhere that the problem may come from different Client - Server date times, and I concluded that in fact my Client date is about 3 seconds late than the Server, for example, Client 12:10:52 and Server 12:10:55.
I already tried changing the Client date time but with no luck.

Does anyone have any idea on how to solve this? Using this method or someother, I just need to refresh the access token.

2

There are 2 best solutions below

5
aeijdenberg On

Make sure you URL encode each of the form parameters rather than just appending them to _url - I think the following will help: http://msdn.microsoft.com/en-us/library/4fkewx0t(v=vs.110).aspx

Additionally make sure you are passing the refresh token (and not the access token or authorization code). It's not guaranteed to change, but currently it usually starts with "1/".

2
pinoyyid On

As @aeijdenberg, I suspect you aren't correctly urlencoding each parameter. Remember my advice is to go the Oauth Playground and see what it is sending. (The docs do NOT uri encode the params which is misleading)

So here is what your request should look like

POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-length: 163
content-type: application/x-www-form-urlencoded
user-agent: google-oauth-playground

client_secret=************&grant_type=refresh_token&refresh_token=1%2Fz5Ogwmp8TqDL31eU1L_Nhddiva_L_8tR7V9k&client_id=407408718192.apps.googleusercontent.com

If and only if, your request is exactly the same as this and you still get invalid grant, then there is a problem with your refresh token, so get a new one.