General developer forum
1. From the page you linked:
a lot of interesting stuff happens in authenticate_user_login().
2. It looks up the username in the mdl_user table to see if they are allowed to log in, and which authentication plugin handles their login requests. (This will be the plugin that handled their first-ever login request.)
I want my users to be able to use either their username or their e-mail address when they log in. An authentication plugin won't help with this because the logic that needs "fixed" is in the core code.
2. While it's true that the program won't allow you to use an e-mail address that is already in use, that doesn't mean it can't be changed in the database. The e-mail field is not a unique field in my MySQL database.
In the default situation people can log in using their username.
So 50% of your requirement is already covered.
The other 50% is that if they do no use their username, but their email instead, they still should be able to log in.
So if it doesn't exists yet, you'd need to write a auth plugin that accepts the email address of a user and based on that checks against the password.
Because the auth plugins work via a failover/waterfall method; as long as one auth plugin does not authenticate the user the next auth plugin in line will be called, this will result in users begin able to either use their username or email to log in.
If there is a chance of email duplication (I seem to recall Moodle code really doesn't like that), you could make sure that in that case people or the admin get a warning.
I spent this afternoon trying to write the plugin you suggest.
When Moodle successfully authenticates a user during the failover/waterfall portion of authenticate_user_login() after not finding the username in the user table, it attempts to create a new account. The user already has an account, so it will likely fail because of duplicate users (or worse...it will actually create a new account and the user now has two!).
If you enable $CFG->authpreventaccountcreation to try to stop this behavior, it never gets to the failover/waterfall routine.