PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Monday, January 10, 2022

[FIXED] How to make sure case insensitive usernames are always accepted by Symfony UserBadge?

 January 10, 2022     doctrine, doctrine-orm, php, symfony, symfony-security     No comments   

Issue

I have created a custom AbstractAuthenticator subclass in my Symfony 5 project which can process user credentials included in HTTP headers.

public function authenticate(Request $request): PassportInterface {
    $userIdentifier = $this->getUserIdentifierFromRequest();
    
    return new Passport(
        new UserBadge($this->userIdentifier),
        new CustomCredentials(
            function ($credentials, UserInterface $user) {
                ...
            },
            
            $credentialFromRequest
        )
    );
}

This works fine and when a invalid username is checked a UserNotFoundException is thrown by UserBadge.

However, I wonder why this implementation is case insensitive on the given username?

I checked the Symfony code and UserBadge uses the EntityUserProvider class which performs a simple $repository->findOneBy([$this->property => $identifier]) (find by field email in my case). After some search I found related answer, which indicate that wether the find... operate case sensitive or case insensitive most likely depends on the underlying datebase (MariaDB 10 in my case).

Is there any way to control wether the username lookup should work case sensitive or not?

While the case insensitive search is fine in the current project, I would like to make sure, that it stays this way, not matter if I port the project to another machine with another underling database...


Solution

You could create a custom User Provider.

Then in your provider simply call strtolower() on the identifier, and LOWER() on the identifier column.

A rather simple implementation, assuming you inject the Entity Manager on your User Provider.


public function loadUserByIdentifier(string $identifier): UserInterface
{
    $user = $this->em->createQueryBuilder()
            ->select('u')
            ->from(YourUser::class, 'u')
            ->where('LOWER(u.username) = :username')
            ->setParameter('username', strtolower($identifier))
            ->setMaxResults(1)
            ->getQuery()
            ->getOneOrNullResult();

    if (!$user instanceof YourUser::class) {
        throw new UserNotFoundException('No user found for ' . $username);
    }

    return $user;

}

Adjust to your application constraints. You can probably move the query itself to the specific entity repository, and create the query there, instead of the provider.



Answered By - yivi
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing