跳转到主要内容

标签(标签)

资源精选(342) Go开发(108) Go语言(103) Go(99) angular(82) LLM(75) 大语言模型(63) 人工智能(53) 前端开发(50) LangChain(43) golang(43) 机器学习(39) Go工程师(38) Go程序员(38) Go开发者(36) React(33) Go基础(29) Python(24) Vue(22) Web开发(20) Web技术(19) 精选资源(19) 深度学习(19) Java(18) ChatGTP(17) Cookie(16) android(16) 前端框架(13) JavaScript(13) Next.js(12) 安卓(11) 聊天机器人(10) typescript(10) 资料精选(10) NLP(10) 第三方Cookie(9) Redwoodjs(9) LLMOps(9) Go语言中级开发(9) 自然语言处理(9) PostgreSQL(9) 区块链(9) mlops(9) 安全(9) 全栈开发(8) ChatGPT(8) OpenAI(8) Linux(8) AI(8) GraphQL(8) iOS(8) 软件架构(7) Go语言高级开发(7) AWS(7) C++(7) 数据科学(7) whisper(6) Prisma(6) 隐私保护(6) RAG(6) JSON(6) DevOps(6) 数据可视化(6) wasm(6) 计算机视觉(6) 算法(6) Rust(6) 微服务(6) 隐私沙盒(5) FedCM(5) 语音识别(5) Angular开发(5) 快速应用开发(5) 提示工程(5) Agent(5) LLaMA(5) 低代码开发(5) Go测试(5) gorm(5) REST API(5) 推荐系统(5) WebAssembly(5) GameDev(5) CMS(5) CSS(5) machine-learning(5) 机器人(5) 游戏开发(5) Blockchain(5) Web安全(5) Kotlin(5) 低代码平台(5) 机器学习资源(5) Go资源(5) Nodejs(5) PHP(5) Swift(5) 智能体(4) devin(4) Blitz(4) javascript框架(4) Redwood(4) GDPR(4) 生成式人工智能(4) Angular16(4) Alpaca(4) 编程语言(4) SAML(4) JWT(4) JSON处理(4) Go并发(4) kafka(4) 移动开发(4) 移动应用(4) security(4) 隐私(4) spring-boot(4) 物联网(4) nextjs(4) 网络安全(4) API(4) Ruby(4) 信息安全(4) flutter(4) 专家智能体(3) Chrome(3) CHIPS(3) 3PC(3) SSE(3) 人工智能软件工程师(3) LLM Agent(3) Remix(3) Ubuntu(3) GPT4All(3) 软件开发(3) 问答系统(3) 开发工具(3) 最佳实践(3) RxJS(3) SSR(3) Node.js(3) Dolly(3) 移动应用开发(3) 低代码(3) IAM(3) Web框架(3) CORS(3) 基准测试(3) Go语言数据库开发(3) Oauth2(3) 并发(3) 主题(3) Theme(3) earth(3) nginx(3) 软件工程(3) azure(3) keycloak(3) 生产力工具(3) gpt3(3) 工作流(3) C(3) jupyter(3) 认证(3) prometheus(3) GAN(3) Spring(3) 逆向工程(3) 应用安全(3) Docker(3) Django(3) R(3) .NET(3) 大数据(3) Hacking(3) 渗透测试(3) C++资源(3) Mac(3) 微信小程序(3) Python资源(3) JHipster(3) 大型语言模型(2) 语言模型(2) 可穿戴设备(2) JDK(2) SQL(2) Apache(2) Hashicorp Vault(2) Spring Cloud Vault(2) Go语言Web开发(2) Go测试工程师(2) WebSocket(2) 容器化(2) AES(2) 加密(2) 输入验证(2) ORM(2) Fiber(2) Postgres(2) Gorilla Mux(2) Go数据库开发(2) 模块(2) 泛型(2) 指针(2) HTTP(2) PostgreSQL开发(2) Vault(2) K8s(2) Spring boot(2) R语言(2) 深度学习资源(2) 半监督学习(2) semi-supervised-learning(2) architecture(2) 普罗米修斯(2) 嵌入模型(2) productivity(2) 编码(2) Qt(2) 前端(2) Rust语言(2) NeRF(2) 神经辐射场(2) 元宇宙(2) CPP(2) 数据分析(2) spark(2) 流处理(2) Ionic(2) 人体姿势估计(2) human-pose-estimation(2) 视频处理(2) deep-learning(2) kotlin语言(2) kotlin开发(2) burp(2) Chatbot(2) npm(2) quantum(2) OCR(2) 游戏(2) game(2) 内容管理系统(2) MySQL(2) python-books(2) pentest(2) opengl(2) IDE(2) 漏洞赏金(2) Web(2) 知识图谱(2) PyTorch(2) 数据库(2) reverse-engineering(2) 数据工程(2) swift开发(2) rest(2) robotics(2) ios-animation(2) 知识蒸馏(2) 安卓开发(2) nestjs(2) solidity(2) 爬虫(2) 面试(2) 容器(2) C++精选(2) 人工智能资源(2) Machine Learning(2) 备忘单(2) 编程书籍(2) angular资源(2) 速查表(2) cheatsheets(2) SecOps(2) mlops资源(2) R资源(2) DDD(2) 架构设计模式(2) 量化(2) Hacking资源(2) 强化学习(2) flask(2) 设计(2) 性能(2) Sysadmin(2) 系统管理员(2) Java资源(2) 机器学习精选(2) android资源(2) android-UI(2) Mac资源(2) iOS资源(2) Vue资源(2) flutter资源(2) JavaScript精选(2) JavaScript资源(2) Rust开发(2) deeplearning(2) RAD(2)

