Qobuz: Fix authentication and add automatic credential fetching
Qobuz API now requires intent=stream parameter for stream URL requests, and the app_secret must be extracted using the Spoofbuz decoding method from bundle.js rather than plain-text values. Changes: - Add intent=stream parameter to stream URL requests - Add QobuzCredentialFetcher class to extract credentials from web player - Add "Fetch Credentials" button to Qobuz settings page - Decode obfuscated app secrets using seed/timezone/info/extras method This fixes "Invalid Request Signature" errors that prevented playback.
This commit is contained in:
committed by
Jonas Kvinge
parent
2cd9498469
commit
2bb0dbada2
@@ -38,6 +38,7 @@
|
||||
#include "core/settings.h"
|
||||
#include "widgets/loginstatewidget.h"
|
||||
#include "qobuz/qobuzservice.h"
|
||||
#include "qobuz/qobuzcredentialfetcher.h"
|
||||
#include "constants/qobuzsettings.h"
|
||||
|
||||
using namespace Qt::Literals::StringLiterals;
|
||||
@@ -46,13 +47,15 @@ using namespace QobuzSettings;
|
||||
QobuzSettingsPage::QobuzSettingsPage(SettingsDialog *dialog, const SharedPtr<QobuzService> service, QWidget *parent)
|
||||
: SettingsPage(dialog, parent),
|
||||
ui_(new Ui::QobuzSettingsPage),
|
||||
service_(service) {
|
||||
service_(service),
|
||||
credential_fetcher_(nullptr) {
|
||||
|
||||
ui_->setupUi(this);
|
||||
setWindowIcon(IconLoader::Load(u"qobuz"_s, true, 0, 32));
|
||||
|
||||
QObject::connect(ui_->button_login, &QPushButton::clicked, this, &QobuzSettingsPage::LoginClicked);
|
||||
QObject::connect(ui_->login_state, &LoginStateWidget::LogoutClicked, this, &QobuzSettingsPage::LogoutClicked);
|
||||
QObject::connect(ui_->button_fetch_credentials, &QPushButton::clicked, this, &QobuzSettingsPage::FetchCredentialsClicked);
|
||||
|
||||
QObject::connect(this, &QobuzSettingsPage::Login, &*service_, &StreamingService::LoginWithCredentials);
|
||||
|
||||
@@ -186,3 +189,40 @@ void QobuzSettingsPage::LoginFailure(const QString &failure_reason) {
|
||||
QMessageBox::warning(this, tr("Authentication failed"), failure_reason);
|
||||
|
||||
}
|
||||
|
||||
void QobuzSettingsPage::FetchCredentialsClicked() {
|
||||
|
||||
ui_->button_fetch_credentials->setEnabled(false);
|
||||
ui_->button_fetch_credentials->setText(tr("Fetching..."));
|
||||
|
||||
if (!credential_fetcher_) {
|
||||
credential_fetcher_ = new QobuzCredentialFetcher(service_->network(), this);
|
||||
QObject::connect(credential_fetcher_, &QobuzCredentialFetcher::CredentialsFetched, this, &QobuzSettingsPage::CredentialsFetched);
|
||||
QObject::connect(credential_fetcher_, &QobuzCredentialFetcher::CredentialsFetchError, this, &QobuzSettingsPage::CredentialsFetchError);
|
||||
}
|
||||
|
||||
credential_fetcher_->FetchCredentials();
|
||||
|
||||
}
|
||||
|
||||
void QobuzSettingsPage::CredentialsFetched(const QString &app_id, const QString &app_secret) {
|
||||
|
||||
ui_->app_id->setText(app_id);
|
||||
ui_->app_secret->setText(app_secret);
|
||||
ui_->checkbox_base64_secret->setChecked(false);
|
||||
|
||||
ui_->button_fetch_credentials->setEnabled(true);
|
||||
ui_->button_fetch_credentials->setText(tr("Fetch Credentials"));
|
||||
|
||||
QMessageBox::information(this, tr("Credentials fetched"), tr("App ID and secret have been successfully fetched from the Qobuz web player."));
|
||||
|
||||
}
|
||||
|
||||
void QobuzSettingsPage::CredentialsFetchError(const QString &error) {
|
||||
|
||||
ui_->button_fetch_credentials->setEnabled(true);
|
||||
ui_->button_fetch_credentials->setText(tr("Fetch Credentials"));
|
||||
|
||||
QMessageBox::warning(this, tr("Credential fetch failed"), error);
|
||||
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ class QShowEvent;
|
||||
class QEvent;
|
||||
class SettingsDialog;
|
||||
class QobuzService;
|
||||
class QobuzCredentialFetcher;
|
||||
class Ui_QobuzSettingsPage;
|
||||
|
||||
class QobuzSettingsPage : public SettingsPage {
|
||||
@@ -55,10 +56,14 @@ class QobuzSettingsPage : public SettingsPage {
|
||||
void LogoutClicked();
|
||||
void LoginSuccess();
|
||||
void LoginFailure(const QString &failure_reason);
|
||||
void FetchCredentialsClicked();
|
||||
void CredentialsFetched(const QString &app_id, const QString &app_secret);
|
||||
void CredentialsFetchError(const QString &error);
|
||||
|
||||
private:
|
||||
Ui_QobuzSettingsPage *ui_;
|
||||
const SharedPtr<QobuzService> service_;
|
||||
QobuzCredentialFetcher *credential_fetcher_;
|
||||
};
|
||||
|
||||
#endif // QOBUZSETTINGSPAGE_H
|
||||
|
||||
@@ -115,6 +115,16 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QPushButton" name="button_fetch_credentials">
|
||||
<property name="text">
|
||||
<string>Fetch Credentials</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Automatically fetch app ID and secret from Qobuz web player</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
Reference in New Issue
Block a user