# Express Integrated OIDC Single Sign-On Guide

This article takes the Express framework based on the Node.js platform as an example and integrates the Node.js identity authentication middleware Passport.js to introduce in detail how Express integrates Authing OIDC single sign-on.

OIDC protocol: OIDC (OpenID Connect) is an identity authentication standard protocol based on the OAuth2 protocol. OIDC uses the OAuth2 authorization server to provide user identity authentication for third-party clients, and pass the corresponding identity authentication information to the client, which can be applied to various types of clients.

Passport: Passport is an authentication middleware for Node.js, which is particularly flexible and modular. It is very convenient to embed any Express-based web application. Support user name password, Facebook and Twitter authentication.

# Configure Authing OIDC application

Register from Authing.cn and enter the Authing console to create an OIDC application and configure application information.

The detailed configuration is as follows:

  • Application name: Your Application Name
  • Authentication address: https://your-application-domain.authing.cn
  • Callback URL: Callback address after application login, for example: http://localhost:3004/auth/cb
  • Authorization mode: default authorization_code, refresh_token, authing Token
  • Return type: default code
  • Authentication method for token exchange: default client_secret_post
  • id_token signature algorithm: HS256 by default

After configuration, the effective information of OIDC is saved at the same time, which is convenient for the later Express integration use.

  • App ID: 5f34e94bece50b891729e345
  • App Secret: 8226514d6740e5a9cd94fad4991e02e9
  • Issuer: https://aj00.authing.cn/oauth/oidc
  • Configuration information: https://aj00.authing.cn/oauth/oidc/.well-known/openid-configuration
  • Callback address: http://localhost:3004/auth/cb

# Express Integration Authing OIDC

(1) Express builds local services

const express = require('express');
var app = express();
app.listen(3004, () => console.log(`Example app listening on port 3004!`))

(2) Connect to the OIDC application and register the'oidc' strategy

const passport = require('passport');
const {Strategy, Issuer} = require('openid-client');
const config = {// oidc configuration information
        appID: '5f34e94bece50b891729e345',
        appSecret:'8226514d6740e5a9cd94fad4991e02e9',
        issuer:'https://aj00.authing.cn/oauth/oidc',
        configInfo:'https://aj00.authing.cn/oauth/oidc/.well-known/openid-configuration',
        callbackUrl:'http://localhost:3004/auth/cb'
}

(async () => {
    const issuer = await Issuer.discover(config.configInfo) // connect to oidc application
    const client = new issuer.Client({ // Initialize issuer information
        client_id: config.appID,
        client_secret: config.appSecret,
        id_token_signed_response_alg:'HS256',
        token_endpoint_auth_method:'client_secret_post',
    });
    const params = {
        redirect_uri: config.callbackUrl,
        scope:'openid profile email phone',
        grant_type:'authorization_code',
        response_type:'code',
        prompt:'consent',
    }
    // possport register oidc strategy
    passport.use('oidc', new Strategy({ client, params }, (tokenset, userinfo, done) => {
        return done(null, userinfo); // return user information
    }));
})()

(3) Define OIDC access, callback, user information query and other interfaces

app.get('/auth', passport.authenticate('oidc'));
app.get('/auth/cb', passport.authenticate('oidc', {
    successRedirect:'/',
    failureRedirect:'/',
}));
app.get('/user', (req, res) => {
    res.send(req.user)
})
app.get('/', (req, res) => {
    res.send("home")
})

(4) In addition to the above core steps, to store sesssion information, serialized user information, logout, etc., please refer to the complete Express integrated Authing OIDC code file in this article.

const express = require('express');
const session = require('express-session');
const passport = require('passport');
const {Strategy, Issuer} = require('openid-client');
const config = {
        appID: '5f34e94bece50b891729e345',
        appSecret:'8226514d6740e5a9cd94fad4991e02e9',
        issuer:'https://aj00.authing.cn/oauth/oidc',
        configInfo:'https://aj00.authing.cn/oauth/oidc/.well-known/openid-configuration',
        callbackUrl:'http://localhost:3004/auth/cb'
}

(async () => {
    
 const issuer = await Issuer.discover(config.configInfo)
    const client = new issuer.Client({
        client_id: config.appID,
        client_secret: config. appSecret,
        id_token_signed_response_alg:'HS256',
        token_endpoint_auth_method:'client_secret_post',
    });
    const params = {
        redirect_uri: config.callbackUrl,
        scope:'openid profile email phone',
        grant_type:'authorization_code',
        response_type:'code',
        prompt:'consent',
    }
    var app = express();
    app.use(session({
        secret:'keyboard cat',
        resave: true,
        saveUninitialized: true}));
    app.use(passport.initialize());
    app.use(passport.session());
    passport.use('oidc', new Strategy({ client, params }, (tokenset, userinfo, done) => {
        return done(null, userinfo);
    }));
    
    app.get('/auth', passport.authenticate('oidc'));
    app.get('/auth/cb', passport.authenticate('oidc', {
        successRedirect:'/',
        failureRedirect:'/user',
    }));
    app.get('/user', (req, res) => {
        res.send(req.user)
    })
    app.get('/', (req, res) => {
        res.send("home")
    })
    app.get('/logout', (req, res) => {
        const logoutBaseURL ='https://aj00.authing.cn/login/profile/logout'
        const appId = '5f17f5d6f64fb07b7094a41b'
        const logoutRedirectURL ='http://localhost:3004'
        const logoutUrl = `${logoutBaseURL}?app_id=${appId}&redirect_uri=${logoutRedirectURL}`
        req.session.destroy();
        res.redirect(logoutUrl)
    })
    passport.serializeUser(function (user, done) {
        done(null, user);
     });
     passport.deserializeUser(function (id, done) {
         done(null, {client_id: id });
     });
     app.listen(3004, () => console.log(`Example app listening on port 3004!`))
})()

For more information, please visit Authing official website (opens new window)