Single sign-on (SSO) is a property of identity and access management (IAM) that enables users to securely authenticate with multiple applications and websites by logging in only once with just one set of credentials (username and password).

Here in this article, we will Implement Single Sign-On in a Node.js App with SAML authentication strategy using Passport.js middleware if you want to read more on Single Sign-on and SAML you can read this article below.

Single Sign-On(SSO) — SAML Authentication Explained

What is Single sign-on?

medium.com

First, we need an Identity Provider which can be an organization’s active directory or any free identity provider like OneLogin. For testing purposes I used OneLogin identity provider it allows us to create a developer account and we can play around it https://developers.onelogin.com/

We can configure our App please follow documentation for more information.

We will configure this information from the SAML-Test connector into our Passport.js middleware.

This includes certificate, endpoint ie. entry point will be the entry point for our app this will redirect our app on the authentication page.

We need to configure our app information into the identity provider to establish trust.

Application details are all Service Provider’s configuration like issuer and consumer callback URL

Consumer URL we will configure Service Provider’s Callback Url which will be called on authentication success.

Above information provided by the identity provider which will set up trust between an identity provider and service provider. Here service provider will be a backend app that will make trust between multiple identity providers like Azure IDP, OneLogin, Google OAuth, and so on.

{
    entryPoint: 'https://ad.example.net/adfs/ls/',
    issuer: 'DEV-BrightLab',
    callbackUrl: 'https://your-app.example.net/login/callback',
    cert: 'MIICizCCAfQCCQCY8tKaMc0BMjANBgkqh ... W=='
 }

Here we have details which we will set up in our service provider to establish a trust between the service provider and identity provider.

entryPoint: is the URL provided by Identity Provider which will be used to redirect users on the login page if not authenticated.

issuer: is a string provided to the Identity Provider to uniquely identify Service Provider.

callbackUrl: This will be the URL of the Service Provider which will consume the SAML response once authentication is done on Identity Provider. Identity Provider will call this URL.

cert: This is the certificate provided by Identity Provider. This will be used to establish the trust between Identity Provider and Service Provider.

Now we are ready to implement our service provider using Passport.js

Passport is authentication middleware for Node.js. extremely flexible and modular, Passport can be unobtrusively dropped into any Express-based web application. A comprehensive set of strategies support authentication using a username and password, Facebook, Twitter, and more.

npm install passport

Install passport-saml, it is a SAML 2.0 authentication provider for Passport, the Node.js authentication library. The code was originally based on Michael Bosworth’s express-saml library.

npm install passport-saml

First We will Setup our passport handler middleware with our identity provider configuration. This is for a single identity provider strategy.

const passport = require('passport');
const passportSaml = require('passport-saml');

passport.serializeUser((user, done) => {
  done(null, user);
});

passport.deserializeUser((user, done) => {
  done(null, user);
});

// SAML strategy for passport -- Single IPD
const strategy = new passportSaml.Strategy(
  {
    entryPoint: process.env.SSO_ENTRYPOINT,
    issuer: process.env.SSO_ISSUER,
    callbackUrl: process.env.SSO_CALLBACK_URL,
    cert: process.env.SSO_CERT,
  },
  (profile, done) => done(null, profile),
);

passport.use(strategy);

module.exports = passport;

Now we can configure this Passport middleware into our app and initialize it.

const express = require('express');
const helmet = require('helmet');
const {
  passport,
} = require('./config');

const {
  userRouter: userV1Router,
} = require('./server/v1/routes');

const { errorHandler } = require('./server/v1/middlewares');

const app = express();

app.use(express.urlencoded({
  extended: true,
}));

app.use(express.json({ limit: '15mb' }));
app.use(helmet());

app.use(passport.initialize());
app.use(passport.session());

//= ==========Registering Router==========
app.use('/user/v1/', userV1Router);

//= ======ERROR Handler
app.use(errorHandler);

