In Javascript, it doesn’t matter if you’re using callbacks, Promises or asynchronous functions (which are basically syntactic sugar for the promise API), asynchronous is like a "plague".
This means that whenever you use an asynchronous API, the rest of the code that used the function will be required to bear that responsibility, thereby becoming asynchronous as well. It’s like a contamination.
Don’t think this is bad because it is a "contamination", it is only a consequence of the asynchronous nature of language.
Therefore, if you have an asynchronous function (like the function login):
// Note que a função abaixo é assíncrona (`async`):
async function login(email, password) {
  // Código qualquer aqui...
};
Any function you call login has to deal with its asynchronous nature. And any function that call the function that called login also... It is, of course, an endless "contamination" upward (towards the call stack):
One way to deal with this asymchronism is to use the async and await the resolution of the promise that login returns using the operator await. Thus:
async function loginController(req, res) {
  // Estamos lidando com o assincronismo de `login` utilizando `await`.
  // Note que, para utilizar o `await`, você é *obrigado* a utilizar o `async`.
  const loggedIn = await login(email, password);
  if (loggedIn) {
    res.send('OK!');
  } else {
    res.send('Dados incorretos.');
  }
}
Another option is to deal with the promise directly using the method then.
function loginController(req, res) {
  login(email, password).then((loggedIn) => {
    if (loggedIn) {
      res.send('OK!');
    } else {
      res.send('Dados incorretos.');
    }
  });
}
Note that in the above case we do not use async in the calling function, but we deal with the asymchronism of login a little more explicitly using directly the promise API.
A slightly more complete example of how to handle the promise API directly:
async function a() {
  await delay(500);
  return 1;
}
// Podemos lidar com o assincronismo sem o `async`. Por exemplo:
function b() {
  // Note que a `Promise` deve ser retornada:
  return a().then((a) => a + 1);
}
 
// Nada impede de usar o `async` depois também:
async function c() {
  const result = await b();
  console.log('Resultado:', result);
}
c().then(() => console.log('Finalizado.'));
// Ignore (só para criar um efeito de "lentidão"):
function delay(t) {
  return new Promise((r) => setTimeout(r, t));
}
 
 
In short, you are not "obliged" to use the async. However, you must deal with the asymchronism. For this, you can use the async, the API of Promises directly, etc..
							
							
						 
The question was not very clear to me (try edit it!)... :) You’re asking if it would be necessary to use the
asyncin functionloginController? If so, yes, it is mandatory, since useawaitwithin a function that is not marked asasyncevokes aSyntaxError.– Luiz Felipe
Actually I’m asking if due to function login be asynchronous, the function loginController should also be, or I can leave it as a common function(synchronous).
– Diego Oliveira