使用OAuth 2.0、OIDC和PKCE保护Express应用
每个Web应用都需要身份验证,但自行构建存在风险且耗时。本教程将指导您集成Okta管理用户身份,并在Express中结合Passport和openid-client库来简化和保护登录流程。
为什么使用Okta进行身份验证
构建身份验证系统并处理凭据、会话和令牌非常不安全,会使应用面临严重漏洞。Okta提供基于OpenID Connect(OIDC)和OAuth 2.0的安全、可扩展且符合标准的解决方案。
为什么在OAuth 2.0中使用PKCE
PKCE(Proof Key for Code Exchange)是授权码流程的安全扩展,最初为移动应用设计,现推荐用于所有OAuth客户端。它有助于防止CSRF和授权码注入攻击。
构建使用Express、OAuth 2.0和PKCE的安全Web应用
让我们构建一个费用仪表板,用户通过Okta登录,并根据其角色查看支出数据。
先决条件
- Node.js(推荐v22+)
- Okta Integrator免费计划组织
创建Express项目并安装依赖
创建项目文件夹并初始化Node.js项目:
npm init -y
npm install express@5.1 passport@0.7 openid-client@6.6 express-session@1.18 ejs@3.1 express-ejs-layouts@2.5 dotenv
npm install --save-dev nodemon
配置OIDC认证的环境变量
创建.env文件:
OKTA_CLIENT_ID={yourClientId}
OKTA_CLIENT_SECRET={clientSecret}
APP_BASE_URL=http://localhost:3000
POST_LOGOUT_URL=http://localhost:3000
创建Okta OIDC Web应用
在Okta管理控制台中:
- 转到Applications > Applications
- 点击Create App Integration
- 选择OIDC - OpenID Connect作为登录方法
- 选择Web Application作为应用类型
构建Express应用
创建index.js文件作为应用主入口点:
import express from 'express';
import session from 'express-session';
import passport from 'passport';
import routes from './routes.js';
import expressLayouts from 'express-ejs-layouts';const app = express();app.set('view engine', 'ejs');
app.use(expressLayouts);
app.set('layout', 'layout');
app.use(express.urlencoded({ extended: false }));app.use(session({secret: "your-hardcoded-secret",resave: false,saveUninitialized: true,
}));app.use(passport.initialize());
app.use(passport.session());passport.serializeUser(function (user, done) {done(null, user);
});passport.deserializeUser(function (obj, done) {done(null, obj);
});app.use('/', routes);app.listen(3000, () => {console.log('Server listening on http://localhost:3000');
});
定义团队映射和示例费用数据
创建utils.js文件:
export const ALL_TEAMS_NAME = ["finance", "hr", "legal", "marketing", "dev advocacy"];export const userTeamMap = {"hannah.smith@task-vantage.com": "admin","grace.li@task-vantage.com": "legal","frank.wilson+@task-vantage.com": "dev advocacy","carol.lee@task-vantage.com": "finance","alice.johnson@task-vantage.com": "marketing","sarah.morgan@task-vantage.com": "hr",
};export const dummyExpenseData = {// 各团队的费用数据
};export function getModifiedTeam(team) {// 辅助函数处理团队信息
}
创建认证处理文件
创建auth.js文件处理OIDC流程:
import * as client from "openid-client";
import "dotenv/config";import { getModifiedTeam, userTeamMap } from './utils.js';async function getClientConfig() {}export async function login(req, res) {// 处理登录逻辑
}export async function authCallback(req, res, next) {// 处理认证回调
}export async function logout(req, res) {// 处理登出逻辑
}export function ensureAuthenticated(req, res, next) {// 中间件确保用户已认证
}
在Express中设置路由
创建routes.js文件:
import express from "express";
import "dotenv/config";import { authCallback, ensureAuthenticated, login, logout } from "./auth.js";
import { dummyExpenseData } from './utils.js';const router = express.Router();// 定义各种路由
router.get("/", (req, res) => {res.render("home", { title: "Home", user: req.user });
});router.get("/login", login);router.get("/authorization-code/callback", authCallback);// 其他路由定义...
在Express中添加EJS视图
创建视图文件,包括:
home.ejs- 主页profile.ejs- 用户资料页dashboard.ejs- 仪表板expenses.ejs- 费用详情页layout.ejs- 布局模板
运行带认证的Express应用
在终端中启动服务器:
npm start
访问http://localhost:3000,点击登录并使用Okta账户认证。
了解更多关于OAuth 2.0、OIDC和PKCE
- OpenID Connect(OIDC)是构建在OAuth 2.0之上的身份和认证层
- 带PKCE的授权码流程是服务器端和基于浏览器的Web应用最安全的流程
查看GitHub上的完整源代码,或探索Okta官方资源以了解更多关键概念。
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)
公众号二维码

公众号二维码
