Skip to content

Commit 12e1112

Browse files
committed
Logout existing sessions after an auth config change
Closes qbittorrent#18443
1 parent 1c43286 commit 12e1112

File tree

6 files changed

+55
-8
lines changed

6 files changed

+55
-8
lines changed

Diff for: src/base/preferences.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,7 @@ void Preferences::setWebUILocalAuthEnabled(const bool enabled)
657657
if (enabled == isWebUILocalAuthEnabled())
658658
return;
659659

660+
m_authBypassChanged = true;
660661
setValue(u"Preferences/WebUI/LocalHostAuth"_s, enabled);
661662
}
662663

@@ -670,6 +671,7 @@ void Preferences::setWebUIAuthSubnetWhitelistEnabled(const bool enabled)
670671
if (enabled == isWebUIAuthSubnetWhitelistEnabled())
671672
return;
672673

674+
m_authBypassChanged = true;
673675
setValue(u"Preferences/WebUI/AuthSubnetWhitelistEnabled"_s, enabled);
674676
}
675677

@@ -763,6 +765,7 @@ void Preferences::setWebUIUsername(const QString &username)
763765
if (username == getWebUIUsername())
764766
return;
765767

768+
m_credentialsChanged = true;
766769
setValue(u"Preferences/WebUI/Username"_s, username);
767770
}
768771

@@ -776,6 +779,7 @@ void Preferences::setWebUIPassword(const QByteArray &password)
776779
if (password == getWebUIPassword())
777780
return;
778781

782+
m_credentialsChanged = true;
779783
setValue(u"Preferences/WebUI/Password_PBKDF2"_s, password);
780784
}
781785

@@ -1977,5 +1981,9 @@ void Preferences::setAddNewTorrentDialogSavePathHistoryLength(const int value)
19771981
void Preferences::apply()
19781982
{
19791983
if (SettingsStorage::instance()->save())
1984+
{
19801985
emit changed();
1986+
if (m_credentialsChanged || m_authBypassChanged)
1987+
emit webAuthConfigChanged(m_credentialsChanged);
1988+
}
19811989
}

Diff for: src/base/preferences.h

+4
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,11 @@ public slots:
430430

431431
signals:
432432
void changed();
433+
void webAuthConfigChanged(bool credentialsChanged);
433434

434435
private:
435436
static Preferences *m_instance;
437+
438+
bool m_credentialsChanged = false;
439+
bool m_authBypassChanged = false;
436440
};

Diff for: src/webui/api/authcontroller.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ void AuthController::loginAction()
8181
{
8282
m_clientFailedLogins.remove(clientAddr);
8383

84-
m_sessionManager->sessionStart();
84+
m_sessionManager->sessionStart(true);
8585
setResult(u"Ok."_s);
8686
LogMsg(tr("WebAPI login success. IP: %1").arg(clientAddr));
8787
}

Diff for: src/webui/api/isessionmanager.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,6 @@ struct ISessionManager
4343
virtual ~ISessionManager() = default;
4444
virtual QString clientId() const = 0;
4545
virtual ISession *session() = 0;
46-
virtual void sessionStart() = 0;
46+
virtual void sessionStart(bool authenticated) = 0;
4747
virtual void sessionEnd() = 0;
4848
};

Diff for: src/webui/webapplication.cpp

+34-4
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ WebApplication::WebApplication(IApplication *app, QObject *parent)
170170

171171
configure();
172172
connect(Preferences::instance(), &Preferences::changed, this, &WebApplication::configure);
173+
connect(Preferences::instance(), &Preferences::webAuthConfigChanged, this, &WebApplication::logoutExistingSessions);
173174

174175
m_sessionCookieName = Preferences::instance()->getWebAPISessionCookieName();
175176
if (!isValidCookieName(m_sessionCookieName))
@@ -299,6 +300,29 @@ const Http::Environment &WebApplication::env() const
299300
return m_env;
300301
}
301302

