mirror of
https://github.com/overte-org/overte.git
synced 2025-04-10 03:22:32 +02:00
Merge pull request #10525 from seefo/master
Added refreshing of Account Managers access token
This commit is contained in:
commit
b0efb6d956
2 changed files with 91 additions and 5 deletions
|
@ -93,6 +93,7 @@ AccountManager::AccountManager(UserAgentGetter userAgentGetter) :
|
|||
}
|
||||
|
||||
const QString DOUBLE_SLASH_SUBSTITUTE = "slashslash";
|
||||
const QString ACCOUNT_MANAGER_REQUESTED_SCOPE = "owner";
|
||||
|
||||
void AccountManager::logout() {
|
||||
// a logout means we want to delete the DataServerAccountInfo we currently have for this URL, in-memory and in file
|
||||
|
@ -190,6 +191,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.";
|
||||
refreshAccessToken();
|
||||
}
|
||||
|
||||
// tell listeners that the auth endpoint has changed
|
||||
emit authEndpointChanged();
|
||||
}
|
||||
|
@ -448,6 +455,12 @@ bool AccountManager::hasValidAccessToken() {
|
|||
|
||||
return false;
|
||||
} else {
|
||||
|
||||
if (!_isWaitingForTokenRefresh && needsToRefreshToken()) {
|
||||
qCDebug(networking) << "Refreshing access token since it will be expiring soon.";
|
||||
refreshAccessToken();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -463,6 +476,15 @@ bool AccountManager::checkAndSignalForAccessToken() {
|
|||
return hasToken;
|
||||
}
|
||||
|
||||
bool AccountManager::needsToRefreshToken() {
|
||||
if (!_accountInfo.getAccessToken().token.isEmpty()) {
|
||||
qlonglong expireThreshold = QDateTime::currentDateTime().addSecs(1 * 60 * 60).toMSecsSinceEpoch();
|
||||
return _accountInfo.getAccessToken().expiryTimestamp < expireThreshold;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void AccountManager::setAccessTokenForCurrentAuthURL(const QString& accessToken) {
|
||||
// replace the account info access token with a new OAuthAccessToken
|
||||
OAuthAccessToken newOAuthToken;
|
||||
|
@ -495,8 +517,6 @@ void AccountManager::requestAccessToken(const QString& login, const QString& pas
|
|||
QUrl grantURL = _authURL;
|
||||
grantURL.setPath("/oauth/token");
|
||||
|
||||
const QString ACCOUNT_MANAGER_REQUESTED_SCOPE = "owner";
|
||||
|
||||
QByteArray postData;
|
||||
postData.append("grant_type=password&");
|
||||
postData.append("username=" + login + "&");
|
||||
|
@ -520,8 +540,6 @@ void AccountManager::requestAccessTokenWithSteam(QByteArray authSessionTicket) {
|
|||
QUrl grantURL = _authURL;
|
||||
grantURL.setPath("/oauth/token");
|
||||
|
||||
const QString ACCOUNT_MANAGER_REQUESTED_SCOPE = "owner";
|
||||
|
||||
QByteArray postData;
|
||||
postData.append("grant_type=password&");
|
||||
postData.append("steam_auth_ticket=" + QUrl::toPercentEncoding(authSessionTicket) + "&");
|
||||
|
@ -535,6 +553,32 @@ void AccountManager::requestAccessTokenWithSteam(QByteArray authSessionTicket) {
|
|||
connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestAccessTokenError(QNetworkReply::NetworkError)));
|
||||
}
|
||||
|
||||
void AccountManager::refreshAccessToken() {
|
||||
|
||||
_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");
|
||||
|
||||
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::refreshAccessTokenFinished);
|
||||
connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(refreshAccessTokenError(QNetworkReply::NetworkError)));
|
||||
}
|
||||
|
||||
void AccountManager::requestAccessTokenFinished() {
|
||||
QNetworkReply* requestReply = reinterpret_cast<QNetworkReply*>(sender());
|
||||
|
||||
|
@ -573,10 +617,47 @@ 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::refreshAccessTokenFinished() {
|
||||
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 a refreshed access-token for" << qPrintable(rootURL.toString());
|
||||
|
||||
_accountInfo.setAccessTokenFromJSON(rootObject);
|
||||
|
||||
persistAccountToFile();
|
||||
}
|
||||
} else {
|
||||
qCWarning(networking) << "Error in response for refresh grant - " << rootObject["error_description"].toString();
|
||||
}
|
||||
|
||||
_isWaitingForTokenRefresh = false;
|
||||
}
|
||||
|
||||
void AccountManager::refreshAccessTokenError(QNetworkReply::NetworkError error) {
|
||||
// TODO: error handling
|
||||
qCDebug(networking) << "AccountManager: failed to refresh access token - " << error;
|
||||
_isWaitingForTokenRefresh = false;
|
||||
}
|
||||
|
||||
void AccountManager::requestProfile() {
|
||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
|
||||
|
|
|
@ -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 refreshAccessToken();
|
||||
|
||||
void requestAccessTokenFinished();
|
||||
void refreshAccessTokenFinished();
|
||||
void requestProfileFinished();
|
||||
void requestAccessTokenError(QNetworkReply::NetworkError error);
|
||||
void refreshAccessTokenError(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 };
|
||||
|
|
Loading…
Reference in a new issue