Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make password fully random #3

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Aside from importing the release zip through the Moodle admin page, your Moodle
- `MOODLE_JWT_ISSUER`: The authority issuing the expected JWTs.
- `MOODLE_JWT_CHECK_CLIENT`: Whether to check the JWT's client.
- `MOODLE_JWT_CLIENT`: The client ID for your SSO realm.
- `MOODLE_JWT_ASSIGN_RANDOM_PASSWORD`: If `true` will generate a random local password for the user, required by Moodle 4.3 and up.

The plugin can also handle username assignment, but this is usually for special situation where you'd like a specific property to be used. Additionally, special characters can be removed through a regular expression.

Expand Down
60 changes: 33 additions & 27 deletions auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*
* @package auth_jwt
* @author Trey Hayden <[email protected]>
* Milt Reder <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
*/

Expand Down Expand Up @@ -71,6 +72,36 @@ public function loginpage_hook() {
$this->attempt_jwt_login();
}

private function generateRandomPassword($length = 12) {
$characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_=+';
$charactersLength = strlen($characters);
$randomPassword = '';
for ($i = 0; $i < $length; $i++) {
$randomPassword .= $characters[random_int(0, $charactersLength - 1)];
}

// Ensure the password meets Moodle's requirements
// At least one lowercase letter
if (!preg_match('/[a-z]/', $randomPassword)) {
$randomPassword .= 'a';
}
// At least one uppercase letter
if (!preg_match('/[A-Z]/', $randomPassword)) {
$randomPassword .= 'A';
}
// At least one digit
if (!preg_match('/\d/', $randomPassword)) {
$randomPassword .= '1';
}
// At least one special character
if (!preg_match('/[\W_]/', $randomPassword)) {
$randomPassword .= '!';
}

// Shuffle the password to ensure randomness
return str_shuffle($randomPassword);
}

private function attempt_jwt_login() {
global $CFG, $DB;

Expand Down Expand Up @@ -155,34 +186,9 @@ private function attempt_jwt_login() {
if ($this->has_env_bool("MOODLE_JWT_ASSIGN_RANDOM_PASSWORD")) {

/**
* The "salt" here will simply be a character block to satisfy password reqs.
*
* There are several fairly random properties to choose from, but we will leave
* the specification to the configuration folks. If not specified, then we will
* use JWT-standard properties in their place.
* Assign a random password that meets Moodle's requirements
*/
$requirementSalt = "aA_12345678";

$envPropertyFirst = getenv("MOODLE_JWT_ASSIGN_RANDOM_PASSWORD_PROPERTY_FIRST");
$envPropertySecond = getenv("MOODLE_JWT_ASSIGN_RANDOM_PASSWORD_PROPERTY_SECOND");

$firstChunk = $payload->sub;
$secondChunk = $payload->iss;

if ($envPropertyFirst != false) {
if (property_exists($payload, $envPropertyFirst)) {
$firstChunk = $payload->$envPropertyFirst;
}
}

if ($envPropertySecond != false) {
if (property_exists($payload, $envPropertySecond)) {
$secondChunk = $payload->$envPropertySecond;
}
}


$password = time() . $firstChunk . $secondChunk . $requirementSalt;
$password = $this->generateRandomPassword();
}

$user = create_user_record($username, $password, "jwt");
Expand Down