Build a Deno App with OKTA Authentication Using Opine Library Full Project For Beginners

Build a Deno App with OKTA Authentication Using Opine Library Full Project For Beginners

Welcome folks today in this tutorial we will be building a deno authentication system using okta library and we will also be using a Framework called as opine. It is very much similar to Express in node JS so we will be implementing this authentication system in our deno application.

Step by step YouTube video is also given in the description you can watch that video to follow along with the blog and all the source code of this blog is given in the description we can copy paste the source code and also a link to the GitHub repository is also given in the bottom of the blog.

 

 

Screenshots

 

 

So as you can see that the screenshot of the application above so if you open the application for the very first time and go to the index page then you will see a anchor tag which will have the text that is go to profile so if you click that anchor link than in the next page in the profile page it will display all sort of information about your okta account so this information is displayed inside a paragraph tag so inside your name will be shown to you email address and all other Okta related account information will be shown to you so this will be the application that we will be building in this tutorial

So as you all know guys that deno is very much different from node JS as it doesn’t require any sort of third party dependency,from command line we can use the dependencies from their URL so just we need to create a typescript file and index.ts file and you just need to copy paste the below code into that file and we did not have to import any sort of third party dependecies.

 

import { opine } from 'https://deno.land/x/opine@0.12.0/mod.ts';

const app = opine();

app.get('/', (req, res) => {
  res.send('Deno Sample');
});

app.listen(3000);
console.log('running on port 3000');

 

So as you can see in the above code snippet we are importing the opine library from this URL and in the next line we are starting the server on localhost 3000 port number and this open library is very much similar to express so whenever we initialise the node application inside Express we  start the application at a particular port number so this is a similar thing that we are doing inside demo application as well

So you can run your order deno application by executing the following command which is shown below

deno run -A index.ts

 

READ  Build a Mini Arithmetic Calculator in HTML5 CSS3 and Javascript Full Project For Beginners

So in this command you can see here on your screen we are passing this – a flag this is used for disabling all the security which is there inside the Deno by default as you know that there is a secure environment in Deno so if you run without this flag then you will not run this application this – a flag this flag is very much necessary in order to run this application

 

import { opine, serveStatic } from 'https://deno.land/x/opine@0.12.0/mod.ts';
import { renderFileToString } from 'https://deno.land/x/dejs@0.7.0/mod.ts';
import { join, dirname } from 'https://deno.land/x/opine@main/deps.ts';

import { ensureAuthenticated } from './middleware/authmiddleware.ts';
import users from './controllers/usercontroller.ts';
import auth from './controllers/authcontroller.ts';

const app = opine();
const __dirname = dirname(import.meta.url);

app.engine('.html', renderFileToString);
app.use(serveStatic(join(__dirname, 'public')));
app.set('view engine', 'html');

app.get('/', (req, res) => {
  res.render('index', { title: 'Deno Sample' });
});

app.use('/users', ensureAuthenticated, users);
app.use('/auth', auth)

app.listen(3000);
console.log('running on port 3000');

 

Now in this block of code we are importing some more dependencies such as we are serving the ejs template inside deno application for using ejs template in putting some more dependencies and also so we are adding some more controllers and middlewares inside our deo application that we will create later on so in order to add them to the root file we are adding these authentication middleware and controller project copy paste this code and later on we will create these controllers and middleware functions

 

Controllers

 

Now we will create a controller so inside your Deno App so inside your root folder create a controllers folder and make a file called as usercontroller.ts and write the file copy paste the below code so this will be the user controller and this file will contain a single route which will control the user for us

 

import { Router } from 'https://deno.land/x/opine@0.12.0/mod.ts';

const users = new Router();

// users routes
users.get('/me', (req, res) => {
  res.render('users/me', { title: 'My Profile', user: res.app.locals.user });
});

export default users;

 

Now we will create the views folder so the views are actually are seen by the user when we know the application so for making the views we need to make a separate folder inside our root folder  so just go to your root folder and create a folder views and inside that folder create two folders which are shared and users inside the shared folder create a new file which is header.html and footer.html and inside your users file create a me.html inside your views folder create index.html so basically this is a structure for all of the views which will be stored inside of a deno application so use are nothing but the actual pieces of application which are seen by the user

READ  BootBoxJS - Bootstrap Modals Library For Creating Beautiful Bootstrap Modals

 

header.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title><%= title %></title>
</head>

<body>

 

footer.html

</body>

</html>

 

me.html

<%- await include('views/shared/header.html', { title }); %>

