DEV Community

Shiono Yoshihide
Shiono Yoshihide

Posted on • Updated on

A road to the easiest user authentication system for Node.js

JavaScript is easy to read and write, but sometimes we are facing difficulties like user authentication.

Before talking about user authentication deeper, let me introduce you what I made this weekend:

GitHub logo saltyshiomix / ark

An easiest authentication system on top of NestJS, TypeORM, NEXT.js(v9.3) and Material UI(v4).

An easiest authentication system on top of NestJS, TypeORM, NEXT.js (v9) and Material UI (v4).

Package License (MIT)

Features

  • Cross platform - Mac, Linux and Windows
  • Database synchronization with entities - powered by TypeORM
  • Server Side Rendering - powered by NEXT.js
  • API server - powered by NestJS
  • Authentication - powered by Passport
  • Material UI design

Technologies

  • Hot reloading for the developer experience :)
    • ts-node-dev - Compiles your TS app and restarts when files are modified
    • NEXT.js - The React Framework
  • Lang
  • Database
    • PostgreSQL - The World's Most Advanced Open Source Relational Database
  • ORM (Object-relational mapping)
    • TypeORM - ORM for TypeScript and JavaScript (ES7, ES6, ES5)
  • Server
    • NestJS - A progressive Node.js framework for building efficient, reliable and scalable server-side applications
      • internally using Express - Fast, unopinionated, minimalist web framework for Node.js
    • NEXT.js - The React Framework
  • Environment variables
    • dotenv - Loads environment variables from .env…

Yes, this is a super duper simple user authentication system :)

On the other hand, it uses these technologies:

  • Hot reloading for the developer experience :)
    • nodemon - Monitor for any changes in your node.js application and automatically restart the server
    • Next.js - The React Framework
  • Lang
  • Database
    • PostgreSQL - The World's Most Advanced Open Source Relational Database
  • ORM (Object-relational mapping)
    • TypeORM - ORM for TypeScript and JavaScript (ES7, ES6, ES5)
  • Server
    • nest - A progressive Node.js framework for building efficient, reliable and scalable server-side applications
      • internally using Express - Fast, unopinionated, minimalist web framework for Node.js
    • Next.js - The React Framework
  • Environment variables
    • dotenv - Loads environment variables from .env for nodejs projects
  • User authentication
    • Passport - Simple, unobtrusive authentication for Node.js
  • UI framework
    • React - A JavaScript library for building user interfaces
    • Next.js - The React Framework
    • Material UI - React components that implement Google's Material Design.

So many libraries, right? Easiest authentication?

Yes.

Let's digging deeper:

Fun Database

Thanks to TypeORM, we can synchronize database with entities.

Here is a user.entity.ts:

import {
  Entity,
  Column,
  PrimaryGeneratedColumn
} from 'typeorm';

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column('varchar')
  name: string;

  @Column('varchar', {
    unique: true
  })
  email: string;

  @Column('varchar')
  password: string;  
}

TypeORM automatically synchronize database from @Entity() decorator information.
In other words, database automatically changes as soon as you save user.entity.ts.

Fun Coding

With nest, we can use modern JavaScript(TypeScript), and with VSCode we can obtain the maximum benefit like code intelligence.

Here is a sample users.controller.ts:

import {
  Controller,
  Get
} from '@nestjs/common';
import { User } from './user.entity';
import { UsersService } from './users.service';

@Controller('api/users')
export class UsersController {
  constructor(private readonly service: UsersService) {}

  @Get()
  async findAll(@Query() query): Promise<User[]> {
    return await this.service.findAll();
  }
}

By constructor injection, users.controller.ts doesn't care about how to findAll() users.

And users.service.ts is like this:

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';

@Injectable()
export class UsersService {
  constructor(@InjectRepository(User) private readonly repository: Repository<User>) {}

  async findAll(): Promise<User[]> {
    return await this.repository.find();
  }
}

Can you believe this?

We can findAll() users without coding SQL scripts because TypeORM and nest conceal implementation. (so called "Repository Pattern")

Fun SEO (Server Side Rendering)

Next.js enables us to write page/index.tsx without caring about server side rendering:

export default () => 'Hello SSR!'; // this is a React.Component :)

How to try ARK

First, you need to install PostgreSQL.

