mirror of
https://github.com/socketio/socket.io.git
synced 2026-01-10 15:37:58 -05:00
docs: update the Passport.js example
This commit is contained in:
@@ -5,6 +5,8 @@ This example shows how to retrieve the authentication context from a basic [Expr
|
||||
|
||||

|
||||
|
||||
Please read the related guide: https://socket.io/how-to/use-with-passport
|
||||
|
||||
## How to use
|
||||
|
||||
```
|
||||
|
||||
55
examples/passport-example/cjs/index.html
Normal file
55
examples/passport-example/cjs/index.html
Normal file
@@ -0,0 +1,55 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Passport example</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Authenticated!</p>
|
||||
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Status</td>
|
||||
<td><span id="status">Disconnected</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Socket ID</td>
|
||||
<td><span id="socket-id"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Username</td>
|
||||
<td><span id="username"></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<form action="/logout" method="post">
|
||||
<div>
|
||||
<input type="submit" value="Log out" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script src="/socket.io/socket.io.js"></script>
|
||||
<script>
|
||||
const socket = io();
|
||||
const socketIdSpan = document.getElementById('socket-id');
|
||||
const usernameSpan = document.getElementById('username');
|
||||
const statusSpan = document.getElementById('status');
|
||||
|
||||
socket.on('connect', () => {
|
||||
statusSpan.innerText = 'connected';
|
||||
socketIdSpan.innerText = socket.id;
|
||||
|
||||
socket.emit('whoami', (username) => {
|
||||
usernameSpan.innerText = username;
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('disconnect', () => {
|
||||
statusSpan.innerText = 'disconnected';
|
||||
socketIdSpan.innerText = '-';
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
109
examples/passport-example/cjs/index.js
Normal file
109
examples/passport-example/cjs/index.js
Normal file
@@ -0,0 +1,109 @@
|
||||
const express = require("express");
|
||||
const { createServer } = require("node:http");
|
||||
const { Server } = require("socket.io");
|
||||
const session = require("express-session");
|
||||
const bodyParser = require("body-parser");
|
||||
const passport = require("passport");
|
||||
const LocalStrategy = require("passport-local").Strategy;
|
||||
const { join } = require("node:path");
|
||||
|
||||
const port = process.env.PORT || 3000;
|
||||
|
||||
const app = express();
|
||||
const httpServer = createServer(app);
|
||||
|
||||
const sessionMiddleware = session({
|
||||
secret: "changeit",
|
||||
resave: true,
|
||||
saveUninitialized: true,
|
||||
});
|
||||
|
||||
app.use(sessionMiddleware);
|
||||
app.use(bodyParser.urlencoded({ extended: false }));
|
||||
app.use(passport.initialize());
|
||||
app.use(passport.session());
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
if (!req.user) {
|
||||
return res.redirect("/login");
|
||||
}
|
||||
res.sendFile(join(__dirname, "index.html"));
|
||||
});
|
||||
|
||||
app.get("/login", (req, res) => {
|
||||
if (req.user) {
|
||||
return res.redirect("/");
|
||||
}
|
||||
res.sendFile(join(__dirname, "login.html"));
|
||||
});
|
||||
|
||||
app.post(
|
||||
"/login",
|
||||
passport.authenticate("local", {
|
||||
successRedirect: "/",
|
||||
failureRedirect: "/",
|
||||
}),
|
||||
);
|
||||
|
||||
app.post("/logout", (req, res) => {
|
||||
const sessionId = req.session.id;
|
||||
req.session.destroy(() => {
|
||||
// disconnect all Socket.IO connections linked to this session ID
|
||||
io.to(`session:${sessionId}`).disconnectSockets();
|
||||
res.status(204).end();
|
||||
});
|
||||
});
|
||||
|
||||
passport.use(
|
||||
new LocalStrategy((username, password, done) => {
|
||||
if (username === "john" && password === "changeit") {
|
||||
console.log("authentication OK");
|
||||
return done(null, { id: 1, username });
|
||||
} else {
|
||||
console.log("wrong credentials");
|
||||
return done(null, false);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
passport.serializeUser((user, cb) => {
|
||||
console.log(`serializeUser ${user.id}`);
|
||||
cb(null, user);
|
||||
});
|
||||
|
||||
passport.deserializeUser((user, cb) => {
|
||||
console.log(`deserializeUser ${user.id}`);
|
||||
cb(null, user);
|
||||
});
|
||||
|
||||
const io = new Server(httpServer);
|
||||
|
||||
io.engine.use(sessionMiddleware);
|
||||
io.engine.use(passport.initialize());
|
||||
io.engine.use(passport.session());
|
||||
|
||||
io.engine.use(
|
||||
(req, res, next) => {
|
||||
if (req.user) {
|
||||
next();
|
||||
} else {
|
||||
res.writeHead(401);
|
||||
res.end();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
io.on("connection", (socket) => {
|
||||
const req = socket.request;
|
||||
|
||||
socket.join(`session:${req.session.id}`);
|
||||
socket.join(`user:${req.user.id}`);
|
||||
|
||||
socket.on("whoami", (cb) => {
|
||||
cb(req.user.username);
|
||||
});
|
||||
});
|
||||
|
||||
httpServer.listen(port, () => {
|
||||
console.log(`application is running at: http://localhost:${port}`);
|
||||
});
|
||||
@@ -8,17 +8,17 @@
|
||||
<p>Not authenticated</p>
|
||||
<form action="/login" method="post">
|
||||
<div>
|
||||
<label>Username:</label>
|
||||
<input type="text" name="username" />
|
||||
<label for="username">Username:</label>
|
||||
<input type="text" id="username" name="username" />
|
||||
<br/>
|
||||
</div>
|
||||
<div>
|
||||
<label>Password:</label>
|
||||
<input type="password" name="password" />
|
||||
<label for="password">Password:</label>
|
||||
<input type="password" id="password" name="password" />
|
||||
</div>
|
||||
<div>
|
||||
<input type="submit" value="Submit" />
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
20
examples/passport-example/cjs/package.json
Normal file
20
examples/passport-example/cjs/package.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "passport-example",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"type": "commonjs",
|
||||
"description": "Example with passport (https://www.passportjs.org)",
|
||||
"scripts": {
|
||||
"start": "node index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"express": "~4.17.3",
|
||||
"express-session": "~1.17.2",
|
||||
"passport": "^0.7.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"socket.io": "^4.7.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "^3.1.1"
|
||||
}
|
||||
}
|
||||
55
examples/passport-example/esm/index.html
Normal file
55
examples/passport-example/esm/index.html
Normal file
@@ -0,0 +1,55 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Passport example</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Authenticated!</p>
|
||||
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Status</td>
|
||||
<td><span id="status">Disconnected</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Socket ID</td>
|
||||
<td><span id="socket-id"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Username</td>
|
||||
<td><span id="username"></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<form action="/logout" method="post">
|
||||
<div>
|
||||
<input type="submit" value="Log out" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script src="/socket.io/socket.io.js"></script>
|
||||
<script>
|
||||
const socket = io();
|
||||
const socketIdSpan = document.getElementById('socket-id');
|
||||
const usernameSpan = document.getElementById('username');
|
||||
const statusSpan = document.getElementById('status');
|
||||
|
||||
socket.on('connect', () => {
|
||||
statusSpan.innerText = 'connected';
|
||||
socketIdSpan.innerText = socket.id;
|
||||
|
||||
socket.emit('whoami', (username) => {
|
||||
usernameSpan.innerText = username;
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('disconnect', () => {
|
||||
statusSpan.innerText = 'disconnected';
|
||||
socketIdSpan.innerText = '-';
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
112
examples/passport-example/esm/index.js
Normal file
112
examples/passport-example/esm/index.js
Normal file
@@ -0,0 +1,112 @@
|
||||
import express from "express";
|
||||
import { createServer } from "http";
|
||||
import { Server } from "socket.io";
|
||||
import session from "express-session";
|
||||
import bodyParser from "body-parser";
|
||||
import passport from "passport";
|
||||
import { Strategy as LocalStrategy } from "passport-local";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const port = process.env.PORT || 3000;
|
||||
|
||||
const app = express();
|
||||
const httpServer = createServer(app);
|
||||
|
||||
const sessionMiddleware = session({
|
||||
secret: "changeit",
|
||||
resave: true,
|
||||
saveUninitialized: true,
|
||||
});
|
||||
|
||||
app.use(sessionMiddleware);
|
||||
app.use(bodyParser.urlencoded({ extended: false }));
|
||||
app.use(passport.initialize());
|
||||
app.use(passport.session());
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
if (!req.user) {
|
||||
return res.redirect("/login");
|
||||
}
|
||||
res.sendFile(join(__dirname, "index.html"));
|
||||
});
|
||||
|
||||
app.get("/login", (req, res) => {
|
||||
if (req.user) {
|
||||
return res.redirect("/");
|
||||
}
|
||||
res.sendFile(join(__dirname, "login.html"));
|
||||
});
|
||||
|
||||
app.post(
|
||||
"/login",
|
||||
passport.authenticate("local", {
|
||||
successRedirect: "/",
|
||||
failureRedirect: "/",
|
||||
}),
|
||||
);
|
||||
|
||||
app.post("/logout", (req, res) => {
|
||||
const sessionId = req.session.id;
|
||||
req.session.destroy(() => {
|
||||
// disconnect all Socket.IO connections linked to this session ID
|
||||
io.to(`session:${sessionId}`).disconnectSockets();
|
||||
res.status(204).end();
|
||||
});
|
||||
});
|
||||
|
||||
passport.use(
|
||||
new LocalStrategy((username, password, done) => {
|
||||
if (username === "john" && password === "changeit") {
|
||||
console.log("authentication OK");
|
||||
return done(null, { id: 1, username });
|
||||
} else {
|
||||
console.log("wrong credentials");
|
||||
return done(null, false);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
passport.serializeUser((user, cb) => {
|
||||
console.log(`serializeUser ${user.id}`);
|
||||
cb(null, user);
|
||||
});
|
||||
|
||||
passport.deserializeUser((user, cb) => {
|
||||
console.log(`deserializeUser ${user.id}`);
|
||||
cb(null, user);
|
||||
});
|
||||
|
||||
const io = new Server(httpServer);
|
||||
|
||||
io.engine.use(sessionMiddleware);
|
||||
io.engine.use(passport.initialize());
|
||||
io.engine.use(passport.session());
|
||||
|
||||
io.engine.use(
|
||||
(req, res, next) => {
|
||||
if (req.user) {
|
||||
next();
|
||||
} else {
|
||||
res.writeHead(401);
|
||||
res.end();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
io.on("connection", (socket) => {
|
||||
const req = socket.request;
|
||||
|
||||
socket.join(`session:${req.session.id}`);
|
||||
socket.join(`user:${req.user.id}`);
|
||||
|
||||
socket.on("whoami", (cb) => {
|
||||
cb(req.user.username);
|
||||
});
|
||||
});
|
||||
|
||||
httpServer.listen(port, () => {
|
||||
console.log(`application is running at: http://localhost:${port}`);
|
||||
});
|
||||
24
examples/passport-example/esm/login.html
Normal file
24
examples/passport-example/esm/login.html
Normal file
@@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Passport example</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Not authenticated</p>
|
||||
<form action="/login" method="post">
|
||||
<div>
|
||||
<label for="username">Username:</label>
|
||||
<input type="text" id="username" name="username" />
|
||||
<br/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="password">Password:</label>
|
||||
<input type="password" id="password" name="password" />
|
||||
</div>
|
||||
<div>
|
||||
<input type="submit" value="Submit" />
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
20
examples/passport-example/esm/package.json
Normal file
20
examples/passport-example/esm/package.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "passport-example",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"description": "Example with passport (https://www.passportjs.org)",
|
||||
"scripts": {
|
||||
"start": "node index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"express": "~4.17.3",
|
||||
"express-session": "~1.17.2",
|
||||
"passport": "^0.7.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"socket.io": "^4.7.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "^3.1.1"
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Passport example</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Authenticated!</p>
|
||||
<p>Socket ID: <span id="socketId"></span></p>
|
||||
<p>Username: <span id="username"></span></p>
|
||||
<form action="/logout" method="post">
|
||||
<div>
|
||||
<input type="submit" value="Log out" />
|
||||
</div>
|
||||
</form>
|
||||
<script src="/socket.io/socket.io.js"></script>
|
||||
<script>
|
||||
const socket = io();
|
||||
const socketIdSpan = document.getElementById("socketId");
|
||||
const usernameSpan = document.getElementById("username");
|
||||
|
||||
socket.on('connect', () => {
|
||||
socketIdSpan.innerText = socket.id;
|
||||
|
||||
socket.emit('whoami', (username) => {
|
||||
usernameSpan.innerText = username;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,104 +0,0 @@
|
||||
const app = require("express")();
|
||||
const server = require("http").createServer(app);
|
||||
const port = process.env.PORT || 3000;
|
||||
|
||||
const session = require("express-session");
|
||||
const bodyParser = require("body-parser");
|
||||
const passport = require("passport");
|
||||
const LocalStrategy = require("passport-local").Strategy;
|
||||
|
||||
const sessionMiddleware = session({ secret: "changeit", resave: false, saveUninitialized: false });
|
||||
app.use(sessionMiddleware);
|
||||
app.use(bodyParser.urlencoded({ extended: false }));
|
||||
app.use(passport.initialize());
|
||||
app.use(passport.session());
|
||||
|
||||
const DUMMY_USER = {
|
||||
id: 1,
|
||||
username: "john",
|
||||
};
|
||||
|
||||
passport.use(
|
||||
new LocalStrategy((username, password, done) => {
|
||||
if (username === "john" && password === "doe") {
|
||||
console.log("authentication OK");
|
||||
return done(null, DUMMY_USER);
|
||||
} else {
|
||||
console.log("wrong credentials");
|
||||
return done(null, false);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
const isAuthenticated = !!req.user;
|
||||
if (isAuthenticated) {
|
||||
console.log(`user is authenticated, session is ${req.session.id}`);
|
||||
} else {
|
||||
console.log("unknown user");
|
||||
}
|
||||
res.sendFile(isAuthenticated ? "index.html" : "login.html", { root: __dirname });
|
||||
});
|
||||
|
||||
app.post(
|
||||
"/login",
|
||||
passport.authenticate("local", {
|
||||
successRedirect: "/",
|
||||
failureRedirect: "/",
|
||||
})
|
||||
);
|
||||
|
||||
app.post("/logout", (req, res) => {
|
||||
console.log(`logout ${req.session.id}`);
|
||||
const socketId = req.session.socketId;
|
||||
if (socketId && io.of("/").sockets.get(socketId)) {
|
||||
console.log(`forcefully closing socket ${socketId}`);
|
||||
io.of("/").sockets.get(socketId).disconnect(true);
|
||||
}
|
||||
req.logout();
|
||||
res.cookie("connect.sid", "", { expires: new Date() });
|
||||
res.redirect("/");
|
||||
});
|
||||
|
||||
passport.serializeUser((user, cb) => {
|
||||
console.log(`serializeUser ${user.id}`);
|
||||
cb(null, user.id);
|
||||
});
|
||||
|
||||
passport.deserializeUser((id, cb) => {
|
||||
console.log(`deserializeUser ${id}`);
|
||||
cb(null, DUMMY_USER);
|
||||
});
|
||||
|
||||
const io = require('socket.io')(server);
|
||||
|
||||
// convert a connect middleware to a Socket.IO middleware
|
||||
const wrap = middleware => (socket, next) => middleware(socket.request, {}, next);
|
||||
|
||||
io.use(wrap(sessionMiddleware));
|
||||
io.use(wrap(passport.initialize()));
|
||||
io.use(wrap(passport.session()));
|
||||
|
||||
io.use((socket, next) => {
|
||||
if (socket.request.user) {
|
||||
next();
|
||||
} else {
|
||||
next(new Error('unauthorized'))
|
||||
}
|
||||
});
|
||||
|
||||
io.on('connect', (socket) => {
|
||||
console.log(`new connection ${socket.id}`);
|
||||
socket.on('whoami', (cb) => {
|
||||
cb(socket.request.user ? socket.request.user.username : '');
|
||||
});
|
||||
|
||||
const session = socket.request.session;
|
||||
console.log(`saving sid ${socket.id} in session ${session.id}`);
|
||||
session.socketId = socket.id;
|
||||
session.save();
|
||||
});
|
||||
|
||||
server.listen(port, () => {
|
||||
console.log(`application is running at: http://localhost:${port}`);
|
||||
});
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"name": "passport-example",
|
||||
"version": "0.0.1",
|
||||
"description": "Example with Passport (http://www.passportjs.org/)",
|
||||
"dependencies": {
|
||||
"body-parser": "~1.19.0",
|
||||
"express": "~4.17.1",
|
||||
"express-session": "~1.17.1",
|
||||
"passport": "~0.4.1",
|
||||
"passport-local": "~1.0.0",
|
||||
"socket.io": "^4.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node index.js"
|
||||
}
|
||||
}
|
||||
55
examples/passport-example/ts/index.html
Normal file
55
examples/passport-example/ts/index.html
Normal file
@@ -0,0 +1,55 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Passport example</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Authenticated!</p>
|
||||
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Status</td>
|
||||
<td><span id="status">Disconnected</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Socket ID</td>
|
||||
<td><span id="socket-id"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Username</td>
|
||||
<td><span id="username"></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<form action="/logout" method="post">
|
||||
<div>
|
||||
<input type="submit" value="Log out" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script src="/socket.io/socket.io.js"></script>
|
||||
<script>
|
||||
const socket = io();
|
||||
const socketIdSpan = document.getElementById('socket-id');
|
||||
const usernameSpan = document.getElementById('username');
|
||||
const statusSpan = document.getElementById('status');
|
||||
|
||||
socket.on('connect', () => {
|
||||
statusSpan.innerText = 'connected';
|
||||
socketIdSpan.innerText = socket.id;
|
||||
|
||||
socket.emit('whoami', (username) => {
|
||||
usernameSpan.innerText = username;
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('disconnect', () => {
|
||||
statusSpan.innerText = 'disconnected';
|
||||
socketIdSpan.innerText = '-';
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
122
examples/passport-example/ts/index.ts
Normal file
122
examples/passport-example/ts/index.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
import express = require("express");
|
||||
import { createServer, ServerResponse } from "http";
|
||||
import { Server } from "socket.io";
|
||||
import session from "express-session";
|
||||
import { type Request } from "express";
|
||||
import bodyParser = require("body-parser");
|
||||
import passport = require("passport");
|
||||
import { Strategy as LocalStrategy } from "passport-local";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
declare global {
|
||||
namespace Express {
|
||||
interface User {
|
||||
id: number;
|
||||
username: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const port = process.env.PORT || 3000;
|
||||
|
||||
const app = express();
|
||||
const httpServer = createServer(app);
|
||||
|
||||
const sessionMiddleware = session({
|
||||
secret: "changeit",
|
||||
resave: true,
|
||||
saveUninitialized: true,
|
||||
});
|
||||
|
||||
app.use(sessionMiddleware);
|
||||
app.use(bodyParser.urlencoded({ extended: false }));
|
||||
app.use(passport.initialize());
|
||||
app.use(passport.session());
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
if (!req.user) {
|
||||
return res.redirect("/login");
|
||||
}
|
||||
res.sendFile(join(__dirname, "index.html"));
|
||||
});
|
||||
|
||||
app.get("/login", (req, res) => {
|
||||
if (req.user) {
|
||||
return res.redirect("/");
|
||||
}
|
||||
res.sendFile(join(__dirname, "login.html"));
|
||||
});
|
||||
|
||||
app.post(
|
||||
"/login",
|
||||
passport.authenticate("local", {
|
||||
successRedirect: "/",
|
||||
failureRedirect: "/",
|
||||
}),
|
||||
);
|
||||
|
||||
app.post("/logout", (req, res) => {
|
||||
const sessionId = req.session.id;
|
||||
req.session.destroy(() => {
|
||||
// disconnect all Socket.IO connections linked to this session ID
|
||||
io.to(`session:${sessionId}`).disconnectSockets();
|
||||
res.status(204).end();
|
||||
});
|
||||
});
|
||||
|
||||
passport.use(
|
||||
new LocalStrategy((username, password, done) => {
|
||||
if (username === "john" && password === "changeit") {
|
||||
console.log("authentication OK");
|
||||
return done(null, { id: 1, username });
|
||||
} else {
|
||||
console.log("wrong credentials");
|
||||
return done(null, false);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
passport.serializeUser((user, cb) => {
|
||||
console.log(`serializeUser ${user.id}`);
|
||||
cb(null, user);
|
||||
});
|
||||
|
||||
passport.deserializeUser((user: Express.User, cb) => {
|
||||
console.log(`deserializeUser ${user.id}`);
|
||||
cb(null, user);
|
||||
});
|
||||
|
||||
const io = new Server(httpServer);
|
||||
|
||||
io.engine.use(sessionMiddleware);
|
||||
io.engine.use(passport.initialize());
|
||||
io.engine.use(passport.session());
|
||||
|
||||
io.engine.use(
|
||||
(req: { user: Express.User }, res: ServerResponse, next: Function) => {
|
||||
if (req.user) {
|
||||
next();
|
||||
} else {
|
||||
res.writeHead(401);
|
||||
res.end();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
io.on("connection", (socket) => {
|
||||
const req = socket.request as Request & { user: Express.User };
|
||||
|
||||
socket.join(`session:${req.session.id}`);
|
||||
socket.join(`user:${req.user.id}`);
|
||||
|
||||
socket.on("whoami", (cb) => {
|
||||
cb(req.user.username);
|
||||
});
|
||||
});
|
||||
|
||||
httpServer.listen(port, () => {
|
||||
console.log(`application is running at: http://localhost:${port}`);
|
||||
});
|
||||
24
examples/passport-example/ts/login.html
Normal file
24
examples/passport-example/ts/login.html
Normal file
@@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Passport example</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Not authenticated</p>
|
||||
<form action="/login" method="post">
|
||||
<div>
|
||||
<label for="username">Username:</label>
|
||||
<input type="text" id="username" name="username" />
|
||||
<br/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="password">Password:</label>
|
||||
<input type="password" id="password" name="password" />
|
||||
</div>
|
||||
<div>
|
||||
<input type="submit" value="Submit" />
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
27
examples/passport-example/ts/package.json
Normal file
27
examples/passport-example/ts/package.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "passport-example",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"description": "Example with passport (https://www.passportjs.org)",
|
||||
"scripts": {
|
||||
"start": "ts-node index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/express-session": "^1.17.7",
|
||||
"@types/node": "^20.6.0",
|
||||
"@types/passport": "^1.0.16",
|
||||
"express": "~4.17.3",
|
||||
"express-session": "~1.17.2",
|
||||
"passport": "^0.7.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"socket.io": "^4.7.2",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/passport-local": "^1.0.38",
|
||||
"prettier": "^3.1.1"
|
||||
}
|
||||
}
|
||||
11
examples/passport-example/ts/tsconfig.json
Normal file
11
examples/passport-example/ts/tsconfig.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"target": "ES2022",
|
||||
"strict": true
|
||||
},
|
||||
"ts-node": {
|
||||
"esm": true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user