使用OAuth 2.0、OIDC和PKCE保护Express应用
每个Web应用都需要身份验证,但自己构建既风险又耗时。你可以集成Okta来管理用户身份,并在Express中将Passport与openid-client库配对,以简化和保护登录流程。在本教程中,你将构建一个安全的、基于角色的费用仪表板,用户可以根据其团队查看相应的费用。
在GitHub上查看完整源代码,无需从零开始设置。
目录
- 为什么使用Okta进行身份验证
- 为什么在OAuth 2.0中使用PKCE
- 使用Express、OAuth 2.0和PKCE构建安全Web应用
- 运行带身份验证的Express应用
- 了解更多关于OAuth 2.0、OIDC和PKCE的信息
为什么使用Okta进行身份验证
构建身份验证系统并处理凭据、会话和令牌非常不安全,会使应用面临严重漏洞。Okta使用OpenID Connect(OIDC)和OAuth 2.0提供安全、可扩展且基于标准的解决方案。它还可以与你喜欢的技术栈的OIDC客户端库无缝集成,并允许你获取令牌。
为什么在OAuth 2.0中使用PKCE
为了进一步加强安全性,本项目使用PKCE(Proof Key for Code Exchange),在RFC 7636中定义。PKCE是授权码流程的安全扩展。开发人员最初为移动应用设计了PKCE,但专家现在建议所有OAuth客户端使用,包括Web应用。它有助于防止CSRF和授权码注入攻击,使其对每种类型的OAuth客户端都有用,即使是使用客户端密钥的Web应用等机密客户端。随着OAuth 2.0的稳步发展,安全最佳实践也在进步。RFC 9700:OAuth 2.0安全最佳实践捕捉了关于最有效和安全实施策略的共识。此外,即将发布的OAuth 2.1草案要求所有授权码流程使用PKCE,将其强化为基线安全标准。
使用Okta,你可以实现现代身份验证功能,并专注于应用逻辑,而无需担心身份验证基础设施。
使用Express、OAuth 2.0和PKCE构建安全Web应用
让我们构建一个费用仪表板,用户使用Okta登录并根据其角色查看支出数据。无论他们在财务、市场还是人力资源部门工作,每个团队只能查看自己的费用。为了在这个演示项目中保持简洁,我们将在应用中直接定义角色和用户。
你将通过openid-client库使用OpenID Connect(OIDC)进行身份验证。然后,你将ID令牌中的每个用户的电子邮件映射到一个团队。仪表板应用最小权限原则,并按团队显示费用,因此每个用户只能看到其部门的支出。
先决条件
- 安装Node.js(推荐v22+)
- Okta Integrator免费计划组织
创建Express项目并安装依赖
创建一个名为express-project-okta的新项目文件夹,并在项目文件夹中打开终端窗口。
初始化新的Node.js项目:
|
|
安装所需的包:
|
|
现在安装开发依赖:
|
|
在package.json文件中,使用以下内容更新scripts属性:
|
|
这些依赖的作用是什么?
这些安装的包成为Express项目的依赖。
- express:处理Web应用的路由和HTTP中间件
- passport:设置和维护服务器端会话
- openid-client:支持PKCE的Node.js OIDC库;处理OAuth握手和令牌交换
- express-session:在服务器上管理用户会话
- dotenv:从.env文件加载环境变量
- ejs:使用嵌入式JavaScript模板启用动态HTML渲染
- express-ejs-layouts:为EJS添加布局支持,帮助管理视图中的通用布局结构
为OIDC身份验证配置环境变量
在根目录中创建一个.env文件,其中包含Okta配置的占位符。
|
|
在下一步中,你将从Okta管理控制台获取这些值。
创建Okta OIDC Web应用
在开始之前,你需要一个Okta Integrator免费计划账户。要获取一个,请注册一个Integrator账户。拥有账户后,登录到你的Integrator账户。接下来,在管理控制台中:
- 转到Applications > Applications
- 单击Create App Integration
- 选择OIDC - OpenID Connect作为登录方法
- 选择Web Application作为应用类型,然后单击Next
输入应用集成名称
配置重定向URI:
- 登录重定向URI:http://localhost:3000/authorization-code/callback
- 登出重定向URI:http://localhost:3000
在Controlled access部分,选择适当的访问级别 单击Save
在哪里找到新应用的凭据?
在管理控制台中手动创建OIDC Web应用会使用应用设置配置你的Okta组织。
创建应用后,你可以在应用的General选项卡上找到配置详细信息:
- Client ID:在Client Credentials部分找到
- Client Secret:在Client Credentials部分单击Show以显示
你将需要这些值用于应用配置:
|
|
你的Okta域是颁发者的第一部分,在/oauth2/default之前。
注意:你也可以使用Okta CLI客户端或Okta PowerShell模块自动化此过程。有关设置应用的更多信息,请参阅本指南。
构建Express应用
在项目根目录中创建一个index.js文件。它作为应用的主要入口点。使用它来初始化Express应用,设置路由,并配置Passport以通过在每个请求上序列化和反序列化用户来管理用户会话。
|
|
定义团队映射和示例费用
创建一个utils.js文件作为项目的数据模块。此文件包括用户到团队的映射,并为每个团队包含虚拟费用数据,涵盖为Web应用测试配置的所有团队。
应用从ID令牌中的电子邮件声明确定用户的团队上下文,并相应地过滤费用列表,因此仪表板仅显示该团队的数据。
要自定义数据,请打开utils.js并更新以下对象:
- ALL_TEAMS_NAME - 列出组织中所有团队的数组
- userTeamMap - 将每个用户的电子邮件(或"admin"用于完全访问)映射到特定团队
- dummyExpenseData - 包含每个团队的示例费用数据
|
|
该文件还定义了getModifiedTeam,一个帮助程序,将团队名称转换为对象数组。每个对象都有一个id和label。如果团队是admin,该函数为ALL_TEAMS_NAME中的每个条目返回一个对象;否则,它为指定团队返回单个对象。在项目的后面,应用调用此函数来转换用户的团队信息。
创建处理身份验证的文件
为此步骤创建一个auth.js文件。此文件使用openid-client库处理OIDC流程:它登录用户,将授权代码交换为令牌,并登出用户。它还定义了一个中间件来保护受保护的路由。
在auth.js文件中,添加以下代码:
|
|
此文件包括以下函数:
- getClientConfig - 使用发现端点检索授权服务器的元数据。
- login - 此函数启动授权码+PKCE流程。它生成启用PKCE所需的值:code_verifier和code_challenge。这些值与state值一起保护用户登录过程免受攻击向量。PKCE防止授权码拦截攻击,state参数防止跨站请求伪造(CSRF)。openid-client使用这些值构建用户登录URL,并将用户重定向到Okta以完成身份验证质询。
- getCallbackUrlWithParams - 重建完整的回调URL,包括协议、主机、路径和查询。
- authCallback - 当用户在身份验证质询成功后重定向回应用时,此函数运行。此时,重定向回应用的URL包括授权码。OIDC客户端通过检查state值与第一次重定向中的参数匹配来验证授权码。一旦验证,openid-client库通过将code_verifier添加到令牌请求来使用授权码进行令牌交换。授权服务器验证授权码和code_verifier值,以确保请求来自进行原始身份验证请求的客户端,减轻使用被盗授权码的攻击。 一旦我们获得有效令牌,我们处理应用的业务逻辑,例如将用户映射到团队,并将配置文件详细信息和ID令牌存储在会话中。如果一切成功,它将用户重定向到仪表板。
- logout - 将用户登出应用并重定向到登出后URL。
- ensureAuthenticated - 允许已认证用户继续并重定向其他用户到登录页面的中间件。
在Express中设置路由
现在事情开始整合起来,感觉像一个真正的应用。routes.js文件定义了所有基本路由,从登录和登出到查看你的配置文件、费用仪表板和单个团队费用页面。应用处理每个端点的核心逻辑,并在授予对受保护页面的访问权限之前检查用户的身份验证状态。
它充当我们应用的流量控制器,将用户引导到正确的页面,并确保只有登录的用户才能查看敏感信息,如费用仪表板或组详细信息。这种结构使我们的应用组织有序且安全,并为流畅的用户体验奠定了基础。
|
|
在Express中添加EJS视图
现在是时候给应用一个用户界面了。你将使用EJS模板构建页面,这些页面动态响应谁登录以及他们看到什么数据。应用使用ejs模板渲染页面,加上express-ejs-layouts用于通用布局结构。
创建一个名为views的文件夹,然后添加以下EJS文件:
home.ejs
|
|
profile.ejs
|
|
layout.ejs
|
|
dashboard.ejs
|
|
expenses.ejs EJS模板以表格格式渲染团队信息和费用数据。
|
|
运行带身份验证的Express应用
在终端中,启动服务器:
|
|
打开浏览器并导航到http://localhost:3000。 单击Login并使用你的Okta账户进行身份验证。然后应用将显示你的费用仪表板、配置文件和登出选项。
注意:当你作为管理员登录到开发控制台时,Okta保持你的组织会话活动,并自动将你登录到应用。要测试其他用户账户,请使用隐身标签测试登录流程。
管理员视图:
用户视图:
费用视图:
就是这样!你已经构建了一个安全的费用仪表板,并使用OIDC和OAuth将你的Express应用连接到Okta。
了解更多关于OAuth 2.0、OIDC和PKCE的信息
以下是我在此项目中用于构建安全费用仪表板的功能的快速概述:
- OpenID Connect(OIDC)是建立在OAuth 2.0之上的身份和身份验证层。
- 带PKCE的授权码流程是服务器端和基于浏览器的Web应用最安全的流程。
如果你想探索整个项目并跳过从零开始设置,请在GitHub上查看完整源代码。
要进一步探索,请查看这些官方Okta资源以了解关键概念。
- 身份验证与授权
- OAuth 2.0和OpenID Connect概述
- 使用PKCE实现授权码
- Okta中的授权服务器
在LinkedIn、Twitter上关注我们,并订阅我们的YouTube频道以查看更多类似内容。如果你有任何问题,请在下面评论!