303+
void WebApplication::logoutExistingSessions(bool credentialsChanged)
304+
{
305+
if (credentialsChanged)
306+
{
307+
qDeleteAll(m_sessions);
308+
m_sessions.clear();
309+
}
310+
else
311+
{
312+
// remove sessions which bypassed authentication
313+
Algorithm::removeIf(m_sessions, [this](const QString &, const WebSession *session)
314+
{
315+
if (!session->isAuthenticated())
316+
{
317+
delete session;
318+
return true;
319+
}
320+
321+
return false;
322+
});
323+
}
324+
}
325+
302326
void WebApplication::setUsername(const QString &username)
303327
{
304328
m_authController->setUsername(username);
@@ -677,7 +701,7 @@ void WebApplication::sessionInitialize()
677701
}
678702

679703
if (!m_currentSession && !isAuthNeeded())
680-
sessionStart();
704+
sessionStart(false);
681705
}
682706

683707
QString WebApplication::generateSid() const
@@ -710,7 +734,7 @@ bool WebApplication::isPublicAPI(const QString &scope, const QString &action) co
710734
return m_publicAPIs.contains(u"%1/%2"_s.arg(scope, action));
711735
}
712736

713-
void WebApplication::sessionStart()
737+
void WebApplication::sessionStart(bool authenticated)
714738
{
715739
Q_ASSERT(!m_currentSession);
716740

@@ -726,7 +750,7 @@ void WebApplication::sessionStart()
726750
return false;
727751
});
728752

729-
m_currentSession = new WebSession(generateSid(), app());
753+
m_currentSession = new WebSession(generateSid(), app(), authenticated);
730754
m_sessions[m_currentSession->id()] = m_currentSession;
731755

732756
m_currentSession->registerAPIController(u"app"_s, new AppController(app(), this));
@@ -911,9 +935,10 @@ QHostAddress WebApplication::resolveClientAddress() const
911935

912936
// WebSession
913937

914-
WebSession::WebSession(const QString &sid, IApplication *app)
938+
WebSession::WebSession(const QString &sid, IApplication *app, bool authenticated)
915939
: ApplicationComponent(app)
916940
, m_sid {sid}
941+
, m_authenticated {authenticated}
917942
{
918943
updateTimestamp();
919944
}
@@ -935,6 +960,11 @@ void WebSession::updateTimestamp()
935960
m_timer.start();
936961
}
937962

963+
bool WebSession::isAuthenticated() const
964+
{
965+
return m_authenticated;
966+
}
967+
938968
void WebSession::registerAPIController(const QString &scope, APIController *controller)
939969
{
940970
Q_ASSERT(controller);

Diff for: src/webui/webapplication.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -71,19 +71,21 @@ namespace BitTorrent
7171
class WebSession final : public ApplicationComponent<QObject>, public ISession
7272
{
7373
public:
74-
explicit WebSession(const QString &sid, IApplication *app);
74+
explicit WebSession(const QString &sid, IApplication *app, bool authenticated);
7575

7676
QString id() const override;
7777

7878
bool hasExpired(qint64 seconds) const;
7979
void updateTimestamp();
80+
bool isAuthenticated() const;
8081

8182
void registerAPIController(const QString &scope, APIController *controller);
8283
APIController *getAPIController(const QString &scope) const;
8384

8485
private:
8586
const QString m_sid;
8687
QElapsedTimer m_timer; // timestamp
88+
bool m_authenticated;
8789
QMap<QString, APIController *> m_apiControllers;
8890
};
8991

@@ -106,10 +108,13 @@ class WebApplication final : public ApplicationComponent<QObject>
106108
void setUsername(const QString &username);
107109
void setPasswordHash(const QByteArray &passwordHash);
108110

111+
public slots:
112+
void logoutExistingSessions(bool credentialsChanged);
113+
109114
private:
110115
QString clientId() const override;
111116
WebSession *session() override;
112-
void sessionStart() override;
117+
void sessionStart(bool authenticated) override;
113118
void sessionEnd() override;
114119

115120
void doProcessRequest();

0 commit comments

Comments
 (0)