在 Node.js 应用程序中使用 OAuth 进行用户身份验证
OAuth 是一种流行的身份验证协议,用于授权第三方应用程序访问用户的数据。在许多 Web 应用程序中,用户可能希望使用他们的 Google、Facebook、Twitter 或其他社交媒体账户进行身份验证。这就是 OAuth 的作用。本文将详细解释在 Node.js 应用程序中使用 OAuth 进行用户身份验证的步骤和注意事项,并提供示例代码。
OAuth 的工作原理
OAuth 系统采用三个主要角色:用户、服务提供者和客户端应用程序。用户允许服务提供者向客户端应用程序授予一些特定的权限。例如,他们可以授权客户端应用程序访问他们的 Google 日历。客户端应用程序使用 OAuth 在用户的允许下,获取用于访问该服务提供者的令牌。该令牌用于代表该用户在客户端应用程序中执行操作。
使用 OAuth 进行身份验证的步骤
认证使用 OAuth 的客户端应用程序通常需要四个步骤:
- 创建应用程序
要使用 OAuth,您需要在目标服务提供者上注册您的应用程序。这需要您提供一些应用程序详细信息,例如名称、描述、图像和重定向 URI。重定向 URI 是客户端应用程序在验证用户之后将被重定向到的位置。
- 请求访问权限
客户端应用程序需要向目标服务提供者请求 OAuth 访问权限。这种方式包括向服务提供者发送一个带有它的客户端 ID 和重定向 URI 的请求。
- 转发重定向 URI
服务提供者将验证此请求,并将用户重定向回客户端应用程序使用的 URI,其中包括服务提供者的授权代码。此代码是客户端应用程序可用于获取授权令牌的一次性代码。
- 获取授权令牌
客户端应用程序可以使用服务提供者的授权代码向服务提供者请求一个访问令牌。令牌是一些信息和元数据,可用于代表用户调用所请求的服务。客户端应用程序使用令牌与提供令牌的服务提供者建立安全连接。
在 Node.js 中使用 OAuth 进行用户身份验证
以下是使用 Node.js 对 OAuth 进行用户身份验证的基本步骤:
- 安装必须的包
在任何 Node.js 应用程序中使用 OAuth 进行身份验证,您需要安装必要的 npm 包。最常见的包是 Passport 和 Passport-Oauth。Passport 是一个构建在 Node.js 之上的身份验证库,支持本地和第三方身份验证策略。Passport-Oauth 是一个开发库,您可以使用它构建与各种 OAuth 服务提供者集成的身份验证策略。
npm install passport passport-oauth
- 配置 Passport
Passport 需要一个认证策略才能与服务提供者进行身份验证。您需要告诉 Passport 如何使用服务提供者的 API 进行身份验证,并将用户身份验证凭据与本地 Passport 用户配置文件进行交互。
// javascriptcn.com 代码示例 const passport = require('passport'); const OAuth2Strategy = require('passport-oauth').OAuth2Strategy; const config = require('./config'); const users = require('./users'); passport.use('provider', new OAuth2Strategy({ authorizationURL: config.provider.authorizationURL, tokenURL: config.provider.tokenURL, clientID: config.provider.clientID, clientSecret: config.provider.clientSecret, callbackURL: config.provider.callbackURL, responseType: 'code', scope: config.provider.scope }, function(accessToken, refreshToken, profile, done) { users.findOrCreate({id: profile.id}, function (err, user) { return done(err, user); }); } ));
此代码中,您使用串联策略包装 OAuth2Strategy。这将告诉 Passport 使用 OAuth 2.0 服务提供者的预定义认证策略。在这里,您可以指定授权 URL,令牌 URL,客户端 ID 和客户端密钥,以及授权后的重定向 URI。
最后,您必须还需要确定向服务提供者请求授权之前所需的范围,以及登录后将用户信息存储在哪里。
- 配置路由
您应该配置一些路由,以允许用户访问身份验证过程并与身份验证服务交互。
app.get('/auth/provider', passport.authenticate('provider')); app.get('/auth/provider/callback', passport.authenticate('provider', {failureRedirect: '/login'}), function(req, res) { res.redirect('/'); });
在这个示例中,您精简了一个路由文件(routes.js),其中 /auth/provider 将重定向用户到服务提供者的身份验证页面。在该页面启动后,它将重定向用户回到您的应用程序,并交由经过身份验证的回调函数接管。如果用户通过 OAuth 验证,则该代码将重定向该用户到您的应用程序的主页。
完整的示例代码:
// javascriptcn.com 代码示例 const express = require('express'); const passport = require('passport'); const OAuth2Strategy = require('passport-oauth').OAuth2Strategy; const app = express(); app.use(passport.initialize()); app.use(passport.session()); passport.serializeUser(function(user, done) { done(null, user); }); passport.deserializeUser(function(user, done) { done(null, user); }); const users = [ { id: 1, name: 'Sven' }, { id: 2, name: 'Assad' } ]; passport.use('provider', new OAuth2Strategy({ authorizationURL: 'http://localhost:3000/oauth/authorize', tokenURL: 'http://localhost:3000/oauth/token', clientID: 'xxxx', clientSecret: 'xxxx', callbackURL: 'http://localhost:3000/auth/provider/callback', responseType: 'code', scope: 'email' }, function(accessToken, refreshToken, profile, done) { console.log(`accessToken was fetched: ${accessToken}`); console.log(`refreshToken was fetched: ${refreshToken}`); console.log(`profile was fetched: ${JSON.stringify(profile)}`); let user = users.filter(entity => entity.id === profile.id)[0]; return done(null, user); } )); app.get('/', function (req, res) { res.send(` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <a href="/auth/provider">Authorize with Provider</a> </div> <div> <a href="/api">Access Protected Resource</a> </div> </body> </html> `); }); app.get('/auth/provider', passport.authenticate('provider')); app.get('/auth/provider/callback', passport.authenticate('provider', {failureRedirect: '/login'}), function(req, res) { console.log('Successfully Authenticated'); res.redirect('/'); }); app.get('/api', ensureAuthenticated, (req, res) => { res.send('Protected Resource'); }); function ensureAuthenticated(req, res, next) { if (req.isAuthenticated()) { next(); } else { res.redirect('/login'); } } app.get('/login', (req, res) => { res.send(` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <a href="/auth/provider">Authorize with Provider</a> </div> </body> </html> `); }); app.listen(3000, () => { console.log('app is running at port 3000!'); });
该示例 app.js 文件中的基本路由文件 routes.js 原始代码已经将上述所有功能整合在一起。
- 该应用程序的主页包括有访问 provider OAuth 服务提供者的链接。
- 在 provider 身份验证之后,它将重定向到 /auth/provider/callback,身份验证成功后,它将重定向一个包含 “successfully authenticated”的网页。
- /api 是一个受保护的资源,只有通过 OAuth 认证连接应用程序的用户才能访问。 这些用户通过 ensureAuthenticated 路由中间件进行身份验证时,如果未经过身份验证,则应该重定向到 /login。
- / login 是另一个包含有访问 /auth/provider 的链接的主页,只要用户通过 OAuth 连接到提供者,它就可以为访问受保护的资源提供身份验证。
总结:
以上就是在 Node.js 应用程序中使用 OAuth 进行用户身份验证的详尽步骤和注意事项。通过本文,您将获得有关在 Node.js 应用程序中使用 OAuth 进行身份验证的深入学习,并且使用完整的示例代码更容易地练习此技术。现在,只要按照上述步骤操作,就可以为您的应用程序添加安全认证,以保护用户数据。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/654dbe0f7d4982a6eb7256bd