OAuth 2.0 是一种广泛使用的协议,用于授权用户使用第三方应用程序。它为应用程序提供了一个标准化的方式,以请求和获取用户的授权,而无需暴露用户的登录凭据。在前端开发中,了解如何构建一个 OAuth 2.0 授权服务器,对于开发具有安全性和用户友好性的应用非常重要。本文将使用 Fastify 和 OAuth 2.0 构建授权服务器,让您轻松掌握 OAuth 2.0 授权的流程。
OAuth 2.0 简介
OAuth 2.0 是一个开放标准,用于授权第三方应用程序访问用户资源的协议。OAuth 2.0 授权流程通常包括以下步骤:
- 用户选择授权第三方应用程序访问其资源。
- 第三方应用程序将用户重定向到授权服务器,以请求访问令牌。
- 用户在授权服务器上进行身份验证,并选择批准或拒绝请求。
- 如果用户选择授权,授权服务器将颁发访问令牌给第三方应用程序。
- 第三方应用程序使用访问令牌访问用户的资源。
在本文中,我们将使用 Fastify 框架快速构建一个 OAuth 2.0 授权服务器,并使用相应的插件来实现 OAuth 2.0 的授权流程。
快速开始
通过以下步骤快速开始使用 Fastify 构建 OAuth 2.0 授权服务器:
安装 Fastify 和相应的插件
首先,我们需要安装 Fastify 和其它相应的插件。在命令行中输入以下命令:
npm install fastify fastify-oauth2 fastify-formbody
配置授权服务器
接下来,我们需要设置授权服务器。我们将在 index.js
中创建一个服务器以供使用。我们将使用 fastify-oauth2
和 fastify-formbody
插件。这些插件将处理身份验证和授权流程。
const fastify = require('fastify')(); // 导入 fastify-oauth2 和 fastify-formbody 插件 fastify.register(require('fastify-oauth2'), { scopes: { // 定义可用的授权范围 profile: 'Access your profile information.', email: 'Access your email address.' }, saveToken: (req, token) => { req.session.accessToken = token // 将访问令牌保存在 session 上 } }); fastify.register(require('fastify-formbody')); // 定义主页路由 fastify.get('/', async (req, reply) => { return 'OAuth 2.0 Authorization Server'; }); // 启动服务器 fastify.listen(3000, (err) => { if (err) console.error(err) console.log('Server listening at http://localhost:3000'); });
我们需要定义一些授权服务器的设置:
- 我们定义了两个授权范围:
profile
和email
。 - 在
saveToken
回调函数中,我们将访问令牌保存在用户的 session 中。这是一种简单的方式,以便在后续的请求中使用该令牌。
现在,我们的授权服务器已经启动,并且提供了一个 "OAuth 2.0 Authorization Server" 的文本响应。
登录
现在,我们需要为用户提供一个登录页面。我们将使用一个简单的 HTML 页面。我们将对用户进行身份验证,并将 Oauth2 请求发送到授权服务器。
<!DOCTYPE html> <html> <head> <title>Login</title> </head> <body> <h1>Login</h1> <form method="post" action="/login"> <div> <label for="username">Username:</label> <input type="text" id="username" name="username"> </div> <div> <label for="password">Password:</label> <input type="password" id="password" name="password"> </div> <div> <input type="submit" value="Login"> </div> </form> </body> </html>
接下来,我们需要在授权服务器中设置 "login" 路由。该路由将验证用户的凭据,如果有效,则将其重定向到授权服务器以进行授权。
fastify.post('/login', async (req, reply) => { // 验证用户凭据 const { username, password } = req.body; if (username === 'admin' && password === 'password') { // 如果用户通过身份验证,则将其重定向到授权服务器 reply.redirect('/oauth/authorize?response_type=code&client_id=clientId&redirect_uri=http://localhost:3000/callback'); } else { // 如果用户未通过身份验证,则返回“Unauthorized”响应 reply.status(401).send('Unauthorized'); } });
我们验证用户凭据,并将用户重定向到授权服务器以请求访问令牌。
授权和访问令牌
现在,用户已经被重定向到授权服务器,并请求访问令牌。授权服务器将提示用户批准或拒绝该请求。如果用户批准,则授权服务器将返回一个授权码。然后,客户端将使用该授权码换取访问令牌。
我们需要在授权服务器中设置 "callback" 路由。该路由将处理从授权服务器返回的授权码,并向客户端返回访问令牌。
fastify.get('/callback', async (req, reply) => { // 从授权服务器获取访问令牌 const token = await fastify.oauth2.getAccessTokenFromAuthorizationCodeFlow(req); // 确认访问令牌是否存在 if (token) { // 发送访问令牌作为 response reply.send(token); } else { // 如果未找到访问令牌,则返回 "Unauthorized" 响应 reply.status(401).send('Unauthorized'); } });
我们使用 fastify.oauth2.getAccessTokenFromAuthorizationCodeFlow
方法从授权服务器获取访问令牌。然后,我们检查访问令牌是否存在。如果存在,则返回访问令牌。否则,我们将返回 "Unauthorized" 响应。
示例代码
完整的示例代码如下:
const fastify = require('fastify')(); // 导入 fastify-oauth2 和 fastify-formbody 插件 fastify.register(require('fastify-oauth2'), { scopes: { // 定义可用的授权范围 profile: 'Access your profile information.', email: 'Access your email address.' }, saveToken: (req, token) => { req.session.accessToken = token // 将访问令牌保存在 session 上 } }); fastify.register(require('fastify-formbody')); // 定义主页路由 fastify.get('/', async (req, reply) => { return 'OAuth 2.0 Authorization Server'; }); // 定义登录页面 fastify.get('/login', async (req, reply) => { return ` <!DOCTYPE html> <html> <head> <title>Login</title> </head> <body> <h1>Login</h1> <form method="post" action="/login"> <div> <label for="username">Username:</label> <input type="text" id="username" name="username"> </div> <div> <label for="password">Password:</label> <input type="password" id="password" name="password"> </div> <div> <input type="submit" value="Login"> </div> </form> </body> </html> `; }); // 处理登录请求 fastify.post('/login', async (req, reply) => { // 验证用户凭据 const { username, password } = req.body; if (username === 'admin' && password === 'password') { // 如果用户通过身份验证,则将其重定向到授权服务器 reply.redirect('/oauth/authorize?response_type=code&client_id=clientId&redirect_uri=http://localhost:3000/callback'); } else { // 如果用户未通过身份验证,则返回“Unauthorized”响应 reply.status(401).send('Unauthorized'); } }); // 授权请求 fastify.get('/oauth/authorize', async (req, reply) => { // 请求授权 return fastify.oauth2.authorize(req, reply); }); // 授权访问令牌 fastify.get('/callback', async (req, reply) => { // 从授权服务器获取访问令牌 const token = await fastify.oauth2.getAccessTokenFromAuthorizationCodeFlow(req); // 确认访问令牌是否存在 if (token) { // 发送访问令牌作为 response reply.send(token); } else { // 如果未找到访问令牌,则返回 "Unauthorized" 响应 reply.status(401).send('Unauthorized'); } }); // 启动服务器 fastify.listen(3000, (err) => { if (err) console.error(err) console.log('Server listening at http://localhost:3000'); });
总结
本文展示了如何使用 Fastify 和 OAuth 2.0 构建授权服务器。通过具有详细而深入的说明和示例代码,我们希望您能够深入理解 OAuth 2.0 授权并自如地使用它。OAuth 2.0 被广泛用于前端开发中,这使得前端开发人员可以更好地控制安全性和用户体验,同时提高了应用程序的流动性和可用性。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65b36b0dadd4f0e0ffc7c26e