Skip to content

Adds single-use passwords to WordPress emails' URLs for frictionless login.

Notifications You must be signed in to change notification settings

KitKatCarson/BH-WP-Autologin-URLs

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

56 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

WordPress tested 5.3 PHPCS WPCS License: GPL v2 or later PHPUnit Active installs

Autologin URLs

Adds single-use passwords to WordPress emails' URLs for frictionless login.

Overview

This plugin hooks into the wp_mail filter to augment existing URLs with login codes so users are automatically logged in when visiting the site through email links.

It is in use for a charity whose annual requests for donations to non-tech-savvy users was resulting in users unable to remember their password. Now those users are instantly logged in.

It should also help solve the problem with WooCommerce abandoned cart emails where the user must be logged in to know who abandoned the cart.

Also useful for logging users back in when they get reply notifications for their comments, bbPress posts etc.

This plugin makes no theme/user-facing changes.

Example Email Example email sent via Comment Reply Email Notification plugin.

Installation & Configuration

Install Autologin URLs from the WordPress plugin directory.

There is no configuration needed. By default:

  • Codes expire after seven days
  • Emails to admins do not get autologin codes added
  • Some emails are filtered out by subject using regex

The settings page can be found in the admin UI under Settings/Autologin URLs, as a link on the Plugins page, or at /wp-admin/options-general.php?page=bh-wp-autologin-urls.

Settings Page

Operation

  • Hooked on wp_mail
  • Login code consists of user id and random alphanumeric password separated by ~
  • Stored in WordPress database hashed as a transient with an expiration time
  • Deleted after a single use

Links take the form: https://brianhenry.ie/?autologin=582~Yxu1UQG8IwJO

Secure

The plugin conforms to all the suggesitions in the StackExchange discussion, Implementing an autologin link in an email:

  • Cryptographically Secure PseudoRandom Number Generation (via wp_rand)
  • Stored as SHA-256 hash
  • Codes are single use
  • Codes automatically expire

Additionally, authentication via Autologin URLs is disabled for 24 hours for users whose accounts have had five failed login attempts through an autologin URL and for IPs which have attempted and failed five times.

Warning: If you use any plugin to save copies of outgoing mail, those saved emails will contain autologin URLs.

Performant

  • The additional rows added as transients to the wp_options table will be proportionate to the number of emails sent
  • Additional database queries only occur when a URL with autologin= is visited
  • No database queries (beyond autoloaded settings) are performed if the autologin user is already logged in
  • Transients are queried by wp_options.option_name which is a UNIQUE column, i.e. indexed
  • Transients are deleted when they are used to login
  • WordPress, since v4.9, automatically purges expired transients

Tested

PHPUnit has been run with WordPress 5.3 on PHP 7.1 to 98% coverage.

API

