- Posts: 6
Bug report - Joomdle 3.1.1 intercepts Joomla Web Services API requests and redir
- Bojan Atanasijevic
- Topic Author
- Offline
- New Member
-
Less
More
6 days 7 hours ago - 6 days 7 hours ago #1
by Bojan Atanasijevic
Bug report - Joomdle 3.1.1 intercepts Joomla Web Services API requests and redir was created by Bojan Atanasijevic
Hi Antonio,
I do not know whet to put bug report, so I decided to post it here.
I believe (with a little help of ChatGPT) I have found a compatibility issue in Joomdle 3.1.1 with the Joomla Web Services API.
Environment:
Joomla: 5.4.8
Joomdle: 3.1.1
Moodle: 4.5.13+
Joomla API authentication: Bearer token
Joomdle SSO: Redirect SSO
Redirect-less SSO: Disabled
Joomdle MFA SSO plugin: Disabled
Problem:
I have a C# application which uses the Joomla REST API to manage Joomla users.
For example, I make the following request:
GET /api/index.php/v1/users?filter[search]=user@example.com
Authorization: Bearer <token>
Accept: application/vnd.api+json
With Joomdle disabled, the Joomla API works correctly and returns the expected JSON response.
However, as soon as the Joomdle - User plugin is enabled, the same API request no longer returns JSON.
Instead, Joomla returns an HTML page which redirects the request to Moodle:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Redirecting to Moodle</title>
</head>
<body>
<form id="joomdle-post-redirect"
action="https://my-moodle-site/auth/joomdle/land.php"
method="post">
<input type="hidden" name="username" value="...">
<input type="hidden" name="token" value="...">
<input type="hidden" name="use_wrapper" value="0">
<input type="hidden" name="create_user" value="0">
<input type="hidden"
name="wantsurl"
value="/api/index.php/v1/users?filter[search]=...">
</form>
<script>
document.getElementById('joomdle-post-redirect').submit();
</script>
</body>
</html>
The important part is that this also happens with other Joomla API endpoints, for example:
GET /api/index.php/v1/config/application
So the problem is not related specifically to the /users endpoint or to filter[search].
Reproduction:
I narrowed the issue down to the Joomdle - User plugin.
Disable all Joomdle plugins.
Call the Joomla REST API using a valid Bearer token.
The API works normally and returns JSON.
Enable only the Joomdle - User plugin.
Make exactly the same API request.
The response is now an HTML page redirecting to Moodle SSO.
I also tested creating a Joomla user through the REST API.
With the Joomdle User plugin enabled, the user synchronization itself works correctly: the Joomla user is created and Joomdle successfully propagates the user to Moodle.
The problem is therefore specifically the SSO redirect being triggered by an API authentication request.
Suspected cause:
I believe the problem is in the doLogin() method in:
plugins/user/joomdle/src/Extension/joomdle.php
The method is called from onUserAfterLogin():
public function onUserAfterLogin(AfterLoginEvent $event): void
{
if ($this->params->get('login_event_to_hook', 'onUserAfterLogin') != 'onUserAfterLogin') {
return;
}
$options = $event->getOptions();
$user = $options;
$username = $user->username;
$this->doLogin($username, $options);
}
doLogin() eventually performs the Moodle SSO redirect:
ContentHelper::redirectToMoodleWithPost(
$moodle_url . '/auth/joomdle/land.php',
[
'username' => $username,
'token' => $token,
'use_wrapper' => 0,
'create_user' => 0,
'wantsurl' => $login_url,
]
);
There does not appear to be a check to distinguish a normal Joomla site login from a Joomla Web Services API authentication.
As a result, an authenticated API request triggers the Joomdle SSO mechanism, which changes the expected REST API response from JSON into an HTML redirect.
Workaround:
I tested the following change at the beginning of doLogin():
private function doLogin($username, $options = array())
{
$app = Factory::getApplication();
if (array_key_exists('skip_joomdleuserplugin', $options)) {
return;
}
// Do not perform Joomdle SSO for Joomla API requests.
if ($app->isClient('api')) {
return;
}
if ($app->isClient('administrator')) {
return true;
}
// ...
}
With this change:
Joomla REST API requests return JSON normally.
Joomla users can still be created through the REST API.
Joomdle still synchronizes newly created users to Moodle.
Normal Joomla browser login still performs Joomdle SSO to Moodle.
So this appears to be a safe and effective workaround.
Expected behaviour:
Joomdle should probably not perform the Moodle SSO redirect when the Joomla application client is the Web Services API.
For example:
if ($app->isClient('api')) {
return;
}
could potentially be added before the SSO logic in doLogin().
I would appreciate your thoughts on whether this should be handled inside Joomdle or whether there is another recommended Joomla API-specific mechanism that Joomdle should use.
Thank you for the great work on Joomdle 3.1.1, and please let me know if you need any additional information or testing.
PS: Sorry for not using code tags for code, it did not work well for me.
Best,
Bojan
I do not know whet to put bug report, so I decided to post it here.
I believe (with a little help of ChatGPT) I have found a compatibility issue in Joomdle 3.1.1 with the Joomla Web Services API.
Environment:
Joomla: 5.4.8
Joomdle: 3.1.1
Moodle: 4.5.13+
Joomla API authentication: Bearer token
Joomdle SSO: Redirect SSO
Redirect-less SSO: Disabled
Joomdle MFA SSO plugin: Disabled
Problem:
I have a C# application which uses the Joomla REST API to manage Joomla users.
For example, I make the following request:
GET /api/index.php/v1/users?filter[search]=user@example.com
Authorization: Bearer <token>
Accept: application/vnd.api+json
With Joomdle disabled, the Joomla API works correctly and returns the expected JSON response.
However, as soon as the Joomdle - User plugin is enabled, the same API request no longer returns JSON.
Instead, Joomla returns an HTML page which redirects the request to Moodle:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Redirecting to Moodle</title>
</head>
<body>
<form id="joomdle-post-redirect"
action="https://my-moodle-site/auth/joomdle/land.php"
method="post">
<input type="hidden" name="username" value="...">
<input type="hidden" name="token" value="...">
<input type="hidden" name="use_wrapper" value="0">
<input type="hidden" name="create_user" value="0">
<input type="hidden"
name="wantsurl"
value="/api/index.php/v1/users?filter[search]=...">
</form>
<script>
document.getElementById('joomdle-post-redirect').submit();
</script>
</body>
</html>
The important part is that this also happens with other Joomla API endpoints, for example:
GET /api/index.php/v1/config/application
So the problem is not related specifically to the /users endpoint or to filter[search].
Reproduction:
I narrowed the issue down to the Joomdle - User plugin.
Disable all Joomdle plugins.
Call the Joomla REST API using a valid Bearer token.
The API works normally and returns JSON.
Enable only the Joomdle - User plugin.
Make exactly the same API request.
The response is now an HTML page redirecting to Moodle SSO.
I also tested creating a Joomla user through the REST API.
With the Joomdle User plugin enabled, the user synchronization itself works correctly: the Joomla user is created and Joomdle successfully propagates the user to Moodle.
The problem is therefore specifically the SSO redirect being triggered by an API authentication request.
Suspected cause:
I believe the problem is in the doLogin() method in:
plugins/user/joomdle/src/Extension/joomdle.php
The method is called from onUserAfterLogin():
public function onUserAfterLogin(AfterLoginEvent $event): void
{
if ($this->params->get('login_event_to_hook', 'onUserAfterLogin') != 'onUserAfterLogin') {
return;
}
$options = $event->getOptions();
$user = $options;
$username = $user->username;
$this->doLogin($username, $options);
}
doLogin() eventually performs the Moodle SSO redirect:
ContentHelper::redirectToMoodleWithPost(
$moodle_url . '/auth/joomdle/land.php',
[
'username' => $username,
'token' => $token,
'use_wrapper' => 0,
'create_user' => 0,
'wantsurl' => $login_url,
]
);
There does not appear to be a check to distinguish a normal Joomla site login from a Joomla Web Services API authentication.
As a result, an authenticated API request triggers the Joomdle SSO mechanism, which changes the expected REST API response from JSON into an HTML redirect.
Workaround:
I tested the following change at the beginning of doLogin():
private function doLogin($username, $options = array())
{
$app = Factory::getApplication();
if (array_key_exists('skip_joomdleuserplugin', $options)) {
return;
}
// Do not perform Joomdle SSO for Joomla API requests.
if ($app->isClient('api')) {
return;
}
if ($app->isClient('administrator')) {
return true;
}
// ...
}
With this change:
Joomla REST API requests return JSON normally.
Joomla users can still be created through the REST API.
Joomdle still synchronizes newly created users to Moodle.
Normal Joomla browser login still performs Joomdle SSO to Moodle.
So this appears to be a safe and effective workaround.
Expected behaviour:
Joomdle should probably not perform the Moodle SSO redirect when the Joomla application client is the Web Services API.
For example:
if ($app->isClient('api')) {
return;
}
could potentially be added before the SSO logic in doLogin().
I would appreciate your thoughts on whether this should be handled inside Joomdle or whether there is another recommended Joomla API-specific mechanism that Joomdle should use.
Thank you for the great work on Joomdle 3.1.1, and please let me know if you need any additional information or testing.
PS: Sorry for not using code tags for code, it did not work well for me.
Best,
Bojan
Last edit: 6 days 7 hours ago by Bojan Atanasijevic.
Please Log in or Create an account to join the conversation.
- Antonio Durán
-
- Offline
- Moderator
-
Less
More
- Posts: 7948
6 days 3 hours ago #2
by Antonio Durán
Replied by Antonio Durán on topic Bug report - Joomdle 3.1.1 intercepts Joomla Web Services API requests and redir
Hi.
Thanks for the bug report.
This has been recently fixed in the current code in github:
github.com/aduranterres/pkg_joomdle/comm...7acd9c2fd39949d62a58
The fix will be included in the next release.
It basically does the same as you did: skip any non front-end logins (including API)
Thanks for the bug report.
This has been recently fixed in the current code in github:
github.com/aduranterres/pkg_joomdle/comm...7acd9c2fd39949d62a58
The fix will be included in the next release.
It basically does the same as you did: skip any non front-end logins (including API)
Please Log in or Create an account to join the conversation.