<h1>My Profile</h1>

<ul>
<% for(var p in user){ %>
  <li><strong><%= p %>: </strong><%= user[p] %></li>
<% } %>
</ul>

<%- await include('views/shared/footer.html'); %>

 

index.html

<%- await include('views/shared/header.html', { title }); %>

<a href="/users/me">My Profile</a>

<%- await include('views/shared/footer.html'); %>

 

After setting up all the views inside your application now it’s time to go to Okta Developer Console to get your information which is client ID and client secret redirect URL and Okta organisation URL so to get all the information you need to first of all create a developer account at their website so if you haven’t created the account you can go to their official website create account and then you can get then you can create a web application like this which is shown below the images shown below

 

 

So after getting all the information from the Okta Developer Console so you need to save this credentials which you have got which is client ID and client secret so that you cannot expose it on public  as this is a sensitive information you can not exposed to the public so we will create .env file which will store it in a secure manner so in the next step we will create this file so copy paste all the code which is shown below

 

.env file

 

issuer=https://{yourOktaOrgUrl}/oauth2/default
clientId={yourClientID}
clientSecret={yourClientSecret}
redirectUrl=http://localhost:3000/auth/callback
state=SuPeR-lOnG-sEcReT

 

Here you will replace the values which are client ID and client secret redirect URL and Okta organisation URL with your values which you have got from Okta Developer Console

After getting all these values from Okta developer Developer Console we are ready to for authentication code which will be communicating with the Okta library so copy paste all this code inside a new folder just make a new folder inside your root directory which is middleware and inside that folder create a file which is earth middleware.ts this file will write a simple middleware function which will always check for every request which is made to the login page so it will check whether the user is logged in or not

 

import { config } from 'https://deno.land/x/dotenv/mod.ts';

export const ensureAuthenticated = async (req:any, res:any, next:any) => {
  const user = req.app.locals.user;
  if(!user){
    const reqUrl = req.originalUrl;
    const {issuer, clientId, redirectUrl, state} = config();
    const authUrl = `${issuer}/v1/authorize?client_id=${clientId}&response_type=code&scope=openid%20email%20profile&redirect_uri=${encodeURIComponent(redirectUrl)}&state=${state}:${reqUrl}`;
    res.location(authUrl).sendStatus(302);
  }
  next();
}

 

READ  Build a CRUD Random Password Generator and Manager Using jQueryUI and Modernizr Library in Browser Full Project For Beginners

Now guys in the next we will be exchanging this authorizatio code which we got from the Okta Developer Console with and access token so for exchanging it we will be creating this code inside a new file so just inside your controllers folder create a file which is authcontroller.ts inside this file will write a simple function which will make a post request to the Okta developer library and inside this post request we will be sending the authorization code that we got in the last step and then this Okta library will exchange this with access token so with the help of the access token we can get any sort of information from the library such as name of the person email address and all that stuff

 

import { Router } from 'https://deno.land/x/opine@0.12.0/mod.ts';
import { config } from "https://deno.land/x/dotenv/mod.ts";

const auth = new Router();

// users routes
auth.get('/callback', async (req, res) => {
 const { issuer, clientId, clientSecret, redirectUrl, state } = config();

 if (req.query.state.split(':')[] !== state) {
   res.send('State code does not match.').sendStatus(400);
 }

 const tokenUrl: string = `${issuer}/v1/token`;
 const code: string = req.query.code;

 const headers = new Headers();
 headers.append('Accept', 'application/json');
 headers.append('Authorization', `Basic ${btoa(clientId + ':' + clientSecret)}`);
 headers.append('Content-Type', 'application/x-www-form-urlencoded');

 const response = await fetch(tokenUrl, {
   method: 'POST',
   headers: headers,
   body: `grant_type=authorization_code&redirect_uri=${encodeURIComponent(redirectUrl)}&code=${code}`
 });

 const data = await response.json();
 if (response.status !== 200) {
   res.send(data);
 }
 const user = parseJwt(data.id_token);
 req.app.locals.user = user;
 req.app.locals.isAuthenticated = true;
 res.location(req.query.state.split(':')_[_1] || '/').sendStatus(302);
});


function parseJwt (token:string) {
  const base64Url = token.split('.')_[_1];
  const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
  const jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
      return '%' + ('00' + c.charCodeAt().toString(16)).slice(-2);
  }).join(''));

  return JSON.parse(jsonPayload);
};

export default auth;

 

DOWNLOAD SOURCE CODE

Leave a Reply