module.exports = app;
  • We will set up two routes one is the GET route which will be the entry point of SSO into the application. when it will be called passport will authenticate and verify the trust in between service provider and the identity provider.
  • Another will be the consumer which will be called by the identity provider once it validated the credentials. Here Request body will be a SAML which is a base64 encoded body here I used the Saml2js module to parse the assertion in the SAML body which will provide the details of user who logged in.

Here is the router code for the Router

const express = require('express');
const useragent = require('useragent');
const Saml2js = require('saml2js');

const { passport } = require('../../../../config');

const {
  handler,
} = require('../../middlewares');

const {
  userLogin,
} = require('./../../controller');

const userAgentHandler = (req, res, next) => {
  const agent = useragent.parse(req.headers['user-agent']);
  const deviceInfo = Object.assign({}, {
    device: agent.device,
    os: agent.os,
  });
  req.device = deviceInfo;
  next();
};

const router = express.Router();

/**
 * This Route Authenticates req with IDP
 * If Session is active it returns saml response
 * If Session is not active it redirects to IDP's login form
 */
router.get('/login/sso',
  passport.authenticate('saml', {
    successRedirect: '/',
    failureRedirect: '/login',
  }));

/**
 * This is the callback URL
 * Once Identity Provider validated the Credentials it will be called with base64 SAML req body
 * Here we used Saml2js to extract user Information from SAML assertion attributes
 * If every thing validated we validates if user email present into user DB.
 * Then creates a session for the user set in cookies and do a redirect to Application
 */
router.post('/login/sso/callback',
  userAgentHandler,
  passport
    .authenticate('saml', { failureRedirect: '/', failureFlash: true }), (req, res, next) => {
    const xmlResponse = req.body.SAMLResponse;
    const parser = new Saml2js(xmlResponse);
    req.samlUserObject = parser.toObject();
    next();
  },
  (req, res) => userLogin.createUserSession(res, req));

module.exports = router;

This is a user login controller which creates the session set in response cookies and redirect response to a UI Application page.

Let's put this all together and see how all this works…..

First, we call GET API localhost:9000/user/v1/users/login/sso

  • This GET API call checks if the active session is there or not, In my case, there was no active session it redirects me on an identity provider login page.
  • Once I entered my username and then password it authenticate request on identity provider and then it called the callback URL of service provider which we configured in the identity provider.
  • This POST callback URL localhost:9000/user/v1/users/login/sso/callback created a session for the application by validating request and redirects to the application dashboard page.

Well, We have successfully configured SAML based Single Sign-On

What if we have a SAAS based multitenant application which has different organizations and we need to configure Single Sign-On with these organization's Active Directory or their identity provider, In this case, we can use Passport’s MultiSAML strategy where we can configure SAML configuration on demand, we can identify organizations by subdomain or we can pass path params to these above URL. Let's configure MultiSamlStrategy

const passport = require('passport');
const MultiSamlStrategy = require('passport-saml/multiSamlStrategy');
const { cassandraClient } = require('../../config');

passport.serializeUser((user, done) => {
  done(null, user);
});

passport.deserializeUser((user, done) => {
  done(null, user);
});

const fetchSamlConfig = (request, done) => {
  const orgId = request.params.id;
  cassandraClient.instance.TenantSSOConfig.findOne({ orgId }, (err, org) => {
    if (err) {
      return done(err);
    }
    return done(null, JSON.parse(org.config));
  });
};

// saml strategy for passport
const strategy = new MultiSamlStrategy(
  {
    passReqToCallback: true, // makes req available in callback
    getSamlOptions(request, done) {
      fetchSamlConfig(request, done);
    },
  },
  (req, profile, done) => {
    done(null, profile);
  },
);
passport.use(strategy);

module.exports = passport;

Here getSamlOptions function will be invoked on passport.authenticate() middleware called here we are fetching SAML configuration from DB on the basis of request orgId and setting this config for this middleware.

Here we configure Routes with path params and also configured their value into identity provider.

He is how I configured my BrightLab application with my Organization’s Active Directory ie. Azure.

we provided callback URL as /login/sso/callback/orgNamehere orgName becomes the value for the path parm id and we fetch SAML configuration from DB by {orgId: orgName} and on calling login API it will be redirected to the meck azure login page.

On submitting id and password identity provider authenticates the request and calls the callback URL and Land on the dashboard Page. similarly, we can pass different org if we have configured it and stored it into our database and we can determine this on the basis on the subdomain as well.

If you want to implement multitenancy into the Node.js application you can read this article below.

Multitenant Node.js Application with mongoose (MongoDB)

Multitenancy is a reference to the mode of operation of software where multiple independent instances of one or…

medium.com

References :

Documentation

Passport is authentication middleware for Node. It is designed to serve a singular purpose: authenticate requests. When…

www.passportjs.org