add debug for sso issue and display error on request failed

This commit is contained in:
Gaelle Braud 2026-03-03 12:12:26 +01:00
parent 91534868b6
commit e23afaf0de
5 changed files with 73 additions and 24 deletions

View file

@ -368,6 +368,7 @@ void App::setSelf(QSharedPointer<App>(me)) {
bool askForConfirmation) {
mCoreModelConnection->invokeToCore([this, path, askForConfirmation]() {
auto apply = [this, path] {
lInfo() << log().arg("Apply fetch config");
mCoreModelConnection->invokeToModel([this, path]() { CoreModel::getInstance()->setFetchConfig(path); });
};
auto callback = [this, path, askForConfirmation]() {
@ -385,9 +386,10 @@ void App::setSelf(QSharedPointer<App>(me)) {
QMetaObject::invokeMethod(getMainWindow(), "showConfirmationPopup", QVariant::fromValue(obj));
};
if (!getMainWindow()) { // Delay
if (askForConfirmation)
if (askForConfirmation) {
lInfo() << log() << "App wants confirmation before applying config, wait for main window to open";
connect(this, &App::mainWindowChanged, this, callback, Qt::SingleShotConnection);
else connect(this, &App::mainWindowChanged, this, apply, Qt::SingleShotConnection);
} else connect(this, &App::mainWindowChanged, this, apply, Qt::SingleShotConnection);
} else {
if (askForConfirmation) callback();
else apply();
@ -398,6 +400,7 @@ void App::setSelf(QSharedPointer<App>(me)) {
&CoreModel::globalStateChanged,
[this](const std::shared_ptr<linphone::Core> &core, linphone::GlobalState gstate, const std::string &message) {
mCoreModelConnection->invokeToCore([this, gstate] {
lInfo() << log().arg("Core global state changed :") << (int)gstate;
setCoreStarted(gstate == linphone::GlobalState::On);
if (gstate == linphone::GlobalState::Configuring) {
if (mMainWindow) {
@ -465,6 +468,7 @@ void App::setSelf(QSharedPointer<App>(me)) {
// Synchronize state for because linphoneCore was ran before any connections.
mCoreModelConnection->invokeToModel([this]() {
auto state = CoreModel::getInstance()->getCore()->getGlobalState();
lInfo() << log().arg("Start app, core global state =") << (int)state;
mCoreModelConnection->invokeToCore([this, state] {
setCoreStarted(state == linphone::GlobalState::On);
if (state == linphone::GlobalState::Configuring) {
@ -547,6 +551,10 @@ void App::setSelf(QSharedPointer<App>(me)) {
emit remainingTimeBeforeOidcTimeoutChanged();
});
});
mCoreModelConnection->makeConnectToModel(&CoreModel::oidcRequestFailed, [this](const QString &error) {
mCoreModelConnection->invokeToCore(
[this, error] { Utils::showInformationPopup("info_popup_error_title", error, false); });
});
mCoreModelConnection->makeConnectToCore(&App::lForceOidcTimeout, [this] {
qDebug() << "App: force oidc timeout";
mCoreModelConnection->invokeToModel([this] { emit CoreModel::getInstance()->forceOidcTimeout(); });
@ -1421,6 +1429,7 @@ void App::onAuthenticationRequested(const std::shared_ptr<linphone::Core> &core,
const std::shared_ptr<linphone::AuthInfo> &authInfo,
linphone::AuthMethod method) {
bool authInfoIsInAccounts = false;
lInfo() << log().arg("onAuthenticationRequested, method =") << (int)method;
if (authInfo) {
for (auto &account : core->getAccountList()) {
if (!account) continue;

View file

@ -49,12 +49,12 @@ QString OAuthHttpServerReplyHandler::callback() const {
OIDCModel::OIDCModel(const std::shared_ptr<linphone::AuthInfo> &authInfo, QObject *parent) {
auto port = CoreModel::getInstance()->getCore()->getConfig()->getInt("app", "oidc_redirect_uri_port", 0);
qDebug() << "OIDC Redirect URI Port set to [" << port << "]";
lInfo() << "OIDC Redirect URI Port set to [" << port << "]";
auto replyHandler = new OAuthHttpServerReplyHandler(port, this);
if (!replyHandler->isListening()) {
lWarning() << log().arg("OAuthHttpServerReplyHandler is not listening on port") << port;
emit requestFailed(tr("OAuthHttpServerReplyHandler is not listening"));
emit finished();
// emit finished();
return;
}
mAuthInfo = authInfo;
@ -72,12 +72,12 @@ OIDCModel::OIDCModel(const std::shared_ptr<linphone::AuthInfo> &authInfo, QObjec
}
mOidc.setClientIdentifier(clientid);
mAuthInfo->setClientId(clientid.toStdString());
qDebug() << "OIDC Client ID set to [" << clientid << "]";
lInfo() << "OIDC Client ID set to [" << clientid << "]";
// find an auth info from LinphoneCore where username = clientid
auto clientSecret = CoreModel::getInstance()->getCore()->findAuthInfo("", clientid.toStdString(), "");
if (clientSecret != nullptr) {
qDebug() << "client secret found for client id [" << clientid << "]";
lInfo() << "client secret found for client id [" << clientid << "]";
mOidc.setClientIdentifierSharedKey(clientSecret->getPassword().c_str());
}
@ -121,6 +121,7 @@ OIDCModel::OIDCModel(const std::shared_ptr<linphone::AuthInfo> &authInfo, QObjec
connect(&mOidc, &QOAuth2AuthorizationCodeFlow::statusChanged, [=](QAbstractOAuth::Status status) {
switch (status) {
case QAbstractOAuth::Status::Granted: {
lInfo() << log().arg("Authentication granted");
stopTimeoutTimer();
//: Authentication granted
emit statusChanged(tr("oidc_authentication_granted_message"));
@ -128,6 +129,7 @@ OIDCModel::OIDCModel(const std::shared_ptr<linphone::AuthInfo> &authInfo, QObjec
break;
}
case QAbstractOAuth::Status::NotAuthenticated: {
lInfo() << log().arg("Not authenticated");
stopTimeoutTimer();
//: Not authenticated
emit statusChanged(tr("oidc_authentication_not_authenticated_message"));
@ -135,11 +137,13 @@ OIDCModel::OIDCModel(const std::shared_ptr<linphone::AuthInfo> &authInfo, QObjec
break;
}
case QAbstractOAuth::Status::RefreshingToken: {
lInfo() << log().arg("Refreshing token");
//: Refreshing token
emit statusChanged(tr("oidc_authentication_refresh_message"));
break;
}
case QAbstractOAuth::Status::TemporaryCredentialsReceived: {
lInfo() << log().arg("Temporary credentials received");
//: Temporary credentials received
emit statusChanged(tr("oidc_authentication_temporary_credentials_message"));
break;
@ -158,22 +162,27 @@ OIDCModel::OIDCModel(const std::shared_ptr<linphone::AuthInfo> &authInfo, QObjec
lWarning() << log().arg("RequestFailed:") << metaEnum.valueToKey(static_cast<int>(error));
switch (error) {
case QAbstractOAuth::Error::NetworkError:
lWarning() << log().arg("Network error");
//: Network error
emit requestFailed(tr("oidc_authentication_network_error"));
break;
case QAbstractOAuth::Error::ServerError:
lWarning() << log().arg("Server error");
//: Server error
emit requestFailed(tr("oidc_authentication_server_error"));
break;
case QAbstractOAuth::Error::OAuthTokenNotFoundError:
lWarning() << log().arg("OAuth token not found");
//: OAuth token not found
emit requestFailed(tr("oidc_authentication_token_not_found_error"));
break;
case QAbstractOAuth::Error::OAuthTokenSecretNotFoundError:
lWarning() << log().arg("OAuth token secret not found");
//: OAuth token secret not found
emit requestFailed(tr("oidc_authentication_token_secret_not_found_error"));
break;
case QAbstractOAuth::Error::OAuthCallbackNotVerified:
lWarning() << log().arg("OAuth callback not verified");
//: OAuth callback not verified
emit requestFailed(tr("oidc_authentication_callback_not_verified_error"));
break;
@ -185,7 +194,7 @@ OIDCModel::OIDCModel(const std::shared_ptr<linphone::AuthInfo> &authInfo, QObjec
connect(&mOidc, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, [this](const QUrl &url) {
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
qDebug() << "Browser authentication url : " << url;
lInfo() << "Browser authentication url : " << url;
//: Requesting authorization from browser
emit statusChanged(tr("oidc_authentication_request_auth_message"));
mTimeout.start();
@ -222,7 +231,7 @@ OIDCModel::OIDCModel(const std::shared_ptr<linphone::AuthInfo> &authInfo, QObjec
mIdToken.clear();
lWarning() << "No ID Token or Access Token found in the tokens.";
emit requestFailed(tr("oidc_authentication_no_token_found_error"));
emit finished();
// emit finished();
}
});
#endif
@ -258,9 +267,9 @@ OIDCModel::OIDCModel(const std::shared_ptr<linphone::AuthInfo> &authInfo, QObjec
});
connect(this, &OIDCModel::finished, this, &OIDCModel::deleteLater);
auto url = QUrl(Utils::coreStringToAppString(authInfo->getAuthorizationServer()));
url.setPath(url.path() + OIDCWellKnown);
lInfo() << log().arg("Get request") << url;
QNetworkRequest request(url);
auto reply = mOidc.networkAccessManager()->get(request);
connect(reply, &QNetworkReply::finished, this, &OIDCModel::openIdConfigReceived);
@ -290,9 +299,17 @@ void OIDCModel::stopTimeoutTimer() {
}
void OIDCModel::openIdConfigReceived() {
lInfo() << log().arg("OpenID config received");
auto reply = dynamic_cast<QNetworkReply *>(sender());
lInfo() << log().arg("Reply :") << reply->readAll();
auto document = QJsonDocument::fromJson(reply->readAll());
if (document.isNull()) return;
if (document.isNull()) {
lWarning() << log().arg("Reply is empty");
//: OIDC reply is empty !
emit requestFailed(tr("oidc_authentication_empty_reply_error"));
// emit finished();
return;
}
auto rootArray = document.toVariant().toMap();
if (rootArray.contains("authorization_endpoint")) {
mOidc.setAuthorizationUrl(QUrl(rootArray["authorization_endpoint"].toString()));
@ -300,10 +317,11 @@ void OIDCModel::openIdConfigReceived() {
lWarning() << log().arg("No authorization endpoint found in OpenID configuration");
//: No authorization endpoint found in OpenID configuration
emit requestFailed(tr("oidc_authentication_no_auth_found_in_config_error"));
emit finished();
// emit finished();
return;
}
if (rootArray.contains("token_endpoint")) {
lInfo() << log().arg("Set token url %1").arg(rootArray["token_endpoint"].toString());
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
mOidc.setTokenUrl(QUrl(rootArray["token_endpoint"].toString()));
#else
@ -315,9 +333,10 @@ void OIDCModel::openIdConfigReceived() {
lWarning() << log().arg("No token endpoint found in OpenID configuration");
//: No token endpoint found in OpenID configuration
emit requestFailed(tr("oidc_authentication_no_token_found_in_config_error"));
emit finished();
// emit finished();
return;
}
lInfo() << log().arg("Grant open id config");
mOidc.grant();
reply->deleteLater();
}
@ -325,7 +344,7 @@ void OIDCModel::openIdConfigReceived() {
void OIDCModel::setBearers() {
auto expiration = QDateTime::currentDateTime().secsTo(mOidc.expirationAt());
auto timeT = mOidc.expirationAt().toSecsSinceEpoch();
qDebug() << "Authenticated for " << expiration << "s";
lInfo() << "Authenticated for " << expiration << "s";
auto accessBearer = linphone::Factory::get()->createBearerToken(Utils::appStringToCoreString(idToken()), timeT);
mAuthInfo->setAccessToken(accessBearer);

View file

@ -128,12 +128,17 @@ void CliModel::cliShow(QHash<QString, QString> args) {
}
void CliModel::cliFetchConfig(QHash<QString, QString> args) {
lInfo() << log().arg("Run fetch-config function");
if (args.contains("fetch-config")) {
if (CoreModel::getInstance()->getCore()->getGlobalState() != linphone::GlobalState::On)
if (CoreModel::getInstance()->getCore()->getGlobalState() != linphone::GlobalState::On) {
lInfo() << log().arg("Global state is not on, wait for change of state to use config");
connect(
CoreModel::getInstance().get(), &CoreModel::globalStateChanged, this,
[this, args]() { cliFetchConfig(args); }, Qt::SingleShotConnection);
else CoreModel::getInstance()->useFetchConfig(args["fetch-config"], false);
} else {
lInfo() << log().arg("Global state is on, use config");
CoreModel::getInstance()->useFetchConfig(args["fetch-config"], false);
}
}
}
@ -240,7 +245,7 @@ void CliModel::Command::execute(QHash<QString, QString> &args, CliModel *parent)
if (!mGenericArguments) { // Check arguments validity.
for (const auto &argName : args.keys()) {
if (!mArgsScheme.contains(argName)) {
qWarning()
lWarning()
<< QStringLiteral("Command with invalid argument: `%1 (%2)`.").arg(mFunctionName).arg(argName);
return;

View file

@ -210,13 +210,14 @@ void CoreModel::setPathAfterStart() {
QString CoreModel::getFetchConfig(QString filePath, bool *error) {
*error = false;
lInfo() << log().arg("Get config %1").arg(filePath);
if (!filePath.isEmpty()) {
if (QUrl(filePath).isRelative()) { // this is a file path
filePath = Paths::getConfigFilePath(filePath, false);
if (!filePath.isEmpty()) filePath = "file://" + filePath;
}
if (filePath.isEmpty()) {
qWarning() << "Remote provisioning cannot be retrieved. Command have been cleaned";
lWarning() << "Remote provisioning path cannot be retrieved. Command have been cleaned";
Utils::showInformationPopup(tr("info_popup_error_title"),
//: "Remote provisioning cannot be retrieved"
tr("fetching_config_failed_error_message"), false);
@ -229,23 +230,28 @@ QString CoreModel::getFetchConfig(QString filePath, bool *error) {
void CoreModel::useFetchConfig(QString filePath, bool askForConfirmation) {
bool error = false;
filePath = getFetchConfig(filePath, &error);
lInfo() << log().arg("Use fetch config");
if (!error && !filePath.isEmpty()) {
if (mCore && mCore->getGlobalState() == linphone::GlobalState::On) {
// TODO
// if (mSettings->getAutoApplyProvisioningConfigUriHandlerEnabled()) setFetchConfig(filePath); else
lInfo() << log().arg("Request fetch config");
emit requestFetchConfig(filePath, askForConfirmation);
} else {
lInfo() << log().arg("Global state is off, wait for requesting fetch config");
connect(
this, &CoreModel::globalStateChanged, this, [filePath, this]() { useFetchConfig(filePath); },
this, &CoreModel::globalStateChanged, this,
[filePath, askForConfirmation, this]() { useFetchConfig(filePath, askForConfirmation); },
Qt::SingleShotConnection);
}
} else {
lWarning() << log().arg("Could not get file path for fetching config, return");
}
}
bool CoreModel::setFetchConfig(QString filePath) {
bool fetched = false;
qDebug() << "setFetchConfig with " << filePath;
lInfo() << "setFetchConfig with " << filePath;
if (!filePath.isEmpty()) {
if (mCore) {
filePath.replace('\\', '/');
@ -254,8 +260,11 @@ bool CoreModel::setFetchConfig(QString filePath) {
}
}
if (!fetched) {
qWarning() << "Remote provisionning cannot be retrieved. Command have been cleaned";
} else emit requestRestart();
lWarning() << "Remote provisionning cannot be retrieved. Command have been cleaned";
} else {
lInfo() << "Remote provisionning has been retrieved. Restart";
emit requestRestart();
}
return fetched;
}
@ -411,8 +420,8 @@ void CoreModel::onAuthenticationRequested(const std::shared_ptr<linphone::Core>
auto username = Utils::coreStringToAppString(authInfo->getUsername());
auto realm = Utils::coreStringToAppString(authInfo->getRealm());
if (!serverUrl.isEmpty()) {
qDebug() << "onAuthenticationRequested for Bearer. Initialize OpenID connection for " << username << "@"
<< realm << " at " << serverUrl;
lInfo() << "onAuthenticationRequested for Bearer. Initialize OpenID connection for " << username << "@"
<< realm << " at " << serverUrl;
QString key = username + '@' + realm + ' ' + serverUrl;
if (mOpenIdConnections.contains(key)) mOpenIdConnections[key]->deleteLater();
auto oidcModel = new OIDCModel(authInfo, this);
@ -422,6 +431,12 @@ void CoreModel::onAuthenticationRequested(const std::shared_ptr<linphone::Core>
emit timeoutTimerStarted();
qDebug() << "start refresh timer";
});
connect(oidcModel, &OIDCModel::requestFailed, this, [this, oidcModel](const QString &error) {
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
lWarning() << log().arg("Request failed") << error;
emit oidcRequestFailed(error);
oidcModel->forceTimeout();
});
if (oidcModel->isTimerRunning()) {
emit timeoutTimerStarted();
}

View file

@ -101,6 +101,7 @@ signals:
void messageReadInChatRoom(std::shared_ptr<linphone::ChatRoom> chatRoom);
void oidcRemainingTimeBeforeTimeoutChanged(int remainingTime);
void forceOidcTimeout();
void oidcRequestFailed(const QString &error);
void timeoutTimerStarted();
void timeoutTimerStopped();