Deno — JWT Authentication

Hi friends, hope you all are safe and sound.

Today we are going to discuss JWT authentication process in DENO. Till now we have learned the following in Deno

Now in this article we will see how we achieve JWT( JSON Web Token) in DENO using djwt.

For this we have created token.ts in this file you can see token realted methods like generate and validate.

import { validateJwt, parseAndDecode, validateJwtObject } from "https://deno.land/x/djwt/validate.ts"; 
import { makeJwt, setExpiration, Jose, Payload } from "https://deno.land/x/djwt/create.ts";
const key = "your-secret";
const header: Jose = {
alg: "HS256",
typ: "JWT"
};
export default{
async generateToken(userID:any) {
const payload: Payload = {
uid: userID,
exp: setExpiration(new Date().getTime() + 60000 * 60)
};
return makeJwt({ header, payload, key })
},
async validateToken(jwt:any) {
return await validateJwt({jwt, key, algorithm: "HS256" });
},
fetchUserId(token: string): any {
return validateJwtObject(parseAndDecode(token)).payload;
}
}

Now if we give it a shape we can use the token in below example. Here we will take bellow ts files for this example.

To support the above, we need below files under utils folder

  • authMiddleware.ts
  • token.ts

First we will prepare the app.ts file where we will start the game. Loading all important modules. On the same page we have declare the routing options. We can create a separate routing page but for now let it be simple.

import { Application } from 'https://deno.land/x/oak/mod.ts'; 
import { Router } from 'https://deno.land/x/oak/mod.ts';
import { authMiddleware } from "./utils/authMiddleware.ts";
import { loginEmployee, getEmployees, logoutEmployee } from './controller.ts';
const PORT = 8000;
const app = new Application();
const router = new Router();
router
.post('/login', loginEmployee)
.get('/employees', authMiddleware, getEmployees)
.get('/logout', authMiddleware, logoutEmployee);
app.use(router.routes());
app.use(router.allowedMethods());
console.log("Server is up and running in port:", PORT); app.listen({port: PORT});

Now after creating the app.ts its time to prepare the controller.ts.

import db from "./database/mongodb.ts"; 
import hash from './utils/hash.ts';
import token from './utils/token.ts';
const empCollection = db.collection("employees");
const getEmployees = async (ctx: any) => {
const employees = await empCollection.find();
ctx.response.body = employees;
};
const loginEmployee = async (ctx: any) => {
const array = ['email', 'password'];
const emp_val = await validation.validate(ctx, array);
if( !emp_val) {
ctx.response.status = 422;
ctx.response.body = { error: "Invalid username/password" };
return;
}

const emp:any = await empCollection.findOne({email: emp_val.email});
if( !emp ) {
ctx.response.status = 422;
ctx.response.body = { error: "Invalid username/password" };
return;
}
let passFlag = false;
passFlag = await hash.verify(emp.password, emp_val.password);

if( !passFlag ) {
ctx.response.status = 422;
ctx.response.body = { error: "Invalid username/password" };
return;
}

const jwt = await token.generateToken(emp._id.$oid);
ctx.response.body = jwt;
ctx.cookies.set('jwt', jwt);
ctx.response.status = 201
};
const logoutEmployee = async (ctx: any) => {
ctx.cookies.delete('jwt');
ctx.response.body = { success: "Successfully Logout." };
};
export { getEmployees, loginEmployee, logoutEmployee }

We need to create few files to support the controller. First we need to think a middleware which authenticate the request.

import { Context } from "https://deno.land/x/oak/mod.ts"; 
import token from '../utils/token.ts';
import db from "../database/mongodb.ts";
const empCollection = db.collection("employees"); const authMiddleware = async (ctx: Context, next: Function) => {
if (!ctx.state.currentUser) {
const jwt = ctx.cookies.get('jwt');
if (jwt) {
const isTokenValid = await token.validateToken(jwt);
if(!isTokenValid) {
ctx.cookies.delete('jwt');
ctx.response.status = 401;
ctx.response.body = {error: "Unauthorized2"};
return;
}
const payload = token.fetchUserId(jwt);
if(payload) {
const uid:string = String(payload.uid);
const emp = await empCollection.findOne({_id: { $oid: uid }});
ctx.state.currentUser = emp;
}
} else {
ctx.state.currentUser = null;
ctx.response.status = 401;
ctx.response.body = {error: "Unauthorized3"};
return;
}
}
await next();
}
export {authMiddleware};

Finally we need the mongodb.ts. Lets see.

import { MongoClient } from "https://deno.land/x/mongo/mod.ts"; const DB_URL = "mongodb://localhost:27017" 
const mongo_client = new MongoClient(); mongo_client.connectWithUri(DB_URL);
const db = mongo_client.database('employees_db');
export default db;

So by the above example we are now clearly understand how JWT token are created in Deno and how they are validated and can use in the middleware.

Please leave a comment at info@codinghub.net and share this article as much as you can. Thank you very much!

We are on Facebook, Twitter, LinkedIn, Medium, Quora, Instagram, etc.

By the way, want to learn more about Deno? Just check out the official Deno documentation.

Originally published at https://www.codinghub.net.

Coding Hub — Learn & Build Your Career

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store