DEV Community

Cover image for OIDC Authentication for Express Apps with Asgardeo
Suvin Nimnaka
Suvin Nimnaka

Posted on

 

OIDC Authentication for Express Apps with Asgardeo

In my previous article, I discussed how we can use Asgardeo Node SDK to add authentication to your Express app. As I mentioned before, the process of using the Node SDK in an Express app is not straightforward because the Node SDK is a generic SDK which is compatible across any Node JS platform. In this article, I will show you how you can use the Asgardeo Express SDK to add authentication to your Express app easily.

TLDR;
Try the official sample app here.

Prerequisites

  • An Asgardeo organization. (You can create an organization upon registration at https://asgardeo.io/signup).
  • A Standard Based Application - Once you create an organization in the Asgardeo Console, you can create a Standard Based Application from the dashboard. (More info)

Projet Initialization
Create a new directory (a folder) and open the directory using your code editor. Open a terminal and type yarn init --y and it will initialize a new project and create a package.json file.

The next step is to install the dependancies.

yarn add @asgardeo/auth-express cookie-parser express
Enter fullscreen mode Exit fullscreen mode

Then add Nodemon as a dev dependancy to hot reload your changes.

yarn add -D nodemon
Enter fullscreen mode Exit fullscreen mode

Once you install Nodemon, modify the package.json and add "serve": "nodemon server.js" in the scripts section so we can use Nodemon to run the server.

Create an Express app
Create a new file and name it as server.js.
Then create a simple express server inside your server.js file. You can use the code below.

const express = require('express');
const cookieParser = require('cookie-parser');

//Define the Port
const PORT = 5000;

//Initialize Express App
const app = express();
app.use(cookieParser());

app.get("/", (req, res) => {
    res.send("Hello World");
});

//Start the app and listen on the PORT
app.listen(PORT, () => { console.log(`Server Started at PORT ${ PORT }`); });
Enter fullscreen mode Exit fullscreen mode

After creating the server, run it using,

yarn run serve
Enter fullscreen mode Exit fullscreen mode

Now if you navigate to http://localhost:5000, you should see a "Hello World" response from the server.

Add configuration for Asgardeo Authentication
Create a new file in the directory and name it as config.js. Inside this file, you need to specify the configuration for the Asgardeo Auth.

const config = {
   clientID: "YOUR_CLIENT_ID",
   clientSecret: "YOUR_CLIENT_SECRET",
   baseUrl: "YOUR_BASE_URL",
   appURL: "http://localhost:5000",
   scope: ["openid", "profile"]
};
module.exports = config;
Enter fullscreen mode Exit fullscreen mode

Replace the clientID, clientSecret and baseUrl from the values you get from Asgardeo Console. Since we run our server in http://localhost:5000, we have to add it as the appURL.

Note:
Make sure you add localhost:5000 as an allowed origin and add localhost:5000/login as an authorized redirect URL in the console. We will discuss why should we authorize localhost:5000/login endpoint specifically later on.

Use the AsgardeoAuth middleware
Open the server.js file and import the middleware from the SDK.

const { AsgardeoExpressClient } = require("@asgardeo/auth-express");
Enter fullscreen mode Exit fullscreen mode

Then instantiate the Asgardeo Express client with the config we created earlier.

AsgardeoExpressClient.getInstance(config);
Enter fullscreen mode Exit fullscreen mode

Now you have to define three callback functions which are needed to initiate the middleware.

  1. onSignIn - Handle a successful user sign in.
  2. onSignOut - Handle a successful user sign out.
  3. onError - Handle errors that might occur in the authentication process.
const onSignIn = (res, response) => {
  if (response) {
    res.status(200).send(response);
  }else{
    res.status(500).send("Something went wrong");
  }
};

const onSignOut = (res) => {
  res.status(200).send("Sign out successful");
};

const onError = (res, error) => {
  if(error){
    res.status(400).send(error);
  }else{
    res.status(500).send("Something went wrong");
  }
};
Enter fullscreen mode Exit fullscreen mode

After defining the callback functions, use the middleware with the Express app we created.

app.use(
  AsgardeoExpressClient.asgardeoExpressAuth(onSignIn, onSignOut, onError)
);
Enter fullscreen mode Exit fullscreen mode

That is all you have to do with the Express SDK to implement authentication. At this point, you can just navigate to http://localhost:5000/login and authenticate yourself. That brings me to explain why we added localhost:5000/login as an authorized redirect URL. The SDK itself is pre-configured to set the login endpoint to /login and to set the logout endpoint to /logout. So even though you didn't have to implement the logic for those 2 endpoints, you still need to authorize the endpoints in the console in order to function properly.

In case you don't like the pre-configured login and logout paths, you can always override the defaults in the config file. All you have to do is add another property to the config object as follows.

const config = {
   ...config,
   loginPath : "/customLogin",
   logoutPath: "/customLogout"
}
Enter fullscreen mode Exit fullscreen mode

Don't forget to change the authorized redirect URL in the console if you're using a custom login and logout paths.

Implementing Protected Routes
In some use cases, you may want to protect a specific route with a login. To do this, Asgardeo Express SDK provides you with a simple middleware. All you have to do is, attach the isAuthenticated middleware to the route you want to protect.

app.get("/protected", isAuthenticated, async (req, res) => {
    res.status(200).send({
        message: "Hello from protected route!"
    });
});
Enter fullscreen mode Exit fullscreen mode

Image description

The Asgardeo Express SDK has many features in addition to the basic login functions I described above. You can check them out at Express SDK GitHub repo. As always, feel free to reach me if you have any questions and you are welcome to make contributions to the SDK as well. Thanks for reading!

Top comments (0)

Visualizing Promises and Async/Await 🤯

async await

☝️ Check out this all-time classic DEV post