64-Nodejs Course 2023: Auth: Logged In User
Tags: node, typescript, mongodb, fastify
Published: 2022-11-14 09:04:31

---
title: 64-Nodejs Course 2023: Auth: Logged In User
published: true
description: 
series: Nodejs Course 2023
tags: nodejs, typescript, mongodb, fastify
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7e6crkw0ihqvd2bdj5zo.png
# Use a ratio of 100:42 for best results.
---

We have seen the access token being generated and verified then stored in database, now let's generate an access token for the user when he hits the `login` route.

## Login Route

Let's create a new route in `src/app/users/routes.ts` and create anew handler/controller for it (`src/app/userss/controllers/auth/login.ts`), notice that i added a new folder called `auth` to hold all the authentication related controllers to be in one folder like `login`, `register`, `logout`, `forgot password`, `reset password` etc.

```ts
// src/app/users/routes.ts
import login from './controllers/auth/login.ts';
// ...

router.post('/login', login);
```

```ts
// src/app/users/controllers/auth/login.ts
import { Request } from "core/http/request";
import { Response } from "core/http/response";

export default async function login(request: Request, response: Response) {
  // get the email and password from the request body
  const { email, password } = request.only(["email", "password"]);
}
```

Now let's get the user from the database using the email and check if the password is correct, if it is correct then we will generate a new access token for the user and store it in the database.

```ts
// src/app/users/controllers/auth/login.ts
import { Request } from "core/http/request";
import { Response } from "core/http/response";
import User from "app/users/models/user";

import User from "app/users/models/user";
import { Request } from "core/http/request";
import { Response } from "core/http/response";

export default async function login(request: Request, response: Response) {
  // get the email and password from the request body
  const { email, password } = request.only(["email", "password"]);

  const user = await User.attempt({ email, password });

  if (!user) {
    return response.badRequest({
      error: "Invalid credentials",
    });
  }

  console.log("Logged in successfully");

  // generate access token
  return response.success({
    user: user.data,
  });
}
```

Here we imported the user model and called a method called `attempt` which will check if the user exists and the password is correct, if it is correct then it will return the user, if not then it will return `null`.

So let's create this `static` method first.

As you see, we passed an object with the email and password, why its an object? because we may use another thing than the email, for example login by username or phone number, so we can pass the email or username or phone number in the object and check if the user exists and the password is correct.

```ts
// src/app/users/models/user.ts
import { verify } from "@mongez/password";
import { except } from "@mongez/reinforcements";
import { Model } from "core/database";
import castPassword from "core/database/casts/cast-password";
import { Casts, Document } from "core/database/model/types";

export default class User extends Model {
  /**
   * Collection name
   */
  public static collectionName = "users";

  /**
   * {@inheritDoc}
   */
  public defaultValue: Document = {
    isActive: true,
    isEmailVerified: false,
    isPhoneVerified: false,
  };

  protected casts: Casts = {
    isActive: "boolean",
    isPhoneVerified: "boolean",
    joinDate: "date",
    password: castPassword,
  };

  /**
   * Attempt to login the user
   */
  public static async attempt(data: any) {
    // find first user with the given data, but exclude from it the password
    const user = await this.first(except(data, ["password"]));

    if (!user) {
      return null;
    }

    // now verify the password

    if (!verify(user.get("password"), data.password)) {
      return null;
    }

    return user;
  }
}
```

Let's split the code into parts:

* First we created a static method called `attempt`
* This method receives an object contains the data that will be used for validation.
* As it is an object, then the best method to get a user for object of columns is `first` method, so we called it and passed the object to it, but we need to exclude the `password` from the object because we don't want to search for the user by the password.
* If the user exists then we will verify the password, if the password is correct then we will return the user, if not then we will return `null`.

We're using [verify](https://github.com/hassanzohdy/mongez-password#verifying-password) function to verify the given password with the ciphered one in the database, if it is not verified return null, otherwise return the user model object.

Now let's create a new user with your email and password `123456` (Just only for testing), then let's test the `attempt` method.

