3c46d8a412
This makes the account system much more modular and makes it treat errors as something recoverable, unless they come directly from the MSA refresh token becoming invalid.
112 lines
3.7 KiB
C++
112 lines
3.7 KiB
C++
#include "MSAStep.h"
|
|
|
|
#include <QNetworkRequest>
|
|
|
|
#include "minecraft/auth/AuthRequest.h"
|
|
#include "minecraft/auth/Parsers.h"
|
|
|
|
#include "Application.h"
|
|
|
|
using OAuth2 = Katabasis::DeviceFlow;
|
|
using Activity = Katabasis::Activity;
|
|
|
|
MSAStep::MSAStep(AccountData* data, Action action) : AuthStep(data), m_action(action) {
|
|
OAuth2::Options opts;
|
|
opts.scope = "XboxLive.signin offline_access";
|
|
opts.clientIdentifier = APPLICATION->msaClientId();
|
|
opts.authorizationUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode";
|
|
opts.accessTokenUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/token";
|
|
|
|
// FIXME: OAuth2 is not aware of our fancy shared pointers
|
|
m_oauth2 = new OAuth2(opts, m_data->msaToken, this, APPLICATION->network().get());
|
|
|
|
connect(m_oauth2, &OAuth2::activityChanged, this, &MSAStep::onOAuthActivityChanged);
|
|
connect(m_oauth2, &OAuth2::showVerificationUriAndCode, this, &MSAStep::showVerificationUriAndCode);
|
|
}
|
|
|
|
MSAStep::~MSAStep() noexcept = default;
|
|
|
|
QString MSAStep::describe() {
|
|
return tr("Logging in with Microsoft account.");
|
|
}
|
|
|
|
|
|
void MSAStep::rehydrate() {
|
|
switch(m_action) {
|
|
case Refresh: {
|
|
// TODO: check the tokens and see if they are old (older than a day)
|
|
return;
|
|
}
|
|
case Login: {
|
|
// NOOP
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void MSAStep::perform() {
|
|
switch(m_action) {
|
|
case Refresh: {
|
|
m_oauth2->refresh();
|
|
return;
|
|
}
|
|
case Login: {
|
|
QVariantMap extraOpts;
|
|
extraOpts["prompt"] = "select_account";
|
|
m_oauth2->setExtraRequestParams(extraOpts);
|
|
|
|
*m_data = AccountData();
|
|
m_oauth2->login();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void MSAStep::onOAuthActivityChanged(Katabasis::Activity activity) {
|
|
switch(activity) {
|
|
case Katabasis::Activity::Idle:
|
|
case Katabasis::Activity::LoggingIn:
|
|
case Katabasis::Activity::Refreshing:
|
|
case Katabasis::Activity::LoggingOut: {
|
|
// We asked it to do something, it's doing it. Nothing to act upon.
|
|
return;
|
|
}
|
|
case Katabasis::Activity::Succeeded: {
|
|
// Succeeded or did not invalidate tokens
|
|
emit hideVerificationUriAndCode();
|
|
QVariantMap extraTokens = m_oauth2->extraTokens();
|
|
#ifndef NDEBUG
|
|
if (!extraTokens.isEmpty()) {
|
|
qDebug() << "Extra tokens in response:";
|
|
foreach (QString key, extraTokens.keys()) {
|
|
qDebug() << "\t" << key << ":" << extraTokens.value(key);
|
|
}
|
|
}
|
|
#endif
|
|
emit finished(AccountTaskState::STATE_WORKING, tr("Got "));
|
|
return;
|
|
}
|
|
case Katabasis::Activity::FailedSoft: {
|
|
// NOTE: soft error in the first step means 'offline'
|
|
emit hideVerificationUriAndCode();
|
|
emit finished(AccountTaskState::STATE_OFFLINE, tr("Microsoft user authentication ended with a network error."));
|
|
return;
|
|
}
|
|
case Katabasis::Activity::FailedGone: {
|
|
emit hideVerificationUriAndCode();
|
|
emit finished(AccountTaskState::STATE_FAILED_GONE, tr("Microsoft user authentication failed - user no longer exists."));
|
|
return;
|
|
}
|
|
case Katabasis::Activity::FailedHard: {
|
|
emit hideVerificationUriAndCode();
|
|
emit finished(AccountTaskState::STATE_FAILED_HARD, tr("Microsoft user authentication failed."));
|
|
return;
|
|
}
|
|
default: {
|
|
emit hideVerificationUriAndCode();
|
|
emit finished(AccountTaskState::STATE_FAILED_HARD, tr("Microsoft user authentication completed with an unrecognized result."));
|
|
return;
|
|
}
|
|
}
|
|
}
|