aboutsummaryrefslogtreecommitdiff
path: root/launcher/minecraft/auth/steps/MSAStep.cpp
blob: 779aee43622b2037db20a9e13fd2cd23dc8d8491 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include "MSAStep.h"

#include <QNetworkRequest>

#include "BuildConfig.h"
#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->getMSAClientID();
    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;
        }
    }
}