Two filters are added to expose the main functionality to developers of other plugins (which don't use wp_mail()), e.g. for push notifications:

$url = apply_filters( 'add_autologin_to_url', $url, $user );
$message = apply_filters( 'add_autologin_to_message', $message, $user );

Filters to configure the expiry time, admin enabled setting and subject exclusion regex list are defined in the BH_WP_Autologin_URLs\wp_mail\WP_Mail class.

Instances of classes hooked in actions and filters are exposed as properties of BH_WP_Autologin_URLs class, accessible with:

/** @var BH_WP_Autologin_URLs\includes\BH_WP_Autologin_URLs $autologin_urls */
$autologin_urls = $GLOBALS['bh-wp-autologin-urls'];

API functions can be accessed through the api property of the main plugin class:

/** @var BH_WP_Autologin_URLs\api\API_Interface $autologin_urls_api */
$autologin_urls_api = $GLOBALS['bh-wp-autologin-urls']->api;

Develop

The plugin uses WordPress Plugin Boilerplate, wp-namespace-autoloader and Mozart composer dependency namespace prefixer, and follows WordPress Coding Standards.

To set up the development environment, run:

composer install

WordPress Coding Standards

The code mostly conforms to WPCS rules, except for :

  • Squiz.PHP.DisallowMultipleAssignments.Found used when making the plugin's hooked objects public for other plugins
  • WordPress.Security.NonceVerification.Recommended when validating the autologin code to log the user in
  • WordPress.DB.DirectDatabaseQuery.DirectQuery and WordPress.DB.DirectDatabaseQuery.NoCaching when deleting in uninstall.php
  • WordPress.Files.FileName.InvalidClassFileName for abstract classes

Some other rules are disabled in the test code.

To see PHP_CodeSniffer WPCS errors run:

vendor/bin/phpcs

Use PHP Code Beautifier and Fixer to automatically correct them where possible:

vendor/bin/phpcbf

WP_Mock Tests

WP_Mock tests can be run with:

phpunit -c tests/wp-mock/phpunit.xml

WordPress-Develop Tests

The wordpress-develop tests are configured to require a local MySQL database (which gets wiped each time) and this plugin is set to require a database called wordpress_tests and a user named wordpress-develop with the password wordpress-develop.

To setup the database, open MySQL shell:

mysql -u root -p

Create the database and user, granting the user full permissions:

CREATE DATABASE wordpress_tests;
CREATE USER 'wordpress-develop'@'%' IDENTIFIED WITH mysql_native_password BY 'wordpress-develop';
GRANT ALL PRIVILEGES ON wordpress_tests.* TO 'wordpress-develop'@'%';
quit

The wordpress-develop tests can then be run with:

phpunit -c tests/wordpress-develop/phpunit.xml 

Code Coverage

Code coverage reporting requires Xdebug installed.

Adding --coverage-text to phpunit commands displays their individual coverage in the console.

Adding --coverage-php tests/reports/wordpress-develop.cov to each allows their coverage stats to be merged using:

vendor/bin/phpcov merge --clover tests/reports/clover.xml --html tests/reports/html tests/reports

All Together

To fix WPCS fixable errors, display the remaining, run WP_Mock and WordPress-develop test suites and output code coverage, run:

vendor/bin/phpcbf; 
vendor/bin/phpcs; 
phpunit -c tests/wordpress-develop/phpunit.xml --coverage-php tests/reports/wordpress-develop.cov --coverage-text; 
phpunit -c tests/wp-mock/phpunit.xml --coverage-php tests/reports/wp-mock.cov --coverage-text; 
vendor/bin/phpcov merge --clover tests/reports/clover.xml --html tests/reports/html tests/reports --text

Code coverage will be output in the console, and as HTML under /tests/reports/html/.

Symlinks

Composer Symlink Handler is used to create a symlink to WordPress src directory in the project root, for convenience.

Composer-Patches

composer-patches is used to apply PRs to composer dependencies while waiting for the repository owners to accept the required changes.

Minimum PHP Version

PHPCompatibilityWP is installed by Composer to check the minimum PHP version required.

./vendor/bin/phpcs -p ./trunk --standard=PHPCompatibilityWP --runtime-set testVersion 5.7-

Minimum WordPress Version

The minimum WordPress version was determined using wpseek.com's Plugin Doctor.

WordPress.org Deployment

https://zerowp.com/use-github-actions-to-publish-wordpress-plugins-on-wp-org-repository/

https://github.com/marketplace/actions/composer-php-actions

TODO

  • Regex for URLs with trailing brackets e.g. "(https://example.org)"
  • Remove the autologin URL parameter in the browser location bar on success
  • Verify i18n is applied everywhere __()
  • Delete all passwords button in admin UI
  • Regex subject filters should be verified with preg_match() before saving
  • Error messages on settings page validation failures
  • Sanitize out regex pattern that would entirely disable the plugin
  • Client-side settings page validation
  • Test adding an autologin code to a URL which already has one overwrites the old one (and leaves only the one).

Licence

GPLv2 or later.

About

Adds single-use passwords to WordPress emails' URLs for frictionless login.

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • PHP 99.0%
  • Other 1.0%