How to create OIDC Client in Nodejs
Introduction
In this artice we will see how to implement OpenID Client in Nodejs using Passport and openid-client.
If you want to implement your own OAuth2.0 Authorization server, you can follow my this article.
Step-By-Step Implementation
Note : I will use oidc-provider which I had created in previous article and it is running on http://localhost:3000/oidc
You can use any oidc-provider.
- we will use npm to create our oidc-client project, First, let’s create our project directory, then we run the init command.
mkdir OIDC-Client
cd OIDC-Client
npm init -y
2. Install required packages
npm install express nodemon cookie-parser express-sessionoryarn add express nodemon cookie-parser express-session
3. create an index.js file and write following codes to create simple server
const express = require('express');
const session = require('express-session');
const cookieParser = require('cookie-parser');
const path = require("path");
const http = require("http");const app = express();
app.use(cookieParser());
app.use(express.urlencoded({
extended: true,
}));app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(express.static(path.join(__dirname, 'public')));app.use(session({
secret: 'secret',
resave: false,
saveUninitialized: true,}));const httpServer = http.createServer(app)
httpServer.listen(8080,() =>{
console.log(`Http Server Running on port 3004`)
})
4. Now , Install passport ,openid-client and helmet
I am sure you must be familiar with passport and helmet. if not let’s see in brief.
passport
— Passport is authentication middleware for Node.js. It’s sole purpose is to authenticate requests, which it does through an extensible set of plugins known as strategies.
for this project I am going to use openid-client strategies.
openid-client
— openid-client is a server side OpenID Relying Party (RP, Client) implementation for Node.js runtime.
helmet
— Helmet helps us to secure our Express apps by setting various HTTP headers.
npm install passport openid-client helmetor yarn add passport openid-client helmet
5. Import passport and helmet . To use passport in Express-based application , we will have to configure following middlewares.
const passport = require('passport');
const helmet = require('helmet');//Helmet midddleware
app.use(helmet());//Passport Middlewares
app.use(passport.initialize());
app.use(passport.session());
6. Passport maintains persistent login sessions. In order for persistent sessions to work, the authenticated user must be serialized to the session, and deserialized when subsequent requests are made.
passport.serializeUser((user, done) => {
console.log('-----------------------------');
console.log('serialize user');
console.log(user);
console.log('-----------------------------');
done(null, user);
});passport.deserializeUser((user, done) => {
console.log('-----------------------------');
console.log('deserialize user');
console.log(user);
console.log('-----------------------------');
done(null, user);
});
7. import Issuer and Strategy from openid-client and discover an Issuer configuration using its published .well-known endpoints
const { Issuer,Strategy } = require('openid-client');Issuer.discover('http://localhost:3000/oidc')
.then(function (oidcIssuer) {
var client = new oidcIssuer.Client({
client_id: 'oidcCLIENT',
client_secret: 'client_super_secret',
redirect_uris: ["http://localhost:8080/login/callback"],
response_types: ['code'],});passport.use('oidc', new Strategy({ client,passReqToCallback: true}, (req, tokenSet, userinfo, done) => {
console.log("tokenSet",tokenSet);
console.log("userinfo",userinfo); // do whatever you want with tokenset and userinfo req.session.tokenSet = tokenSet;
req.session.userinfo = userinfo;
return done(null, tokenSet.claims());
}));
});
8. Create routes for login, login callback
app.get('/login',(req, res, next) => {
console.log('-----------------------------');
console.log('Login Handler Started');
next();
},
passport.authenticate('oidc',{scope:"openid"}));app.get('/login/callback',(req,res,next) =>
{
passport.authenticate('oidc',{
successRedirect: '/user',
failureRedirect: '/' })
(req, res, next)
})
create home route and /user route
app.get("/",(req,res) =>{
res.send(" <a href='/login'>Log In with OAuth 2.0 Provider </a>")})app.get ("/user",(req,res) =>{res.header("Content-Type",'application/json'); res.end(JSON.stringify({tokenset:req.session.tokenSet,userinfo:req.session.userinfo},null,2));})
9. So Our Final index.js will be like this
10 . Run index.js to start server
nodemon index.js
11 . Go to http://localhost:8080 on browser. and click on “Log in with OAuth 2.0 Provider”
12. You will be redirected to OAuth Provider Login Page. As I am using prevoiusly created oidc-provider which is running on http://localhost:3000/oidc so it will take me following page
put any random username and password.
After you continue it will redirect us to client redirect url
Voilla..!! You got access_token
How to get userinfo from this access_token ?
Copy access_token and and go to postman and make a post request with this access_token to userinfo endpoint (you can get this endpoint in .well-known/openid-configuration of provider).
put access_token in x-www-form-urlencoded and send, you will get userinfo in response.