Check the module web, it defines the login form and js files etc, check also the file res_users.py in module base/res/ and there is the login function defined.
def login(self, db, login, password):
if not password:
user_id = False
cr = pooler.get_db(db).cursor()
# autocommit: our single update request will be performed atomically.
# (In this way, there is no opportunity to have two transactions
# interleaving their cr.execute()..cr.commit() calls and have one
# of them rolled back due to a concurrent access.)
# check if user exists
res = self.search(cr, SUPERUSER_ID, [('login','=',login)])
user_id = res
# check credentials
self.check_credentials(cr, user_id, password)
# We effectively unconditionally write the res_users line.
# Even w/ autocommit there's a chance the user row will be locked,
# in which case we can't delay the login just for the purpose of
# update the last login date - hence we use FOR UPDATE NOWAIT to
# try to get the lock - fail-fast
# Failing to acquire the lock on the res_users row probably means
# another request is holding it. No big deal, we don't want to
# prevent/delay login in that case. It will also have been logged
# as a SQL error, if anyone cares.
cr.execute("SELECT id FROM res_users WHERE id=%s FOR UPDATE NOWAIT", (user_id,), log_exceptions=False)
cr.execute("UPDATE res_users SET login_date = now() AT TIME ZONE 'UTC' WHERE id=%s", (user_id,))
_logger.debug("Failed to update last_login for db:%s login:%s", db, login, exc_info=True)
_logger.info("Login failed for db:%s login:%s", db, login)
user_id = False
and check the methods authenticate, check and check_credentials also.