The O2::refresh() function is used to generate a new access token using the refresh token. In the O2::onRefreshFinished() callback, the new access token is saved as expected. However O2::onRefreshFinished() assumes that the authorization server will provide the refresh token in the response. If the authorization server does not provide a refresh token, the old refresh token is replaced by an empty string. This issue is easily reproducible with YouTube where the access token expires each hour.
The O2::refresh() function is used to generate a new access token using the refresh token.
In the O2::onRefreshFinished() callback, the new access token is saved as expected. However O2::onRefreshFinished() assumes that the authorization server will provide the refresh token in the response. If the authorization server does not provide a refresh token, the old refresh token is replaced by an empty string. This issue is easily reproducible with YouTube where the access token expires each hour.

According to the OAuth v2 specs, when generating a new access token using a refresh token, the authorization server is not required to return the old refresh token nor a new refresh token. See https://tools.ietf.org/html/draft-ietf-oauth-v2-31
Also YouTube explicitly tells that the response when refreshing an access token DOES NOT contain the refresh token ( https://developers.google.com/youtube/v3/guides/auth/installed-apps ):

As long as the user has not revoked the access granted to the application, the token server returns a JSON object that contains a new access token. The following snippet shows a sample response:
{
 "access_token":"1/fFAGRNJru1FTz70BzhT3Zg",
 "expires_in":3920,
 "token_type":"Bearer"
}

Steps to reproduce:

1- Launch an application using O2
2- Add a YouTube account
3- Quit the application
4- Delete the access token (while leaving the refresh token for this account)
5- Launch again the application

Result: You can see that a new access token has been generated but the refresh token is gone.

6- Quit the application
7- Delete the access token
8- Launch again the application

Result: Since we have no access token and no refresh token, we need to request the user credentials.

Fix:

The fix consists at keeping the old refresh token if there is no refresh token in the access token response.

Timac/o2,pipacs/o2,pipacs/o2,Timac/o2