Search
  • Seiji Ralph Villafranca

Learning Basic JWT with Node and Type ORM

In this tutorial, I will teach how to setup our JSON Web token (JWT) with NodeJS and TypeORM but before we proceed on the JWT part, I will discuss first the background of TypeORM for us to understand what are its additional offered powers and benefits for Node JS.


What the hell is Type ORM

the ORM term is very familiar for developers especially who are into object oriented programming, ORM stands for for Object relational mapping, it is a commonly used programming technique that allows us to converts data into a usable object within the programming language by creating a "virtual object database'.


ORM is very powerful as it gives us an easier way to access objects and their properties in the database and at the same time it also provides features such as helpers and query function that executes similar SQL statements that we can apply in our language.


So we want to apply this technique with NodeJS, we wan it the OOP way, this is where TypeORM comes in, TypeORM gives us the capability for NodeJS to have a ORM strategy that can be written in typescript. It offers a wild range of features such as defining database-specific column types, entity manager, repository access, Active Record and Data Mapper and more.


Mapping Database as a Programming Object

I have mentioned earlier the term Active Record and Data Mapper, these two concepts are one the the core features of TypeORM as this will give us capability to convert database object as a usable models in NodeJS. let us look at the first example below how to define a class using Data Mapper.


import{Entity, PrimaryGeneratedColumn, Column} from"typeorm";  
@Entity()
export class Blog{      
   @PrimaryGeneratedColumn()     
   id: number;      
   @Column()     
   title: string;      
   @Column()     
   summary: string;      
   @Column()     
   body: string;
 } 

we can see in the example that we have created a simple class Blog with properties, it is a simple model that has added decorators, the @Entity decorator allows the TypeORM to identify that this class must be mapped to a specific database table and the @PrimaryGeneratedColumn and @Column defines the columns for the object.


If we are to use the model in our programming, we will create a repository for the Blog class to access query functions for our model.


const repository = connection.getRepository(Blog);
const blog = new Blog(); 

blog.title ="Awesome Blog"; 
blog.summary ="Summary is Awesome";
blog.body = "This is very Awesome";
 
 await repository.save(blog);
 const allBlogs = await repository.find();
 const firstUser = await repository.findOne(1);


in the given example, we have created a repository for the Blog Model, with the created repository, we are now able to access the helpers that will allow us to insert, get, update and delete data in our database.


The next implementation of mapping is using the Active Record Approach, this is almost the same as the Data Mapper, the only difference here is we will extend the Blog class with the BaseEntity from TypeORM to give the class query and helper functions.


import{Entity, PrimaryGeneratedColumn, Column, BaseEntity} from "typeorm";  
@Entity()
export class Blog extends BaseEntity{      
   @PrimaryGeneratedColumn()     
   id: number;      
   @Column()     
   title: string;      
   @Column()     
   summary: string;      
   @Column()     
   body: string;
 } 

in the example above, we have extended out Blog model with BaseEntity class, and if we are to us the model to in our logic:


const blog = new Blog(); 
blog.title ="Awesome Blog"; 
blog.summary ="Summary is Awesome";
blog.body = "This is very Awesome";
 
 await blog.save(blog);
 const allBlogs = await blog.find();
 const firstUser = await blog.findOne(1);

when using the Active Record Approach, we don't need to create a repository for our model as we can access our functions directly on the model itself as BaseEntity class has provided these needed features.


Creating our first Node JS TypeORM

We might think that it is a great dilemma for us to setup our NodeJS with the TypeORM framework, well, thanks to the developers and they have provided a CLI for us to scaffold our TypeORM project, the first step is to install our TypeORM executing the following command:

npm install -g typeorm

after successfully installing typeorm in our machine, let's now start scaffolding our project we will execute the following command:

typeorm init --name AwseomeTypeORM --database mssql

in this command, we haves used two parameters for creating our project, the first parameter is the name parameter that would define the name of our scaffolded project, the second parameter is what database we will use for the connection.


After successful execution of the command, we now have our TypeORM project created, we will see the following folder structure in our application.


Awesome TypeORM
├── src              // place of your TypeScript code
│   ├── entity       // place where your entities (database models) are stored
│   │   └── User.ts  // sample entity
│   ├── migration    // place where your migrations are stored
│   └── index.ts     // start point of your application
├── .gitignore       // standard gitignore file
├── ormconfig.json   // ORM and database connection configuration
├── package.json     // node module dependencies
├── README.md        // simple readme file
└── tsconfig.json    // TypeScript compiler options

more information @ https://typeorm.io/


Now we have our TypeORM ready, let us deep dive on our ormconfig.json, let us look on code below.


