Merge pull request #180 from Scrumplex/feat-msa-clientid-detection
Detect MSA Client ID change
This commit is contained in:
		| @@ -228,6 +228,18 @@ void LaunchController::login() { | |||||||
|                 emitFailed(errorString); |                 emitFailed(errorString); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |             case AccountState::Disabled: { | ||||||
|  |                 auto errorString = tr("The launcher's client identification has changed. Please remove this account and add it again."); | ||||||
|  |                 QMessageBox::warning( | ||||||
|  |                         m_parentWidget, | ||||||
|  |                         tr("Client identification changed"), | ||||||
|  |                         errorString, | ||||||
|  |                         QMessageBox::StandardButton::Ok, | ||||||
|  |                         QMessageBox::StandardButton::Ok | ||||||
|  |                 ); | ||||||
|  |                 emitFailed(errorString); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|             case AccountState::Gone: { |             case AccountState::Gone: { | ||||||
|                 auto errorString = tr("The account no longer exists on the servers. It may have been migrated, in which case please add the new account you migrated this one to."); |                 auto errorString = tr("The account no longer exists on the servers. It may have been migrated, in which case please add the new account you migrated this one to."); | ||||||
|                 QMessageBox::warning( |                 QMessageBox::warning( | ||||||
|   | |||||||
| @@ -327,6 +327,10 @@ bool AccountData::resumeStateFromV3(QJsonObject data) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if(type == AccountType::MSA) { |     if(type == AccountType::MSA) { | ||||||
|  |         auto clientIDV = data.value("msa-client-id"); | ||||||
|  |         if (clientIDV.isString()) { | ||||||
|  |             msaClientID = clientIDV.toString(); | ||||||
|  |         } // leave msaClientID empty if it doesn't exist or isn't a string | ||||||
|         msaToken = tokenFromJSONV3(data, "msa"); |         msaToken = tokenFromJSONV3(data, "msa"); | ||||||
|         userToken = tokenFromJSONV3(data, "utoken"); |         userToken = tokenFromJSONV3(data, "utoken"); | ||||||
|         xboxApiToken = tokenFromJSONV3(data, "xrp-main"); |         xboxApiToken = tokenFromJSONV3(data, "xrp-main"); | ||||||
| @@ -360,6 +364,7 @@ QJsonObject AccountData::saveState() const { | |||||||
|     } |     } | ||||||
|     else if (type == AccountType::MSA) { |     else if (type == AccountType::MSA) { | ||||||
|         output["type"] = "MSA"; |         output["type"] = "MSA"; | ||||||
|  |         output["msa-client-id"] = msaClientID; | ||||||
|         tokenToJSONV3(output, msaToken, "msa"); |         tokenToJSONV3(output, msaToken, "msa"); | ||||||
|         tokenToJSONV3(output, userToken, "utoken"); |         tokenToJSONV3(output, userToken, "utoken"); | ||||||
|         tokenToJSONV3(output, xboxApiToken, "xrp-main"); |         tokenToJSONV3(output, xboxApiToken, "xrp-main"); | ||||||
|   | |||||||
| @@ -47,6 +47,7 @@ enum class AccountState { | |||||||
|     Offline, |     Offline, | ||||||
|     Working, |     Working, | ||||||
|     Online, |     Online, | ||||||
|  |     Disabled, | ||||||
|     Errored, |     Errored, | ||||||
|     Expired, |     Expired, | ||||||
|     Gone |     Gone | ||||||
| @@ -81,6 +82,7 @@ struct AccountData { | |||||||
|     bool legacy = false; |     bool legacy = false; | ||||||
|     bool canMigrateToMSA = false; |     bool canMigrateToMSA = false; | ||||||
|  |  | ||||||
|  |     QString msaClientID; | ||||||
|     Katabasis::Token msaToken; |     Katabasis::Token msaToken; | ||||||
|     Katabasis::Token userToken; |     Katabasis::Token userToken; | ||||||
|     Katabasis::Token xboxApiToken; |     Katabasis::Token xboxApiToken; | ||||||
|   | |||||||
| @@ -291,6 +291,9 @@ QVariant AccountList::data(const QModelIndex &index, int role) const | |||||||
|                     case AccountState::Expired: { |                     case AccountState::Expired: { | ||||||
|                         return tr("Expired", "Account status"); |                         return tr("Expired", "Account status"); | ||||||
|                     } |                     } | ||||||
|  |                     case AccountState::Disabled: { | ||||||
|  |                         return tr("Disabled", "Account status"); | ||||||
|  |                     } | ||||||
|                     case AccountState::Gone: { |                     case AccountState::Gone: { | ||||||
|                         return tr("Gone", "Account status"); |                         return tr("Gone", "Account status"); | ||||||
|                     } |                     } | ||||||
|   | |||||||
| @@ -43,6 +43,8 @@ QString AccountTask::getStateMessage() const | |||||||
|         return tr("Authentication task succeeded."); |         return tr("Authentication task succeeded."); | ||||||
|     case AccountTaskState::STATE_OFFLINE: |     case AccountTaskState::STATE_OFFLINE: | ||||||
|         return tr("Failed to contact the authentication server."); |         return tr("Failed to contact the authentication server."); | ||||||
|  |     case AccountTaskState::STATE_DISABLED: | ||||||
|  |         return tr("Client ID has changed. New session needs to be created."); | ||||||
|     case AccountTaskState::STATE_FAILED_SOFT: |     case AccountTaskState::STATE_FAILED_SOFT: | ||||||
|         return tr("Encountered an error during authentication."); |         return tr("Encountered an error during authentication."); | ||||||
|     case AccountTaskState::STATE_FAILED_HARD: |     case AccountTaskState::STATE_FAILED_HARD: | ||||||
| @@ -78,6 +80,12 @@ bool AccountTask::changeState(AccountTaskState newState, QString reason) | |||||||
|             emitFailed(reason); |             emitFailed(reason); | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|  |         case AccountTaskState::STATE_DISABLED: { | ||||||
|  |             m_data->errorString = reason; | ||||||
|  |             m_data->accountState = AccountState::Disabled; | ||||||
|  |             emitFailed(reason); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|         case AccountTaskState::STATE_FAILED_SOFT: { |         case AccountTaskState::STATE_FAILED_SOFT: { | ||||||
|             m_data->errorString = reason; |             m_data->errorString = reason; | ||||||
|             m_data->accountState = AccountState::Errored; |             m_data->accountState = AccountState::Errored; | ||||||
|   | |||||||
| @@ -35,6 +35,7 @@ enum class AccountTaskState | |||||||
|     STATE_CREATED, |     STATE_CREATED, | ||||||
|     STATE_WORKING, |     STATE_WORKING, | ||||||
|     STATE_SUCCEEDED, |     STATE_SUCCEEDED, | ||||||
|  |     STATE_DISABLED, //!< MSA Client ID has changed. Tell user to reloginn | ||||||
|     STATE_FAILED_SOFT, //!< soft failure. authentication went through partially |     STATE_FAILED_SOFT, //!< soft failure. authentication went through partially | ||||||
|     STATE_FAILED_HARD, //!< hard failure. main tokens are invalid |     STATE_FAILED_HARD, //!< hard failure. main tokens are invalid | ||||||
|     STATE_FAILED_GONE, //!< hard failure. main tokens are invalid, and the account no longer exists |     STATE_FAILED_GONE, //!< hard failure. main tokens are invalid, and the account no longer exists | ||||||
|   | |||||||
| @@ -176,6 +176,9 @@ void MinecraftAccount::authFailed(QString reason) | |||||||
| { | { | ||||||
|     switch (m_currentTask->taskState()) { |     switch (m_currentTask->taskState()) { | ||||||
|         case AccountTaskState::STATE_OFFLINE: |         case AccountTaskState::STATE_OFFLINE: | ||||||
|  |         case AccountTaskState::STATE_DISABLED: { | ||||||
|  |             // NOTE: user will need to fix this themselves. | ||||||
|  |         } | ||||||
|         case AccountTaskState::STATE_FAILED_SOFT: { |         case AccountTaskState::STATE_FAILED_SOFT: { | ||||||
|             // NOTE: this doesn't do much. There was an error of some sort. |             // NOTE: this doesn't do much. There was an error of some sort. | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -12,9 +12,10 @@ using OAuth2 = Katabasis::DeviceFlow; | |||||||
| using Activity = Katabasis::Activity; | using Activity = Katabasis::Activity; | ||||||
|  |  | ||||||
| MSAStep::MSAStep(AccountData* data, Action action) : AuthStep(data), m_action(action) { | MSAStep::MSAStep(AccountData* data, Action action) : AuthStep(data), m_action(action) { | ||||||
|  |     m_clientId = APPLICATION->getMSAClientID(); | ||||||
|     OAuth2::Options opts; |     OAuth2::Options opts; | ||||||
|     opts.scope = "XboxLive.signin offline_access"; |     opts.scope = "XboxLive.signin offline_access"; | ||||||
|     opts.clientIdentifier = APPLICATION->getMSAClientID(); |     opts.clientIdentifier = m_clientId; | ||||||
|     opts.authorizationUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode"; |     opts.authorizationUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode"; | ||||||
|     opts.accessTokenUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/token"; |     opts.accessTokenUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/token"; | ||||||
|  |  | ||||||
| @@ -48,6 +49,10 @@ void MSAStep::rehydrate() { | |||||||
| void MSAStep::perform() { | void MSAStep::perform() { | ||||||
|     switch(m_action) { |     switch(m_action) { | ||||||
|         case Refresh: { |         case Refresh: { | ||||||
|  |             if (m_data->msaClientID != m_clientId) { | ||||||
|  |                 emit hideVerificationUriAndCode(); | ||||||
|  |                 emit finished(AccountTaskState::STATE_DISABLED, tr("Microsoft user authentication failed - client identification has changed.")); | ||||||
|  |             } | ||||||
|             m_oauth2->refresh(); |             m_oauth2->refresh(); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| @@ -57,6 +62,7 @@ void MSAStep::perform() { | |||||||
|             m_oauth2->setExtraRequestParams(extraOpts); |             m_oauth2->setExtraRequestParams(extraOpts); | ||||||
|  |  | ||||||
|             *m_data = AccountData(); |             *m_data = AccountData(); | ||||||
|  |             m_data->msaClientID = m_clientId; | ||||||
|             m_oauth2->login(); |             m_oauth2->login(); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -29,4 +29,5 @@ private slots: | |||||||
| private: | private: | ||||||
|     Katabasis::DeviceFlow *m_oauth2 = nullptr; |     Katabasis::DeviceFlow *m_oauth2 = nullptr; | ||||||
|     Action m_action; |     Action m_action; | ||||||
|  |     QString m_clientId; | ||||||
| }; | }; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user