Added refreshing of Account Manager's access token

Changed indentention style to match guidelines
This commit is contained in:
seefo 2017-05-22 14:33:33 -07:00
parent c24561ec96
commit e77e900812
2 changed files with 98 additions and 1 deletions

View file

@ -189,6 +189,12 @@ void AccountManager::setAuthURL(const QUrl& authURL) {
requestProfile();
}
// prepare to refresh our token if it is about to expire
if (needsToRefreshToken()) {
qCDebug(networking) << "Refreshing access token since it will be expiring soon.";
requestNewAccessToken();
}
// tell listeners that the auth endpoint has changed
emit authEndpointChanged();
}
@ -443,6 +449,12 @@ bool AccountManager::hasValidAccessToken() {
return false;
} else {
if (!_isWaitingForTokenRefresh && needsToRefreshToken()) {
qCDebug(networking) << "Refreshing access token since it will be expiring soon.";
requestNewAccessToken();
}
return true;
}
}
@ -458,6 +470,15 @@ bool AccountManager::checkAndSignalForAccessToken() {
return hasToken;
}
bool AccountManager::needsToRefreshToken() {
if (!_accountInfo.getAccessToken().token.isEmpty())
{
qlonglong expireThreshold = QDateTime::currentDateTime().addSecs(1 * 60 * 60).toMSecsSinceEpoch();
if (_accountInfo.getAccessToken().expiryTimestamp < expireThreshold) return true;
}
return false;
}
void AccountManager::setAccessTokenForCurrentAuthURL(const QString& accessToken) {
// replace the account info access token with a new OAuthAccessToken
OAuthAccessToken newOAuthToken;
@ -530,6 +551,33 @@ void AccountManager::requestAccessTokenWithSteam(QByteArray authSessionTicket) {
connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestAccessTokenError(QNetworkReply::NetworkError)));
}
void AccountManager::requestNewAccessToken() {
_isWaitingForTokenRefresh = true;
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest request;
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
request.setHeader(QNetworkRequest::UserAgentHeader, _userAgentGetter());
QUrl grantURL = _authURL;
grantURL.setPath("/oauth/token");
const QString ACCOUNT_MANAGER_REQUESTED_SCOPE = "owner";
QByteArray postData;
postData.append("grant_type=refresh_token&");
postData.append("refresh_token=" + QUrl::toPercentEncoding(_accountInfo.getAccessToken().refreshToken) + "&");
postData.append("scope=" + ACCOUNT_MANAGER_REQUESTED_SCOPE);
request.setUrl(grantURL);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QNetworkReply* requestReply = networkAccessManager.post(request, postData);
connect(requestReply, &QNetworkReply::finished, this, &AccountManager::requestNewAccessTokenFinished);
connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestNewAccessTokenError(QNetworkReply::NetworkError)));
}
void AccountManager::requestAccessTokenFinished() {
QNetworkReply* requestReply = reinterpret_cast<QNetworkReply*>(sender());
@ -568,10 +616,54 @@ void AccountManager::requestAccessTokenFinished() {
void AccountManager::requestAccessTokenError(QNetworkReply::NetworkError error) {
// TODO: error handling
qCDebug(networking) << "AccountManager requestError - " << error;
qCDebug(networking) << "AccountManager: failed to fetch access token - " << error;
emit loginFailed();
}
void AccountManager::requestNewAccessTokenFinished() {
QNetworkReply* requestReply = reinterpret_cast<QNetworkReply*>(sender());
QJsonDocument jsonResponse = QJsonDocument::fromJson(requestReply->readAll());
const QJsonObject& rootObject = jsonResponse.object();
if (!rootObject.contains("error")) {
// construct an OAuthAccessToken from the json object
if (!rootObject.contains("access_token") || !rootObject.contains("expires_in")
|| !rootObject.contains("token_type")) {
// TODO: error handling - malformed token response
qCDebug(networking) << "Received a response for refresh grant that is missing one or more expected values.";
}
else {
// clear the path from the response URL so we have the right root URL for this access token
QUrl rootURL = requestReply->url();
rootURL.setPath("");
qCDebug(networking) << "Storing an account with access-token for" << qPrintable(rootURL.toString());
_accountInfo.setAccessTokenFromJSON(rootObject);
persistAccountToFile();
requestProfile();
}
}
else {
// TODO: error handling
qCDebug(networking) << "Error in response for refresh grant -" << rootObject["error_description"].toString();
emit loginFailed();
}
_isWaitingForTokenRefresh = false;
}
void AccountManager::requestNewAccessTokenError(QNetworkReply::NetworkError error) {
// TODO: error handling
qCDebug(networking) << "AccountManager: failed to refresh access token - " << error;
emit loginFailed();
_isWaitingForTokenRefresh = false;
}
void AccountManager::requestProfile() {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();

View file

@ -79,6 +79,7 @@ public:
bool isLoggedIn() { return !_authURL.isEmpty() && hasValidAccessToken(); }
bool hasValidAccessToken();
bool needsToRefreshToken();
Q_INVOKABLE bool checkAndSignalForAccessToken();
void setAccessTokenForCurrentAuthURL(const QString& accessToken);
@ -97,10 +98,13 @@ public:
public slots:
void requestAccessToken(const QString& login, const QString& password);
void requestAccessTokenWithSteam(QByteArray authSessionTicket);
void requestNewAccessToken();
void requestAccessTokenFinished();
void requestNewAccessTokenFinished();
void requestProfileFinished();
void requestAccessTokenError(QNetworkReply::NetworkError error);
void requestNewAccessTokenError(QNetworkReply::NetworkError error);
void requestProfileError(QNetworkReply::NetworkError error);
void logout();
void generateNewUserKeypair() { generateNewKeypair(); }
@ -141,6 +145,7 @@ private:
QMap<QNetworkReply*, JSONCallbackParameters> _pendingCallbackMap;
DataServerAccountInfo _accountInfo;
bool _isWaitingForTokenRefresh { false };
bool _isAgent { false };
bool _isWaitingForKeypairResponse { false };