Skip to content

Commit d943c3e

Browse files
docs: update the Passport.js example
1 parent 6ab2509 commit d943c3e

17 files changed

+641
-156
lines changed

examples/passport-example/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ This example shows how to retrieve the authentication context from a basic [Expr
55

66
![Passport example](assets/passport_example.gif)
77

8+
Please read the related guide: https://socket.io/how-to/use-with-passport
9+
810
## How to use
911

1012
```
+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Passport example</title>
6+
</head>
7+
<body>
8+
<p>Authenticated!</p>
9+
10+
<table>
11+
<tbody>
12+
<tr>
13+
<td>Status</td>
14+
<td><span id="status">Disconnected</span></td>
15+
</tr>
16+
<tr>
17+
<td>Socket ID</td>
18+
<td><span id="socket-id"></span></td>
19+
</tr>
20+
<tr>
21+
<td>Username</td>
22+
<td><span id="username"></span></td>
23+
</tr>
24+
</tbody>
25+
</table>
26+
27+
<form action="/logout" method="post">
28+
<div>
29+
<input type="submit" value="Log out" />
30+
</div>
31+
</form>
32+
33+
<script src="/socket.io/socket.io.js"></script>
34+
<script>
35+
const socket = io();
36+
const socketIdSpan = document.getElementById('socket-id');
37+
const usernameSpan = document.getElementById('username');
38+
const statusSpan = document.getElementById('status');
39+
40+
socket.on('connect', () => {
41+
statusSpan.innerText = 'connected';
42+
socketIdSpan.innerText = socket.id;
43+
44+
socket.emit('whoami', (username) => {
45+
usernameSpan.innerText = username;
46+
});
47+
});
48+
49+
socket.on('disconnect', () => {
50+
statusSpan.innerText = 'disconnected';
51+
socketIdSpan.innerText = '-';
52+
});
53+
</script>
54+
</body>
55+
</html>
+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
const express = require("express");
2+
const { createServer } = require("node:http");
3+
const { Server } = require("socket.io");
4+
const session = require("express-session");
5+
const bodyParser = require("body-parser");
6+
const passport = require("passport");
7+
const LocalStrategy = require("passport-local").Strategy;
8+
const { join } = require("node:path");
9+
10+
const port = process.env.PORT || 3000;
11+
12+
const app = express();
13+
const httpServer = createServer(app);
14+
15+
const sessionMiddleware = session({
16+
secret: "changeit",
17+
resave: true,
18+
saveUninitialized: true,
19+
});
20+
21+
app.use(sessionMiddleware);
22+
app.use(bodyParser.urlencoded({ extended: false }));
23+
app.use(passport.initialize());
24+
app.use(passport.session());
25+
26+
app.get("/", (req, res) => {
27+
if (!req.user) {
28+
return res.redirect("/login");
29+
}
30+
res.sendFile(join(__dirname, "index.html"));
31+
});
32+
33+
app.get("/login", (req, res) => {
34+
if (req.user) {
35+
return res.redirect("/");
36+
}
37+
res.sendFile(join(__dirname, "login.html"));
38+
});
39+
40+
app.post(
41+
"/login",
42+
passport.authenticate("local", {
43+
successRedirect: "/",
44+
failureRedirect: "/",
45+
}),
46+
);
47+
48+
app.post("/logout", (req, res) => {
49+
const sessionId = req.session.id;
50+
req.session.destroy(() => {
51+
// disconnect all Socket.IO connections linked to this session ID
52+
io.to(`session:${sessionId}`).disconnectSockets();
53+
res.status(204).end();
54+
});
55+
});
56+
57+
passport.use(
58+
new LocalStrategy((username, password, done) => {
59+
if (username === "john" && password === "changeit") {
60+
console.log("authentication OK");
61+
return done(null, { id: 1, username });
62+
} else {
63+
console.log("wrong credentials");
64+
return done(null, false);
65+
}
66+
}),
67+
);
68+
69+
passport.serializeUser((user, cb) => {
70+
console.log(`serializeUser ${user.id}`);
71+
cb(null, user);
72+
});
73+
74+
passport.deserializeUser((user, cb) => {
75+
console.log(`deserializeUser ${user.id}`);
76+
cb(null, user);
77+
});
78+
79+
const io = new Server(httpServer);
80+
81+
io.engine.use(sessionMiddleware);
82+
io.engine.use(passport.initialize());
83+
io.engine.use(passport.session());
84+
85+
io.engine.use(
86+
(req, res, next) => {
87+
if (req.user) {
88+
next();
89+
} else {
90+
res.writeHead(401);
91+
res.end();
92+
}
93+
},
94+
);
95+
96+
io.on("connection", (socket) => {
97+
const req = socket.request;
98+
99+
socket.join(`session:${req.session.id}`);
100+
socket.join(`user:${req.user.id}`);
101+
102+
socket.on("whoami", (cb) => {
103+
cb(req.user.username);
104+
});
105+
});
106+
107+
httpServer.listen(port, () => {
108+
console.log(`application is running at: http://localhost:${port}`);
109+
});

examples/passport-example/login.html renamed to examples/passport-example/cjs/login.html