{
"type": "mssql",
"host": "localhost",
"username": "sa",
"password": "sa",
"database": "awesomedb",
"synchronize": true,
"logging": false,
"entities": ["src/entity/**/*.ts"],
"migrations": ["src/migration/**/*.ts"],
"subscribers": ["src/subscriber/**/*.ts"],
"cli": {"entitiesDir": "src/entity",
        "migrationsDir": "src/migration",
        "subscribersDir": "src/subscriber"
        }
}

in our previous command, we have selected MSSQL as our choice of database, having the value of type is mssql, the host for now will be localhost as we will connect locally to our database, the username and password will be the credentials for our SQL Authentication Server, the synchronize will be set to true as we will apply the code first programming here in our application, in my example above, i have replaced all the values with my database credentials.


Installing other dependencies


Yes we have created our TypeORM application, but this does not stop here, first let's execute the command npm install to install the defined dependencies in our package .json, We also need other dependencies for our project to create endpoints as, we will install the following libraries we need after we proceed on creating our login endpoint.


Express JS

we will use express js framework for us to create our routes/endpoints in our node js

npm install express --save

Body Parser

a library for node js that will enable us to parse JSON Objects in the request body of an endpoint

npm install body-parser --save

BcryptJS

this is the encryption that we will be using for the user's password.

npm install bcrpytjs --save

jsonwebtoken

this is a library for us to allow to sign a new valid token if the username and password is valid.

npm install jsonwebtoken --save

class validator

a library that we will use for validating values of model properties using decorators

npm install class-validator --save

http

the one that will be used to create a server for our endpoints.

npm install http --save

After installing all other dependencies, we are now ready to bake our code!


Configuring our node server

in the root of our project open the index.ts file and we should replace the existing code with the following below:



the routes will have an error for now as we have not yet defined specific routes on our application. this file will be the main entry of our Node JS, we can see in the example above that we created a server with all our defined routes.


the next step is we will now create our controllers, routes, and our model/entity for the User object, under the src folder we will create the following folders namely controllers, routes, config and middlewares.


under the config folder create a file config.ts and place the folowing code.

export default {
 jwtSecret: '@SEIJIV',
};

this will be our key for generating our jwt, it's a better practice that our key is not predictable having a long length and a combination of special characters.


under the entity folder, we will see an existing User model under the User.ts file, we will reused this auto generated Model and replace with the following code.

in the code above, we can see that we have added three properties, namely the id which the primary key and an auto generated column where it will use an uuid format, the username and password of the user which has a validator of @IsNotEmpty having it as a required value. the hasPassword() function will be used to encrypt the password of the user before inserting it into the database, and the added function named checkIfUnencryptedPasswordisValid() will be used to validate the user password on login.


now under the controllers folder, create a file named AuthController.ts and place the following code


The first function is the mainly the login function which will accept the username and password of the user, we have created a user repository where we will call the findOne() and check if the username already exists, if not we will now check if the password is valid using the checkIfUnencryptedPasswordisValid() function, if two checks have passed, the jw will be created using the sign() function of jsonwebtoken, we have used the id and and username of the user to generate the token.


Now we have created our model and controller for User, we will now create the endpoint for the login, under the routes folder we will add the auth.ts with the following code.

and we will also add an index.ts under routes folder file which will act as a barrel file for all our routes.



this will now create a {baseUrl}/auth/login endpoint in our application that will be available for the client to be called.


and that's it! we have created our working login endpoint with jwt, but lets create another controller named UserController.ts and create a function that will create a user in our application.


and we will add a user.ts file under the routes folder to open an endpoint for the createUser function


and we will ad the user router in the index file of routes.

and we have successfully created our create user endpoint.


Running and Testing the endpoints


Now we can run our application on this point, we can install nodemon globally so we can run our node js application and automatically restarts the server if there are code changes.

npm install nodemon -g

after successful installation, we will add the following script command in our package.json

 "watch-start": "nodemon src/index.ts"

and run the command npm run watch-start to run our application.


we will see the result in our terminal if our application has successfully connected to our database and is now currently running on our port. (Note* you should create the database in the mssql with the name initialized on your ormconfig.json manually)



now we will use Postman to test our endpoints, the first step is to create a user in our database that we will use in our login endpoint.


we have successfully created our user and we will use this new credentials for our login endpoint.


and we have successfully generated a valid JWT for our created credentials! in this case we are returning only the created JWT of the response, we can also add additional information such as first time login flag of the user or some profile information needed on the dashboard.


and that's it, I hope you have learned from this tutorial for the code of the project here is the Github repository that you can freely clone Cheers!

https://github.com/SeijiV13/awesome-type-orm-starter

43 views0 comments

Recent Posts

See All