summaryrefslogtreecommitdiffstats
path: root/logic/auth/flows/RefreshTask.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'logic/auth/flows/RefreshTask.cpp')
-rw-r--r--logic/auth/flows/RefreshTask.cpp156
1 files changed, 156 insertions, 0 deletions
diff --git a/logic/auth/flows/RefreshTask.cpp b/logic/auth/flows/RefreshTask.cpp
new file mode 100644
index 00000000..b56ed9bc
--- /dev/null
+++ b/logic/auth/flows/RefreshTask.cpp
@@ -0,0 +1,156 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <logic/auth/flows/RefreshTask.h>
+
+#include <logic/auth/MojangAccount.h>
+
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonArray>
+#include <QVariant>
+#include <QDebug>
+
+#include "logger/QsLog.h"
+
+RefreshTask::RefreshTask(MojangAccountPtr account, QObject *parent)
+ : YggdrasilTask(account, parent)
+{
+}
+
+QJsonObject RefreshTask::getRequestContent() const
+{
+ /*
+ * {
+ * "clientToken": "client identifier"
+ * "accessToken": "current access token to be refreshed"
+ * "selectedProfile": // specifying this causes errors
+ * {
+ * "id": "profile ID"
+ * "name": "profile name"
+ * }
+ * "requestUser": true/false // request the user structure
+ * }
+ */
+ auto account = getMojangAccount();
+ QJsonObject req;
+ req.insert("clientToken", account->clientToken());
+ req.insert("accessToken", account->accessToken());
+ /*
+ {
+ auto currentProfile = account->currentProfile();
+ QJsonObject profile;
+ profile.insert("id", currentProfile->id());
+ profile.insert("name", currentProfile->name());
+ req.insert("selectedProfile", profile);
+ }
+ */
+ req.insert("requestUser", true);
+
+ return req;
+}
+
+bool RefreshTask::processResponse(QJsonObject responseData)
+{
+ auto account = getMojangAccount();
+
+ // Read the response data. We need to get the client token, access token, and the selected
+ // profile.
+ QLOG_DEBUG() << "Processing authentication response.";
+
+ // If we already have a client token, make sure the one the server gave us matches our
+ // existing one.
+ QString clientToken = responseData.value("clientToken").toString("");
+ if (clientToken.isEmpty())
+ {
+ // Fail if the server gave us an empty client token
+ // TODO: Set an error properly to display to the user.
+ QLOG_ERROR() << "Server didn't send a client token.";
+ return false;
+ }
+ if (!account->clientToken().isEmpty() && clientToken != account->clientToken())
+ {
+ // The server changed our client token! Obey its wishes, but complain. That's what I do
+ // for my parents, so...
+ QLOG_ERROR() << "Server changed our client token to '" << clientToken
+ << "'. This shouldn't happen, but it isn't really a big deal.";
+ return false;
+ }
+
+ // Now, we set the access token.
+ QLOG_DEBUG() << "Getting new access token.";
+ QString accessToken = responseData.value("accessToken").toString("");
+ if (accessToken.isEmpty())
+ {
+ // Fail if the server didn't give us an access token.
+ // TODO: Set an error properly to display to the user.
+ QLOG_ERROR() << "Server didn't send an access token.";
+ return false;
+ }
+
+ // we validate that the server responded right. (our current profile = returned current
+ // profile)
+ QJsonObject currentProfile = responseData.value("selectedProfile").toObject();
+ QString currentProfileId = currentProfile.value("id").toString("");
+ if (account->currentProfile()->id() != currentProfileId)
+ {
+ // TODO: Set an error to display to the user.
+ QLOG_ERROR() << "Server didn't specify the same selected profile as ours.";
+ return false;
+ }
+
+ // this is what the vanilla launcher passes to the userProperties launch param
+ if (responseData.contains("user"))
+ {
+ auto obj = responseData.value("user").toObject();
+ auto userId = obj.value("id").toString();
+ auto propArray = obj.value("properties").toArray();
+ QLOG_DEBUG() << "User ID: " << userId;
+ QLOG_DEBUG() << "User Properties: ";
+ for (auto prop : propArray)
+ {
+ auto propTuple = prop.toObject();
+ auto name = propTuple.value("name").toString();
+ auto value = propTuple.value("value").toString();
+ QLOG_DEBUG() << name << " : " << value;
+ }
+ }
+
+ // We've made it through the minefield of possible errors. Return true to indicate that
+ // we've succeeded.
+ QLOG_DEBUG() << "Finished reading refresh response.";
+ // Reset the access token.
+ account->setAccessToken(accessToken);
+ account->propagateChange();
+ return true;
+}
+
+QString RefreshTask::getEndpoint() const
+{
+ return "refresh";
+}
+
+QString RefreshTask::getStateMessage(const YggdrasilTask::State state) const
+{
+ switch (state)
+ {
+ case STATE_SENDING_REQUEST:
+ return tr("Refreshing: Sending request.");
+ case STATE_PROCESSING_RESPONSE:
+ return tr("Refreshing: Processing response.");
+ default:
+ return YggdrasilTask::getStateMessage(state);
+ }
+}