Authentication plugin - Make username case insensitive

Hi,

I am trying to figure out how to make the Authentication username be case insensitive. The database (PostGreSQL) we are backing against is case sensitive in it’s varchar fields.

Since we are using email addresses, I am saving them as all lowercase. However, we have some users who insist on punching in their email addresses camel case. Is there a straightforward way to make $this->Auth->identify() be case insensitive on the username/email address?

Thanks!

You should be able to write your own Authenticator ?

Then in Application.php getAuthenticationService() put it into use:

Use your new one instead of Form.

As an alternative:

Could you capture the posted data in the login method and force it to lowercase before authenticating, and also capture the registration post data and force it lower also before saving?

Honestly, I would prefer to avoid writing my own authenticator for something this basic. I have written an LDAP authenticator.

The password identifier and the form authenticator do 99% of what I need.

Since the request data is now a protected member in Cake 4.X and the identify() function is literally using the request directly, capturing and modifying before hand is not really an option.

I guess I could always use javascript to lowercase the form field contents on submit. This just seems like such a hack for something that should be built in as an option.

You can insert new data into the request using Request::withData().

$request = $request->withData($key, $value);

also, if the password identifier and form authenticator do 99% of what you need then new class would likely be a very simple extends of the existing class. Not so hard to write?

I did something like the following using CakePHP 4.x (and the Authentication plugin) having the same Postgres case-sensitivity issue you noted:

In src/Application.php, you should have getAuthenticationService() function already in place (as needed by the Authentication plugin), so you should just need to update the way the code Identifies users (or whatever you call your “users”) by using a custom Resolver.

public function getAuthenticationService( ServerRequestInterface $request ): AuthenticationServiceInterface {
	$service = new AuthenticationService();

	...

	$fields = [
		'username' => 'email',
		'password' => 'password'
	];

	$service->loadIdentifier( 'Authentication.Password', [
		'fields' => $fields,
		'resolver' => [
			'className' => 'Custom'
		]
	] );

	...

	return $service;
}

Note: the “Custom” name above can be anything you’d like; make sure the Resolver file and class names below matches the name you select.

Also, the fields above are the ones I used, but you can use any names you’d like for username and password; they should match your database field names. Similarly, the fields found in the Resolver find() query below should match your database field names.

in src/Identifier/Resolver/CustomResolver.php

namespace App\Identifier\Resolver;

use Authentication\Identifier\Resolver\ResolverInterface;
use Cake\Core\InstanceConfigTrait;
use Cake\ORM\Locator\LocatorAwareTrait;

class CustomResolver implements ResolverInterface
{
	use InstanceConfigTrait;
	use LocatorAwareTrait;

	protected $_defaultConfig = [];

	public function __construct( array $config = [] ) {
		$this->setConfig( $config );
	}

	public function find( array $conditions, $type = self::TYPE_AND ) {
		return $this->getTableLocator()
			->get( 'Users' )
			->find()
			->where( [
				'lower(Users.email)' => strtolower( $conditions['email'] )
			] )
			->first();
	}
}

Note: my example uses a Users table, but your could be using another table.

You can read more here:

3 Likes

Hot damn. That’s what I am talking about.

The “issue” of being case-sensitive is not really an issue but a feature. They really should provide an option/setting to tell it to make the username case insensitive.

Muchas gracias ryanolton, esto funcionó perfectamente para mi.

This thread was very helpful, thank you. For those that do have the option to modify the DB, it is possible to modify the relevant column to be case insensitive. It requires enabling the CITEXT extension and then modifying the column’s data type to CITEXT. This guide set me in the right direction.