PageSourceSearch

https://socket.io/assets/js/29d8e286.75aa758c.js

js socket.io collected 2026-09-24 07:26:24 UTC 20,042 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunksample_website=self.webpackChunksample_website||[]).push([[6782],{3905:(e,n,t)=>{t.d(n,{Zo:()=>u,kt:()=>h});var r=t(7294);function s(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function o(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?a(Object(t),!0).forEach((function(n){s(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):a(Object(t)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}))}return e}function i(e,n){if(null==e)return{};var t,r,s=function(e,n){if(null==e)return{};var t,r,s={},a=Object.keys(e);for(r=0;r<a.length;r++)t=a[r],n.indexOf(t)>=0||(s[t]=e[t]);return s}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)t=a[r],n.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(s[t]=e[t])}return s}var l=r.createContext({}),p=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},u=function(e){var n=p(e.components);return r.createElement(l.Provider,{value:n},e.children)},c="mdxType",d={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},m=r.forwardRef((function(e,n){var t=e.components,s=e.mdxType,a=e.originalType,l=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),c=p(t),m=s,h=c["".concat(l,".").concat(m)]||c[m]||d[m]||a;return t?r.createElement(h,o(o({ref:n},u),{},{components:t})):r.createElement(h,o({ref:n},u))}));function h(e,n){var t=arguments,s=n&&n.mdxType;if("string"==typeof e||s){var a=t.length,o=new Array(a);o[0]=m;var i={};for(var l in n)hasOwnProperty.call(n,l)&&(i[l]=n[l]);i.originalType=e,i[c]="string"==typeof e?e:s,o[1]=i;for(var p=2;p<a;p++)o[p]=t[p];return r.createElement.apply(null,o)}return r.createElement.apply(null,t)}m.displayName="MDXCreateElement"},6541:(e,n,t)=>{t.r(n),t.d(n,{contentTitle:()=>l,default:()=>m,frontMatter:()=>i,metadata:()=>p,toc:()=>u});var r=t(3117),s=(t(7294),t(3905)),a=t(4866),o=t(5162);const i={title:"How to use with Passport.js"},l="How to use with Passport.js",p={type:"mdx",permalink:"/how-to/use-with-passport",source:"@site/src/pages/how-to/use-with-passport.md",title:"How to use with Passport.js",description:"Let's start from a basic application:",frontMatter:{title:"How to use with Passport.js"}},u=[{value:"Sharing the user context",id:"sharing-the-user-context",level:2},{value:"Using the user ID",id:"using-the-user-id",level:2}],c={toc:u},d="wrapper";
1function m(e){let{components:n,...t}=e;return(0,s.kt)(d,(0,r.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,s.kt)("h1",{id:"how-to-use-with-passportjs"},"How to use with Passport.js"),(0,s.kt)("p",null,"Let's start from a basic application:"),(0,s.kt)(a.Z,{groupId:"lang",mdxType:"Tabs"},(0,s.kt)(o.Z,{value:"cjs",label:"CommonJS",default:!0,mdxType:"TabItem"},(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-js"},'const express = require("express");\nconst { createServer } = require("node:http");\nconst { Server } = require("socket.io");\nconst session = require("express-session");\nconst bodyParser = require("body-parser");\nconst passport = require("passport");\nconst LocalStrategy = require("passport-local").Strategy;\nconst { join } = require("node:path");\n\nconst port = process.env.PORT || 3000;\n\nconst app = express();\nconst httpServer = createServer(app);\n\nconst sessionMiddleware = session({\n  secret: "changeit",\n  resave: true,\n  saveUninitialized: true,\n});\n\napp.use(sessionMiddleware);\napp.use(bodyParser.urlencoded({ extended: false }));\napp.use(passport.session());\n\napp.get("/", (req, res) => {\n  if (!req.user) {\n    return res.redirect("/login");\n  }\n  res.sendFile(join(__dirname, "index.html"));\n});\n\napp.get("/login", (req, res) => {\n  if (req.user) {\n    return res.redirect("/");\n  }\n  res.sendFile(join(__dirname, "login.html"));\n});\n\napp.post(\n  "/login",\n  passport.authenticate("local", {\n    successRedirect: "/",\n    failureRedirect: "/",\n  }),\n);\n\npassport.use(\n  new LocalStrategy((username, password, done) => {\n    if (username === "john" && password === "changeit") {\n      console.log("authentication OK");\n      return done(null, { id: 1, username });\n    } else {\n      console.log("wrong credentials");\n      return done(null, false);\n    }\n  }),\n);\n\npassport.serializeUser((user, cb) => {\n  console.log(`serializeUser ${user.id}`);\n  cb(null, user);\n});\n\npassport.deserializeUser((user, cb) => {\n  console.log(`deserializeUser ${user.id}`);\n  cb(null, user);\n});\n\nconst io = new Server(httpServer);\n\nhttpServer.listen(port, () => {\n  console.log(`application is running at: http://localhost:${port}`);\n});\n\n'))),(0,s.kt)(o.Z,{value:"mjs",label:"ES modules",mdxType:"TabItem"},(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-js"},'import express from "express";\nimport { createServer } from "http";\nimport { Server } from "socket.io";\nimport session from "express-session";\nimport bodyParser from "body-parser";\nimport passport from "passport";
1\nimport { Strategy as LocalStrategy } from "passport-local";\nimport { dirname, join } from "node:path";\nimport { fileURLToPath } from "node:url";\n\nconst port = process.env.PORT || 3000;\n\nconst app = express();\nconst httpServer = createServer(app);\n\nconst sessionMiddleware = session({\n  secret: "changeit",\n  resave: true,\n  saveUninitialized: true,\n});\n\napp.use(sessionMiddleware);\napp.use(bodyParser.urlencoded({ extended: false }));\napp.use(passport.session());\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\napp.get("/", (req, res) => {\n  if (!req.user) {\n    return res.redirect("/login");\n  }\n  res.sendFile(join(__dirname, "index.html"));\n});\n\napp.get("/login", (req, res) => {\n  if (req.user) {\n    return res.redirect("/");\n  }\n  res.sendFile(join(__dirname, "login.html"));\n});\n\napp.post(\n  "/login",\n  passport.authenticate("local", {\n    successRedirect: "/",\n    failureRedirect: "/",\n  }),\n);\n\napp.post("/logout", (req, res) => {\n  const sessionId = req.session.id;\n  req.session.destroy(() => {\n    // disconnect all Socket.IO connections linked to this session ID\n    io.to(`session:${sessionId}`).disconnectSockets();\n    res.status(204).end();\n  });\n});\n\npassport.use(\n  new LocalStrategy((username, password, done) => {\n    if (username === "john" && password === "changeit") {\n      console.log("authentication OK");\n      return done(null, { id: 1, username });\n    } else {\n      console.log("wrong credentials");\n      return done(null, false);\n    }\n  }),\n);\n\npassport.serializeUser((user, cb) => {\n  console.log(`serializeUser ${user.id}`);\n  cb(null, user);\n});\n\npassport.deserializeUser((user, cb) => {\n  console.log(`deserializeUser ${user.id}`);\n  cb(null, user);\n});\n\nconst io = new Server(httpServer);\n\nhttpServer.listen(port, () => {\n  console.log(`application is running at: http://localhost:${port}`);\n});\n'))),(0,s.kt)(o.Z,{value:"ts",label:"TypeScript",mdxType:"TabItem"},(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-ts"},'import express = require("express");\nimport { createServer } from "http";\nimport { Server } from "socket.io";\nimport session from "express-session";\nimport { type Request, type Response } from "express";\nimport bodyParser = require("body-parser");\nimport passport = require("passport");
1\nimport { Strategy as LocalStrategy } from "passport-local";\nimport { dirname, join } from "node:path";\nimport { fileURLToPath } from "node:url";\n\ndeclare global {\n  namespace Express {\n    interface User {\n      id: number;\n      username: string;\n    }\n  }\n}\n\nconst port = process.env.PORT || 3000;\n\nconst app = express();\nconst httpServer = createServer(app);\n\nconst sessionMiddleware = session({\n  secret: "changeit",\n  resave: true,\n  saveUninitialized: true,\n});\n\napp.use(sessionMiddleware);\napp.use(bodyParser.urlencoded({ extended: false }));\napp.use(passport.initialize());\napp.use(passport.session());\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\napp.get("/", (req, res) => {\n  if (!req.user) {\n    return res.redirect("/login");\n  }\n  res.sendFile(join(__dirname, "index.html"));\n});\n\napp.get("/login", (req, res) => {\n  if (req.user) {\n    return res.redirect("/");\n  }\n  res.sendFile(join(__dirname, "login.html"));\n});\n\napp.post(\n  "/login",\n  passport.authenticate("local", {\n    successRedirect: "/",\n    failureRedirect: "/",\n  }),\n);\n\napp.post("/logout", (req, res) => {\n  const sessionId = req.session.id;\n  req.session.destroy(() => {\n    // disconnect all Socket.IO connections linked to this session ID\n    io.to(`session:${sessionId}`).disconnectSockets();\n    res.status(204).end();\n  });\n});\n\npassport.use(\n  new LocalStrategy((username, password, done) => {\n    if (username === "john" && password === "changeit") {\n      console.log("authentication OK");\n      return done(null, { id: 1, username });\n    } else {\n      console.log("wrong credentials");\n      return done(null, false);\n    }\n  }),\n);\n\npassport.serializeUser((user, cb) => {\n  console.log(`serializeUser ${user.id}`);\n  cb(null, user);\n});\n\npassport.deserializeUser((user: Express.User, cb) => {\n  console.log(`deserializeUser ${user.id}`);\n  cb(null, user);\n});\n\nconst io = new Server(httpServer);\n\nhttpServer.listen(port, () => {\n  console.log(`application is running at: http://localhost:${port}`);\n});\n\n')),(0,s.kt)("admonition",{type:"note"},(0,s.kt)("p",{parentName:"admonition"},"You'll need those additional types:"),(0,s.kt)("pre",{parentName:"admonition"},(0,s.kt)("code",{parentName:"pre"},"npm install @types/express @types/express-session @types/passport @types/passport-local\n"))))),(0,s.kt)("h2",{id:"sharing-the-user-context"},"Sharing the user context"),(0,s.kt)("p",null,"The user context can be shared with the Socket.IO server by calling:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-js"},"function onlyForHandshake(middleware) {\n  return (req, res, next) => {\n    const isHandshake = req._query.sid === undefined;\n    if (isHandshake) {\n      middleware(req, res, next);\n    } else {\n      next();\n    }\n  };\n}\n\nio.engine.use(onlyForHandshake(sessionMiddleware));\nio.engine.use(onlyForHandshake(passport.session()));\nio.engine.use(\n  onlyForHandshake((req, res, next) => {\n    if (req.user) {\n      next();\n    } else {\n      res.writeHead(401);\n      res.end();\n    }\n  }),\n);\n")),(0,s.kt)("p",null,"Here's what happens:"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"the ",(0,s.kt)("a",{parentName:"li",href:"https://www.npmjs.com/package/express-session"},(0,s.kt)("inlineCode",{parentName:"a"},"express-session"))," middleware retrieves the session context from the cookie"),(0,s.kt)("li",{parentName:"ul"},"the ",(0,s.kt)("a",{parentName:"li",href:"https://www.passportjs.org/"},(0,s.kt)("inlineCode",{parentName:"a"},"passport"))," middleware extracts the user context from the session"),(0,s.kt)("li",{parentName:"ul"},"and finally, the handshake is validated if the user context was found")),(0,s.kt)("admonition",{type:"tip"},(0,s.kt)("p",{parentName:"admonition"},"The ",(0,s.kt)("inlineCode",{parentName:"p"},"onlyForHandshake()")," method ensures that the middlewares are only applied to the first HTTP request of the session.")),(0,s.kt)("p",null,"You'll now have access to the ",(0,s.kt)("inlineCode",{parentName:"p"},"user")," object:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-js"},'io.on("connection", (socket) => {\n  const user = socket.request.user;\n});\n')),(0,s.kt)("h2",{id:"using-the-user-id"},"Using the user ID"),(0,s.kt)("p",null,"You can use the user ID to make the link between Express and Socket.IO:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-js"},'io.on("connection", (socket) => {\n  const userId = socket.request.user.id;\n\n  // the user ID is used as a room\n  socket.join(`user:${userId}`);\n});\n')),(0,s.kt)("p",null,"Which allows you to easily broadcast an event to all the connections of a given user:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-js"},'io.to(`user:${userId}`).emit("foo", "bar");\n')),(0,s.kt)("p",null,"You can also check whether a user is currently connected:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-js"},"const sockets = await io.in(`user:${userId}`).fetchSockets();\nconst isUserConnected = sockets.length > 0;\n")),(0,s.kt)("p",null,"That's it for the compatibility with ",(0,s.kt)("a",{parentName:"p",href:"https://www.passportjs.org/"},"Passport.js"),". Thanks for reading!"),(0,s.kt)("p",null,"The complete example can be found ",(0,s.kt)("a",{parentName:"p",href:"https://github.com/socketio/socket.io/tree/main/examples/passport-example"},"here"),"."),(0,s.kt)("admonition",{type:"tip"},(0,s.kt)(a.Z,{groupId:"lang",mdxType:"Tabs"},(0,s.kt)(o.Z,{value:"cjs",label:"CommonJS",default:!0,attributes:{className:"display-none"},mdxType:"TabItem"},(0,s.kt)("p",{parentName:"admonition"},"You can run this example directly in your browser on:"),(0,s.kt)("ul",{parentName:"admonition"},(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("a",{parentName:"li",href:"https://codesandbox.io/p/sandbox/github/socketio/socket.io/tree/main/examples/passport-example/cjs?file=index.js"},"CodeSandbox")),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("a",{parentName:"li",href:"https://stackblitz.com/github/socketio/socket.io/tree/main/examples/passport-example/cjs?file=index.js"},"StackBlitz"))),"  "),(0,s.kt)(o.Z,{value:"mjs",label:"ES modules",attributes:{className:"display-none"},mdxType:"TabItem"},(0,s.kt)("p",{parentName:"admonition"},"You can run this example directly in your browser on:"),(0,s.kt)("ul",{parentName:"admonition"},(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("a",{parentName:"li",href:"https://codesandbox.io/p/sandbox/github/socketio/socket.io/tree/main/examples/passport-example/esm?file=index.js"},"CodeSandbox")),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("a",{parentName:"li",href:"https://stackblitz.com/github/socketio/socket.io/tree/main/examples/passport-example/esm?file=index.js"},"StackBlitz"))),"  "),(0,s.kt)(o.Z,{value:"ts",label:"TypeScript",attributes:{className:"display-none"},mdxType:"TabItem"},(0,s.kt)("p",{parentName:"admonition"},"You can run this example directly in your browser on:"),(0,s.kt)("ul",{parentName:"admonition"},(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("a",{parentName:"li",href:"https://codesandbox.io/p/sandbox/github/socketio/socket.io/tree/main/examples/passport-example/ts?file=index.ts"},"CodeSandbox")),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("a",{parentName:"li",href:"https://stackblitz.com/github/socketio/socket.io/tree/main/examples/passport-example/ts?file=index.ts"},"StackBlitz"))),"  "))))}m.isMDXComponent=!0},5162:(e,n,t)=>{t.d(n,{Z:()=>o});var r=t(7294),s=t(4334);const a={tabItem:"tabItem_Ymn6"};function o(e){let{children:n,hidden:t,className:o}=e;return r.createElement("div",{role:"tabpanel",className:(0,s.Z)(a.tabItem,o),hidden:t},n)}},4866:(e,n,t)=>{t.d(n,{Z:()=>w});var r=t(3117),s=t(7294),a=t(4334),o=t(2466),i=t(6550),l=t(1980),p=t(7392),u=t(12);function c(e){return function(e){return s.Children.map(e,(e=>{if(!e||(0,s.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad <Tabs>
1 child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the <Tabs> component should be <TabItem>, and every <TabItem> should have a unique "value" prop.`)}))?.filter(Boolean)??[]}(e).map((e=>{let{props:{value:n,label:t,attributes:r,default:s}}=e;return{value:n,label:t,attributes:r,default:s}}))}function d(e){const{values:n,children:t}=e;return(0,s.useMemo)((()=>{const e=n??c(t);return function(e){const n=(0,p.l)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in <Tabs>. Every value needs to be unique.`)}(e),e}),[n,t])}function m(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function h(e){let{queryString:n=!1,groupId:t}=e;const r=(0,i.k6)(),a=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)throw new Error('Docusaurus error: The <Tabs> component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return t??null}({queryString:n,groupId:t});return[(0,l._X)(a),(0,s.useCallback)((e=>{if(!a)return;const n=new URLSearchParams(r.location.search);n.set(a,e),r.replace({...r.location,search:n.toString()})}),[a,r])]}function f(e){const{defaultValue:n,queryString:t=!1,groupId:r}=e,a=d(e),[o,i]=(0,s.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the <Tabs> component requires at least one <TabItem> children component");if(n){if(!m({value:n,tabValues:t}))throw new Error(`Docusaurus error: The <Tabs> has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=t.find((e=>e.default))??t[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:a}))),[l,p]=h({queryString:t,groupId:r}),[c,f]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[r,a]=(0,u.Nk)(t);return[r,(0,s.useCallback)((e=>{t&&a.set(e)}),[t,a])]}({groupId:r}),b=(()=>{const e=l??c;return m({value:e,tabValues:a})?e:null})();(0,s.useLayoutEffect)((()=>{b&&i(b)}),[b]);return{selectedValue:o,selectValue:(0,s.useCallback)((e=>{if(!m({value:e,tabValues:a}))throw new Error(`Can't select invalid tab value=${e}`);i(e),p(e),f(e)}),[p,f,a]),tabValues:a}}var b=t(2389);const g={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};function k(e){let{className:n,block:t,selectedValue:i,selectValue:l,tabValues:p}=e;const u=[],{blockElementScrollPositionUntilNextRender:c}=(0,o.o5)(),d=e=>{const n=e.currentTarget,t=u.indexOf(n),r=p[t].value;r!==i&&(c(n),l(r))},m=e=>{let n=null;switch(e.key){case"Enter":d(e);break;case"ArrowRight":{const t=u.indexOf(e.currentTarget)+1;n=u[t]??u[0];break}case"ArrowLeft":{const t=u.indexOf(e.currentTarget)-1;n=u[t]??u[u.length-1];break}}n?.focus()};return s.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,a.Z)("tabs",{"tabs--block":t},n)},p.map((e=>{let{value:n,label:t,attributes:o}=e;return s.createElement("li",(0,r.Z)({role:"tab",tabIndex:i===n?0:-1,"aria-selected":i===n,key:n,ref:e=>u.push(e),onKeyDown:m,onClick:d},o,{className:(0,a.Z)("tabs__item",g.tabItem,o?.className,{"tabs__item--active":i===n})}),t??n)})))}function y(e){let{lazy:n,children:t,selectedValue:r}=e;const a=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=a.find((e=>e.props.value===r));return e?(0,s.cloneElement)(e,{className:"margin-top--md"}):null}return s.createElement("div",{className:"margin-top--md"},a.map(((e,n)=>(0,s.cloneElement)(e,{key:n,hidden:e.props.value!==r}))))}function v(e){const n=f(e);return s.createElement("div",{className:(0,a.Z)("tabs-container",g.tabList)},s.createElement(k,(0,r.Z)({},e,n)),s.createElement(y,(0,r.Z)({},e,n)))}function w(e){const n=(0,b.Z)();return s.createElement(v,(0,r.Z)({key:String(n)},e))}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.