```ts
// src/app/users/routes.tsimport { connection } from "core/database";
import router from "core/router";
import login from "./controllers/auth/login";
import createUser from "./controllers/create-user";
import getUser from "./controllers/get-user";
import usersList from "./controllers/users-list";
import User from "./models/user";

router.get("/users", usersList);
router.get("/users/:id", getUser);
router.post("/users", createUser);
router.post("/login", login);

connection.on("connected", async () => {
  const user = await User.create({
    email: "hassanzohdy@gmail.com",
    password: "123456",
  });

  console.log(user.data);
});
```

Now you should see in the console something similar to this:

![Created User](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6qg5br6kbvuypy6upb7u.png)

Thanks to our amazing `casts` property, the password is auto hashed and stored in the database.

Now let's test our `attempt` method:

Open postman and send a `POST` request to `http://localhost:3000/login` with the following body:

> Don't forget to added the Authorization header with your Bearer {token}.

And in the `Body` tab, select form data or json, whatever you like, i prefer form data for ease of reading and use and put your email and password.

If you entered the data correctly, you should see in the console `Logged in successfully` and user data will be returned, if not you should see in the postman an error object with message `Invalid credentials`.

## Generating Access Token

Now, we need to generate the access token for current user, but if you remember, generating the token was done in the `registerAuthRoutes` function, in that sense, we really need to pluck it form there, this is going to be our next article Inshaa Allah.

## 🎨 Conclusion

In this article, we saw the login workflow and how to use the `attempt` method to verify user credentials, and how we made it more flexible and dynamic.

## 🚀 Project Repository

You can find the latest updates of this project on [Github](https://github.com/hassanzohdy/nodejs-2023)

## 😍 Join our community

Join our community on [Discord](https://discord.gg/pb2vmdfhGf) to get help and support (Node Js 2023 Channel).

## 🎞️ Video Course (Arabic Voice)

If you want to learn this course in video format, you can find it on [Youtube](https://www.youtube.com/playlist?list=PLGO8ntvxgiZMJc7RN2lIq9WmMOlWZGzmz), the course is in Arabic language.

## 📚 Bonus Content 📚

You may have a look at these articles, it will definitely boost your knowledge and productivity.

General Topics

* [Event Driven Architecture: A Practical Guide in Javascript](https://dev.to/hassanzohdy/event-driven-architecture-the-best-paradigm-that-i-love-to-work-with-in-javascript-and-node-js-1gnk)
* [Best Practices For Case Styles: Camel, Pascal, Snake, and Kebab Case In Node And Javascript](https://dev.to/hassanzohdy/best-practices-for-case-styles-camel-pascal-snake-and-kebab-case-in-node-and-javascript-55oi)
* [After 6 years of practicing MongoDB, Here are my thoughts on MongoDB vs MySQL
](https://dev.to/hassanzohdy/after-6-years-of-practicing-mongodb-here-are-my-thoughts-on-mongodb-vs-mysql-574b)

Packages & Libraries

* [Collections: Your ultimate Javascript Arrays Manager](https://dev.to/hassanzohdy/collections-your-ultimate-javascript-array-handler-3o15)
* [Supportive Is: an elegant utility to check types of values in JavaScript](https://dev.to/hassanzohdy/supportive-is-an-elegant-utility-to-check-types-of-values-in-javascript-1b3e)
* [Localization: An agnostic i18n package to manage localization in your project](https://dev.to/hassanzohdy/mongez-localization-the-simplest-way-to-translate-your-website-regardless-your-favorite-framework-4gi3)

 React Js Packages

* [useFetcher: easiest way to fetch data in React Js](https://dev.to/hassanzohdy/usefetcher-the-easiest-way-to-fetch-data-in-react-45o9)

Courses (Articles)

* [React Js: Let"s Create File Manager With React Js and Node Js](https://dev.to/hassanzohdy/lets-create-a-file-manager-from-scratch-with-react-and-typescript-chapter-i-a-good-way-to-expand-your-experience-5g4k)