If you use Mac and Homebrew, setup is so easy:

# install database (postgresql)
$ brew install postgresql

# if you want to start postgresql in startup, try do this
$ brew services start postgresql

# create user "arkuser" with password "arkark"
$ createuser -P arkuser

# create database "arkdb" owened by "arkuser"
$ createdb arkdb -O arkuser

That's it!

And use it like Next.js:

# clone repository
$ git clone https://github.com/saltyshiomix/ark.git

# install dependencies
$ cd ark
$ yarn

# development mode
# please make sure to create the `.env` file!
$ yarn dev

# production mode
# please make sure to create the `.next/.env` file!
$ yarn build
$ yarn start

(.env file is like this:)

# DB
DB_TYPE=postgres
DB_HOST=localhost
DB_PORT=5432
DB_USERNAME=arkuser
DB_PASSWORD=arkark
DB_DATABASE=arkdb
DB_SYNCHRONIZE=true

# App
HOST=localhost
PORT=4000
SESSION_SECRET=ark

And you'll see http://localhost:4000:

login screen

And create an account:

signup screen

You are now logged in!

logged-in screen

Conclusion

I created ARK repository for the purpose of showing how to implement user authentication system easily.

So PRs are welcome!
(like "Implement social login", "Implement JSON API" and so on.)

I hope you helped :)

Top comments (13)

Collapse
 
simonas88 profile image
simonas88

While this is nice and all, isn't it now no different than any other OOP-language code? Now I'm not saying javascript is good for the sake of being different, but why go all this length with the setup of tens of different libraries, when you could've arguably done it faster with the same result in .NET?

Collapse
 
maheshkale profile image
Mahesh K

Because not everyone wants to use .Net.

Collapse
 
academicrevolt profile image
Academic Revolt

.NET doesn't handle JSON as efficiently as Node.js. However, this tutorial uses postgres instead of mongo, so good point.

Collapse
 
guardadodev profile image
Guardadodev

Awesome project, I was just about to start an auth project just like this with the same stack!

Collapse
 
saltyshiomix profile image
Shiono Yoshihide

Thank you sooo much!
I hope you enjoy it :)

NestjS and NEXT.js are so awesome, I believe.

Collapse
 
yourleader profile image
yourleader

do you have any problema by running on dev?

Collapse
 
geshan profile image
Geshan Manandhar

Good post, great work!

Collapse
 
saltyshiomix profile image
Shiono Yoshihide

Thank you very much!
I'll implement social login like GitHub, soon :)

Collapse
 
chaostheory profile image
Brian Lee • Edited

Question: why did you use NestJS with NextJS? Isn't this all possible leaving out NestJS since NextJS has routing? I know NestJS, but I'm very new to NextJS.

Collapse
 
saltyshiomix profile image
Shiono Yoshihide

Next.js is a react framework that provides SSR(Server Side Rendering) easily.
So if you want to use react with better SEO, Next.js is one of the best choices.

Nest is just a server framework, so it doesn't care about client side.

Generally way, web services have two repositories: server repo and client one.
But I think it's complex enough to learn or test simple web stack :)

Collapse
 
igcp profile image
Igor Conde

Cool post,exactly what I was looking for, for studies.

Collapse
 
saltyshiomix profile image
Shiono Yoshihide

Thanks Igor!

Feel free to open issues if you have any troubles :)

By the way, I'm currently working on react-ssr, which is an alternative to NEXT.js. (I think)

This renders React as a view template engine of Express like this:

// server.js
const posts = [
  { id: 1, body: 'This is a first post.' },
  { id: 2, body: 'This is a second post.' },
  { id: 3, body: 'This is a last post.' },
];

app.get('/', (req, res) => {
  res.render('index', { posts });
});
// views/index.jsx
import React from 'react';

const IndexPage = ({ posts }) => {
  return (
    <React.Fragment>
      {posts.map((post, index) => {
        return (
          <p key={index}>
            <a href={'/posts/' + post.id}>{post.body}</a>
          </p>
        );
      })}
    </React.Fragment>
  );
};

export default IndexPage;

If you like, please try it :)

Thank you in advance!

Yoshihide

Collapse
 
yourleader profile image
yourleader

thanx , this is a very good work. I dont know if you have the time to help me, I can't run your code on dev. I thing the problem is in next.config.js file