Skip to content

Commit

Permalink
Client: Add credentialsChanged() signal
Browse files Browse the repository at this point in the history
Users may want to serialize the new credentials.

This also exposes the used authentication method in QXmppOutgoingClient.
  • Loading branch information
lnjX committed Jun 20, 2024
1 parent e7dd83b commit 2396889
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 2 deletions.
5 changes: 4 additions & 1 deletion src/client/QXmppClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -945,12 +945,15 @@ void QXmppClient::_q_socketStateChanged(QAbstractSocket::SocketState socketState
}

/// At connection establishment, send initial presence.
void QXmppClient::_q_streamConnected()
void QXmppClient::_q_streamConnected(const QXmpp::Private::SessionBegin &session)
{
d->receivedConflict = false;
d->reconnectionTries = 0;

// notify managers
if (session.fastTokenChanged) {
Q_EMIT credentialsChanged();
}
Q_EMIT connected();
Q_EMIT stateChanged(QXmppClient::ConnectedState);

Expand Down
13 changes: 12 additions & 1 deletion src/client/QXmppClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ class QXmppRosterManager;
class QXmppVCardManager;
class QXmppVersionManager;

namespace QXmpp::Private {
struct SessionBegin;
}

///
/// \defgroup Core Core classes
///
Expand Down Expand Up @@ -296,6 +300,13 @@ class QXMPP_EXPORT QXmppClient : public QXmppLoggable
/// This signal is emitted when the client state changes.
void stateChanged(QXmppClient::State state);

/// Emitted when the credentials, e.g. tokens have changed.
///
/// This means that the QXmppCredentials in the QXmppConfiguration of this client has changed.
///
/// \since QXmpp 1.8
Q_SIGNAL void credentialsChanged();

public Q_SLOTS:
void connectToServer(const QXmppConfiguration &,
const QXmppPresence &initialPresence =
Expand All @@ -315,7 +326,7 @@ private Q_SLOTS:
void _q_elementReceived(const QDomElement &element, bool &handled);
void _q_reconnect();
void _q_socketStateChanged(QAbstractSocket::SocketState state);
void _q_streamConnected();
void _q_streamConnected(const QXmpp::Private::SessionBegin &);
void _q_streamDisconnected();

private:
Expand Down
5 changes: 5 additions & 0 deletions src/client/QXmppOutgoingClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ void QXmppOutgoingClient::startSasl2Auth(const Sasl2::StreamFeature &sasl2Featur
if (auto success = std::get_if<Sasl2::Success>(&result)) {
debug(u"Authenticated"_s);
d->isAuthenticated = true;
d->authenticationMethod = AuthenticationMethod::Sasl2;
d->config.setJid(success->authorizationIdentifier);
d->bind2Bound = std::move(success->bound);

Expand Down Expand Up @@ -369,6 +370,7 @@ void QXmppOutgoingClient::startNonSaslAuth()
// successful Non-SASL Authentication
debug(u"Authenticated (Non-SASL)"_s);
d->isAuthenticated = true;
d->authenticationMethod = AuthenticationMethod::NonSasl;

// xmpp connection made
openSession();
Expand Down Expand Up @@ -454,6 +456,8 @@ void QXmppOutgoingClient::openSession()
d->c2sStreamManager.enabled(),
d->c2sStreamManager.streamResumed(),
d->bind2Bound.has_value(),
d->authenticationMethod == AuthenticationMethod::Sasl2 && d->fastTokenManager.tokenChanged(),
d->authenticationMethod,
};
d->bind2Bound.reset();

Expand Down Expand Up @@ -645,6 +649,7 @@ void QXmppOutgoingClient::handleStreamFeatures(const QXmppStreamFeatures &featur
if (std::holds_alternative<Success>(result)) {
debug(u"Authenticated"_s);
d->isAuthenticated = true;
d->authenticationMethod = AuthenticationMethod::Sasl;
handleStart();
} else {
auto [text, err] = std::get<SaslManager::AuthError>(std::move(result));
Expand Down
8 changes: 8 additions & 0 deletions src/client/QXmppOutgoingClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,18 @@ enum HandleElementResult {
Finished,
};

enum class AuthenticationMethod {
NonSasl,
Sasl,
Sasl2,
};

struct SessionBegin {
bool smEnabled;
bool smResumed;
bool bind2Used;
bool fastTokenChanged;
AuthenticationMethod authenticationMethod;
};

struct SessionEnd {
Expand Down
1 change: 1 addition & 0 deletions src/client/QXmppOutgoingClient_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ class QXmppOutgoingClientPrivate
bool isAuthenticated = false;
bool bindModeAvailable = false;
bool sessionStarted = false;
AuthenticationMethod authenticationMethod = AuthenticationMethod::Sasl;
std::optional<Bind2Bound> bind2Bound;

std::variant<QXmppOutgoingClient *, StarttlsManager, NonSaslAuthManager, SaslManager, Sasl2Manager, C2sStreamManager *, BindManager> listener;
Expand Down
2 changes: 2 additions & 0 deletions src/client/QXmppSaslManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ void FastTokenManager::onSasl2Authenticate(Sasl2::Authenticate &auth, const Sasl
};

requestedMechanism.reset();
m_tokenChanged = false;

if (feature.fast && isFastEnabled(config) && !hasToken()) {
// request token
Expand All @@ -356,6 +357,7 @@ void FastTokenManager::onSasl2Success(const Sasl2::Success &success)
success.token->token,
success.token->expiry,
};
m_tokenChanged = true;
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/client/QXmppSaslManager_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,12 @@ class FastTokenManager
bool hasToken() const;
void onSasl2Authenticate(Sasl2::Authenticate &auth, const Sasl2::StreamFeature &feature);
void onSasl2Success(const Sasl2::Success &success);
bool tokenChanged() const { return m_tokenChanged; }

private:
QXmppConfiguration &config;
std::optional<SaslHtMechanism> requestedMechanism;
bool m_tokenChanged = false;
};

} // namespace QXmpp::Private
Expand Down
2 changes: 2 additions & 0 deletions tests/qxmppsasl/tst_qxmppsasl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -939,6 +939,7 @@ void tst_QXmppSasl::sasl2Fast()
QVERIFY(task.isFinished());
auto success = expectFutureVariant<Sasl2::Success>(task);
fast.onSasl2Success(success);
QVERIFY(fast.tokenChanged());

QVERIFY(config.credentialData().htToken.has_value());
auto token = unwrap(config.credentialData().htToken);
Expand All @@ -963,6 +964,7 @@ void tst_QXmppSasl::sasl2Fast()
QVERIFY(task.isFinished());
success = expectFutureVariant<Sasl2::Success>(task);
fast.onSasl2Success(success);
QVERIFY(fast.tokenChanged());
token = unwrap(config.credentialData().htToken);
QCOMPARE(token.secret, u"t0k3n-rotation-token");
QCOMPARE(token.mechanism, SaslHtMechanism(IanaHashAlgorithm::Sha3_512, SaslHtMechanism::None));
Expand Down

0 comments on commit 2396889

Please sign in to comment.