{"id":345,"date":"2026-05-04T10:39:14","date_gmt":"2026-05-04T08:39:14","guid":{"rendered":"https:\/\/developer.ps\/?p=345"},"modified":"2026-09-22T20:52:17","modified_gmt":"2026-09-22T18:52:17","slug":"sms-password-reset-for-moodle-a-simple-plugin-approach","status":"publish","type":"post","link":"https:\/\/developer.ps\/index.php\/2026\/05\/04\/sms-password-reset-for-moodle-a-simple-plugin-approach\/","title":{"rendered":"SMS Password Reset for Moodle: A Simple Plugin Approach"},"content":{"rendered":"\r\n\n<p class=\"wp-block-paragraph\">Password reset in Moodle is traditionally email-based, but that doesn\u2019t always fit real-world usage, especially in mobile-first environments or regions where email access is inconsistent.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To address this, I built a lightweight plugin that enables <strong>SMS-based password reset<\/strong>:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&#x1f449; <a href=\"https:\/\/github.com\/dirar\/sms_password_reset\">https:\/\/github.com\/dirar\/sms_password_reset<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This post explains what it does, how it works, and where it fits best.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Why Add SMS Reset to Moodle?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Out of the box, Moodle relies on email for password recovery. That\u2019s fine in many cases, but it introduces friction:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Users don\u2019t always have reliable email access<\/li>\n\n\n\n<li>Reset emails can be delayed or flagged as spam<\/li>\n\n\n\n<li>Mobile users prefer phone-based verification<\/li>\n\n\n\n<li>Some deployments use phone numbers as the primary identifier<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Adding SMS support provides a more direct and accessible reset flow.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">What This Plugin Does<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This plugin adds an <strong>OTP-based password reset flow via SMS<\/strong>:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>User enters their phone number<\/li>\n\n\n\n<li>A one-time password (OTP) is generated<\/li>\n\n\n\n<li>OTP is sent via SMS<\/li>\n\n\n\n<li>User verifies the code<\/li>\n\n\n\n<li>User resets their password<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">It integrates into Moodle\u2019s authentication\/reset flow without breaking existing functionality.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">How It Works (High-Level)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The plugin keeps things simple and modular:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">&#x1f539; OTP Generation<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Short-lived code (e.g., 4\u20136 digits)<\/li>\n\n\n\n<li>Stored securely (hashed, not plain text)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">&#x1f539; SMS Delivery<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Works with external SMS gateways (configurable)<\/li>\n\n\n\n<li>Can be adapted for local providers<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">&#x1f539; Verification Layer<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Validates OTP<\/li>\n\n\n\n<li>Enforces expiration<\/li>\n\n\n\n<li>Limits retry attempts<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">&#x1f539; Password Update<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Allows reset only after successful verification<\/li>\n\n\n\n<li>Invalidates OTP immediately after use<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Security Considerations<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">SMS-based systems need careful handling. This plugin includes (or is designed to support):<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>OTP expiration<\/strong> (short validity window)<\/li>\n\n\n\n<li><strong>Rate limiting<\/strong> (prevent brute force attempts)<\/li>\n\n\n\n<li><strong>Hashed OTP storage<\/strong><\/li>\n\n\n\n<li><strong>One-time use enforcement<\/strong><\/li>\n\n\n\n<li><strong>Minimal user enumeration exposure<\/strong><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">You should still align it with your organization\u2019s security policies.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Integration with Moodle<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The plugin is designed to fit naturally into Moodle:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Hooks into the password reset process<\/li>\n\n\n\n<li>Can coexist with email reset (optional fallback)<\/li>\n\n\n\n<li>Configurable via Moodle admin settings<\/li>\n\n\n\n<li>Extendable for custom authentication flows<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">When This Is Useful<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This plugin is particularly helpful for:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Schools and institutions with mobile-first users<\/li>\n\n\n\n<li>Training platforms in regions with limited email usage<\/li>\n\n\n\n<li>Systems where phone number is the primary login<\/li>\n\n\n\n<li>Government or NGO deployments requiring simpler UX<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Possible Enhancements<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Depending on your use case, you might extend it with:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Multi-channel reset (SMS + email)<\/li>\n\n\n\n<li>Integration with national SMS gateways<\/li>\n\n\n\n<li>Logging and audit trails<\/li>\n\n\n\n<li>Admin dashboard for OTP monitoring<\/li>\n\n\n\n<li>Support for multi-factor authentication (MFA)<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Final Thoughts<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For many Moodle deployments, email-based password reset is no longer enough.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Adding SMS-based recovery improves:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Accessibility<\/li>\n\n\n\n<li>User experience<\/li>\n\n\n\n<li>Completion rates<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">This plugin is a simple way to introduce that capability without overengineering the solution.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Password reset in Moodle is traditionally email-based, but that doesn\u2019t always fit real-world usage, especially in mobile-first environments or regions where email access is inconsistent. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22,21],"tags":[],"class_list":["post-345","post","type-post","status-publish","format-standard","hentry","category-moodle","category-php"],"_links":{"self":[{"href":"https:\/\/developer.ps\/index.php\/wp-json\/wp\/v2\/posts\/345","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/developer.ps\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/developer.ps\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/developer.ps\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/developer.ps\/index.php\/wp-json\/wp\/v2\/comments?post=345"}],"version-history":[{"count":2,"href":"https:\/\/developer.ps\/index.php\/wp-json\/wp\/v2\/posts\/345\/revisions"}],"predecessor-version":[{"id":348,"href":"https:\/\/developer.ps\/index.php\/wp-json\/wp\/v2\/posts\/345\/revisions\/348"}],"wp:attachment":[{"href":"https:\/\/developer.ps\/index.php\/wp-json\/wp\/v2\/media?parent=345"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/developer.ps\/index.php\/wp-json\/wp\/v2\/categories?post=345"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/developer.ps\/index.php\/wp-json\/wp\/v2\/tags?post=345"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}