+5-5
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@
88
<p>Not authenticated</p>
99
<form action="/login" method="post">
1010
<div>
11-
<label>Username:</label>
12-
<input type="text" name="username" />
11+
<label for="username">Username:</label>
12+
<input type="text" id="username" name="username" />
1313
<br/>
1414
</div>
1515
<div>
16-
<label>Password:</label>
17-
<input type="password" name="password" />
16+
<label for="password">Password:</label>
17+
<input type="password" id="password" name="password" />
1818
</div>
1919
<div>
2020
<input type="submit" value="Submit" />
2121
</div>
2222
</form>
2323
</body>
24-
</html>
24+
</html>
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "passport-example",
3+
"version": "0.0.1",
4+
"private": true,
5+
"type": "commonjs",
6+
"description": "Example with passport (https://www.passportjs.org)",
7+
"scripts": {
8+
"start": "node index.js"
9+
},
10+
"dependencies": {
11+
"express": "~4.17.3",
12+
"express-session": "~1.17.2",
13+
"passport": "^0.7.0",
14+
"passport-local": "^1.0.0",
15+
"socket.io": "^4.7.2"
16+
},
17+
"devDependencies": {
18+
"prettier": "^3.1.1"
19+
}
20+
}
+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Passport example</title>
6+
</head>
7+
<body>
8+
<p>Authenticated!</p>
9+
10+
<table>
11+
<tbody>
12+
<tr>
13+
<td>Status</td>
14+
<td><span id="status">Disconnected</span></td>
15+
</tr>
16+
<tr>
17+
<td>Socket ID</td>
18+
<td><span id="socket-id"></span></td>
19+
</tr>
20+
<tr>
21+
<td>Username</td>
22+
<td><span id="username"></span></td>
23+
</tr>
24+
</tbody>
25+
</table>
26+
27+
<form action="/logout" method="post">
28+
<div>
29+
<input type="submit" value="Log out" />
30+
</div>
31+
</form>
32+
33+
<script src="/socket.io/socket.io.js"></script>
34+
<script>
35+
const socket = io();
36+
const socketIdSpan = document.getElementById('socket-id');
37+
const usernameSpan = document.getElementById('username');
38+
const statusSpan = document.getElementById('status');
39+
40+
socket.on('connect', () => {
41+
statusSpan.innerText = 'connected';
42+
socketIdSpan.innerText = socket.id;
43+
44+
socket.emit('whoami', (username) => {
45+
usernameSpan.innerText = username;
46+
});
47+
});
48+
49+
socket.on('disconnect', () => {
50+
statusSpan.innerText = 'disconnected';
51+
socketIdSpan.innerText = '-';
52+
});
53+
</script>
54+
</body>
55+
</html>
+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import express from "express";
2+
import { createServer } from "http";
3+
import { Server } from "socket.io";
4+
import session from "express-session";
5+
import bodyParser from "body-parser";
6+
import passport from "passport";
7+
import { Strategy as LocalStrategy } from "passport-local";
8+
import { dirname, join } from "node:path";
9+
import { fileURLToPath } from "node:url";
10+
11+
const port = process.env.PORT || 3000;
12+
13+
const app = express();
14+
const httpServer = createServer(app);
15+
16+
const sessionMiddleware = session({
17+
secret: "changeit",
18+
resave: true,
19+
saveUninitialized: true,
20+
});
21+
22+
app.use(sessionMiddleware);
23+
app.use(bodyParser.urlencoded({ extended: false }));
24+
app.use(passport.initialize());
25+
app.use(passport.session());
26+
27+
const __dirname = dirname(fileURLToPath(import.meta.url));
28+
29+
app.get("/", (req, res) => {
30+
if (!req.user) {
31+
return res.redirect("/login");
32+
}
33+
res.sendFile(join(__dirname, "index.html"));
34+
});
35+
36+
app.get("/login", (req, res) => {
37+
if (req.user) {
38+
return res.redirect("/");
39+
}
40+
res.sendFile(join(__dirname, "login.html"));
41+
});
42+
43+
app.post(
44+
"/login",
45+
passport.authenticate("local", {
46+
successRedirect: "/",
47+
failureRedirect: "/",
48+
}),
49+
);
50+
51+
app.post("/logout", (req, res) => {
52+
const sessionId = req.session.id;
53+
req.session.destroy(() => {
54+
// disconnect all Socket.IO connections linked to this session ID
55+
io.to(`session:${sessionId}`).disconnectSockets();
56+
res.status(204).end();
57+
});
58+
});
59+
60+
passport.use(
61+
new LocalStrategy((username, password, done) => {
62+
if (username === "john" && password === "changeit") {
63+
console.log("authentication OK");
64+
return done(null, { id: 1, username });
65+
} else {
66+
console.log("wrong credentials");
67+
return done(null, false);
68+
}
69+
}),
70+
);
71+
72+
passport.serializeUser((user, cb) => {
73+
console.log(`serializeUser ${user.id}`);
74+
cb(null, user);
75+
});
76+
77+
passport.deserializeUser((user, cb) => {
78+
console.log(`deserializeUser ${user.id}`);
79+
cb(null, user);
80+
});
81+
82+
const io = new Server(httpServer);
83+
84+
io.engine.use(sessionMiddleware);
85+
io.engine.use(passport.initialize());
86+
io.engine.use(passport.session());
87+
88+
io.engine.use(
89+
(req, res, next) => {
90+
if (req.user) {
91+
next();
92+
} else {
93+
res.writeHead(401);
94+
res.end();
95+
}
96+
},
97+
);
98+
99+
io.on("connection", (socket) => {
100+
const req = socket.request;
101+
102+
socket.join(`session:${req.session.id}`);
103+
socket.join(`user:${req.user.id}`);
104+
105+
socket.on("whoami", (cb) => {
106+
cb(req.user.username);
107+
});
108+
});
109+
110+
httpServer.listen(port, () => {
111+
console.log(`application is running at: http://localhost:${port}`);
112+
});

0 commit comments

Comments
 (0)