How else would you achieve it - throwing exceptions for program flow is quite common in Python for example; Iterator.next() throws StopIteration when it reaches the end of the iterable.
I see your point, I didn't notice that the parent mentioned WrongPasswordException, when I implemented something similar previously it looked like this:
User.authorize(username, password)
-> Returns true if valid username/password
-> Returns false if username/password do not match
-> Raises AccountDisabled if username/password valid but account disabled
The normal login failure case is not exceptional - but the others are.
Then again, stuff like authentication and authorization (two separate concepts!) are often better handled on some middleware or service layer than in models and controllers.