feat: Enhanced OIDC Admin Login module

Refactored the OIDC Admin Login for WHMCS to improve usability and configuration management. The module now supports dynamic configuration via the WHMCS admin interface, removing the need for manual edits to a config file. This change facilitates easier module activation, configuration, and management directly from the WHCMS admin panel.

Key changes include:
- Transitioned the installation path to the more appropriate `/modules/addons` directory.
- Eliminated the `config.dist.php` file in favor of storing configuration details in the database, which are set through the WHMCS admin UI.
- Added admin UI components for module activation and configuration, including fields for OIDC provider URL, client ID, client secret, OIDC claim, and OIDC scopes.
- Introduced a login handler script that dynamically fetches configuration from the database, authenticates users via their OIDC provider, and handles session setup within WHMCS based on the `preferred_username` claim.
- Implemented instructional comments and setup guidelines in README to guide users through the new installation and configuration process.

This upgrade streamlines the setup process for administrators and strengthens the module's integration with WHMCS, making it more accessible and easier to manage.
This commit is contained in:
Kumi 2024-04-27 15:17:12 +02:00
parent 07d80ba0af
commit 83e171bc5d
Signed by: kumi
GPG key ID: ECBCC9082395383F
4 changed files with 177 additions and 75 deletions

View file

@ -1,18 +1,14 @@
# Simple WHMCS OIDC Admin Login
# WHMCS OIDC Admin Login Module
This is a simple WHMCS OIDC Admin Login module that allows WHMCS administrators
to login to the WHMCS admin area using an OIDC provider.
It is not a full-fledged WHMCS module (yet), but so far only a script that
allows WHMCS administrators to login to the WHMCS admin area using an OIDC
provider.
It will redirect the user to the OIDC provider's login page, log the user in
based on the `preferred_username` claim, and redirect the user back to the WHMCS
admin area.
## Disclaimer
The module was developed as a proof of concept and is not intended for
production use. It may have security vulnerabilities and may not work as
expected.
This module is provided as-is, not supported, and not endorsed by WHMCS. Use it
at your own risk.
@ -21,26 +17,42 @@ at your own risk.
1. Install the module by uploading it to your WHMCS installation directory.
```bash
cd /path/to/whmcs/modules/security
git clone https://git.private.coffee/kumisystems/whmcs-oidc_admin_login.git
cd whmcs-oidc_admin_login
cd /path/to/whmcs/modules/addons
git clone https://git.private.coffee/kumisystems/whmcs-oidc_admin_login.git oidc_admin_login
cd oidc_admin_login
composer install
cp config.dist.php config.php
```
2. Configure the module by editing the `config.php` file.
2. Enable the module in the WHMCS admin area.
- Go to `Setup` -> 'System Settings' -> `Addon Modules`. (https://your-whmcs-domain.com/admin/configaddonmods.php)
- Click on `Activate` next to `OIDC Admin Login`.
- Click on `Configure` next to `OIDC Admin Login`.
- Enter the OIDC provider configuration details in the form.
- Click on `Save Changes`.
## Usage
You can access the OIDC Admin Login page by visiting the following URL:
```
https://your-whmcs-domain.com/modules/security/oidc_admin_login.php
https://your-whmcs-domain.com/modules/addons/oidc_admin_login/login.php
```
If you are not logged in, you will be redirected to the OIDC provider login
page. After you have logged in, you will be redirected back to the WHMCS admin
area.
After you have logged in, you will be redirected back to the WHMCS admin area.
Unfortunately, there doesn't seem to be a way to hook into the WHMCS login
process to automatically redirect the user to the OIDC login page. You can
instead configure your web server to redirect the user to the OIDC login page
when they visit the WHMCS admin login page. For example, you can add the
following to your nginx configuration:
```nginx
location = /admin/login.php {
return 301 /modules/addons/oidc_admin_login/login.php;
}
```
## License

View file

@ -1,11 +0,0 @@
<?php
if (!defined("WHMCS")) {
die("This file cannot be accessed directly");
}
// OIDC Provider details
$oidcProviderUrl = 'https://kumidc.local'; // The URL of your OIDC Provider
$clientID = '123456'; // Your OIDC Client ID
$clientSecret = 'thisisaverylongsecretstring'; // Your OIDC Client Secret

89
login.php Normal file
View file

@ -0,0 +1,89 @@
<?php
/*
* This file is part of a project developed by Kumi Systems e.U.
*
* Copyright (c) 2023 Kumi Systems e.U.
*
* This software is released under the MIT License.
* See the LICENSE file in the project root for more information.
*/
// Error reporting
error_reporting(E_ALL);
ini_set('display_errors', 1);
require_once 'vendor/autoload.php';
require_once "../../../init.php";
use Jumbojett\OpenIDConnectClient;
use WHMCS\Database\Capsule;
// Check if the module is activated
$moduleActivated = Capsule::table('tbladdonmodules')
->where('module', '=', 'oidc_admin_login')
->count() > 0;
if (!$moduleActivated) {
// Handle the error case where the module is not activated
error_log("OIDC SSO login failed: Module not activated");
die("OIDC SSO login failed: Module not activated");
}
// Fetch the module configuration
$moduleConfig = Capsule::table('tbladdonmodules')
->where('module', '=', 'oidc_admin_login')
->get();
$oidcProviderUrl = $moduleConfig->where('setting', '=', 'oidcProviderUrl')->first()->value;
$clientID = $moduleConfig->where('setting', '=', 'clientId')->first()->value;
$clientSecret = $moduleConfig->where('setting', '=', 'clientSecret')->first()->value;
$oidcScopes = $moduleConfig->where('setting', '=', 'oidcScopes')->first()->value;
$oidcClaim = $moduleConfig->where('setting', '=', 'oidcClaim')->first()->value;
$oidcScopes = explode(',', $oidcScopes);
// Initialize the OIDC client
$oidc = new OpenIDConnectClient($oidcProviderUrl, $clientID, $clientSecret);
$oidc->addScope($oidcScopes);
try {
// Authenticate the user with the OIDC provider
$oidc->authenticate();
// Fetch the user's details
$userInfo = $oidc->requestUserInfo();
// Get the value of the claim to use as the WHMCS username
if (isset($userInfo->$oidcClaim)) {
$username = $userInfo->$oidcClaim;
// Initialize WHMCS authentication class
$auth = new WHMCS\Auth();
// Attempt to find and authenticate the user by username
if ($auth->getInfobyUsername($username)) {
// Set session variables for the logged-in user
$auth->setSessionVars();
$redirectUri = '/admin/';
// TODO: Preserve the original redirect URL
header('Location: ' . $redirectUri);
exit;
} else {
// Handle the error case where the username doesn't exist in WHMCS
error_log("OIDC SSO login failed: Username not found in WHMCS");
// TODO: Redirect to a failure page
die("OIDC SSO login failed: Username not found in WHMCS");
}
} else {
// Handle missing username claim
error_log("OIDC SSO login failed: Username claim not found in user info");
exit;
}
} catch (Exception $e) {
// Handle errors, such as authentication failures
error_log("OIDC SSO login error: " . $e->getMessage());
die("OIDC SSO login error: " . $e->getMessage());
}

View file

@ -1,51 +1,63 @@
<?php
require_once 'vendor/autoload.php';
require_once "../../../init.php";
require_once "config.php";
use Jumbojett\OpenIDConnectClient;
// Initialize the OIDC client
$oidc = new OpenIDConnectClient($oidcProviderUrl, $clientID, $clientSecret);
$oidc->addScope(['openid', 'email', 'profile']);
try {
// Authenticate the user with the OIDC provider
$oidc->authenticate();
// Fetch the user's details
$userInfo = $oidc->requestUserInfo();
// The 'preferred_username' claim will be used as the WHMCS username
if (isset($userInfo->preferred_username)) {
$username = $userInfo->preferred_username;
// Initialize WHMCS authentication class
$auth = new WHMCS\Auth();
// Attempt to find and authenticate the user by username
if ($auth->getInfobyUsername($username)) {
// Set session variables for the logged-in user
$auth->setSessionVars();
$redirectUri = '/admin/';
header('Location: ' . $redirectUri);
exit;
} else {
// Handle the error case where the username doesn't exist in WHMCS
error_log("OIDC SSO login failed: Username not found in WHMCS");
// TODO: Redirect to a failure page
die("OIDC SSO login failed: Username not found in WHMCS");
}
} else {
// Handle missing username claim
error_log("OIDC SSO login failed: Username claim not found in user info");
exit;
}
} catch (Exception $e) {
// Handle errors, such as authentication failures
error_log("OIDC SSO login error: " . $e->getMessage());
die("OIDC SSO login error: " . $e->getMessage());
function oidc_admin_login_config()
{
// Plugin details displayed by WHMCS
return [
'name' => 'OIDC Admin Login',
'description' => 'This module provides an OpenID Connect based single sign-on (SSO) solution for WHMCS admin users.',
'version' => '0.1',
'author' => 'Kumi Systems e.U.',
'fields' => [
// Configuration fields for the module
// Displayed in WHMCS admin area under Addon Modules and used to store OIDC provider details
'oidcProviderUrl' => [
'FriendlyName' => 'OIDC Provider URL',
'Type' => 'text',
'Size' => '25',
'Default' => '',
'Description' => 'Enter the URL of your OIDC provider.',
],
'clientId' => [
'FriendlyName' => 'Client ID',
'Type' => 'text',
'Size' => '25',
'Default' => '',
'Description' => 'Enter the client ID provided by your OIDC provider.',
],
'clientSecret' => [
'FriendlyName' => 'Client Secret',
'Type' => 'password',
'Size' => '25',
'Default' => '',
'Description' => 'Enter the client secret provided by your OIDC provider.',
],
'oidcClaim' => [
'FriendlyName' => 'OIDC Claim',
'Type' => 'text',
'Size' => '25',
'Default' => 'preferred_username',
'Description' => 'Enter the OIDC claim to use as the WHMCS username.',
],
'oidcScopes' => [
'FriendlyName' => 'OIDC Scopes',
'Type' => 'text',
'Size' => '25',
'Default' => 'openid,email,profile',
'Description' => 'Enter the OIDC scopes to request from the provider, separated by commas.',
],
],
];
}
function oidc_admin_login_activate()
{
// Code to execute when the module is activated
return ['status' => 'success', 'description' => 'OIDC Admin Login activated successfully'];
}
function oidc_admin_login_deactivate()
{
// Code to execute when the module is deactivated
return ['status' => 'success', 'description' => 'OIDC Admin Login deactivated successfully'];
}