构建电子邮件营销引擎第3部分:通过Auth0确保前端
#教程 #node #express #productmarketing

Building an Email Marketing Engine Part 3: Securing Your Frontend with Auth0

在本系列的先前文章中,我们介绍了我们的电子邮件营销引擎的初始设置,以及如何通过SendGrid API发送电子邮件至SQLITE数据库中的联系人。现在,让我们深入研究任何Web应用程序的重要组成部分 - 安全性。在本文中,我们将了解如何使用Auth0进行前端。

Auth0和Express-Openid-Connect

auth0是一种灵活的,可以进行的解决方案,可在您的应用程序中添加身份验证和授权服务。您的团队和组织可以避免建立自己的解决方案来验证和授权用户所带来的成本,时间和风险。

我们使用了express-openid-connect库,这是一个已开发的auth0中间件,它使您在express.js应用中设置身份验证非常容易。

让我们深入研究我们的代码:

const { auth } = require('express-openid-connect');

require('dotenv').config();

const config = {
  authRequired: true,
  auth0Logout: true,
  secret: 'a long, randomly-generated string stored in env',
  baseURL: 'https://your_application_domain.com',
  clientID: 'your_client_id',
  issuerBaseURL: 'https://your_domain.region.auth0.com'
};

app.use(auth(config));

在此片段中,我们需要authdotenvauth函数来加载环境变量。然后,我们定义一个配置对象config,我们传递给auth函数。

这是每个配置选项的作用:

  • authRequired:这是一个布尔值,如果是的,则需要对所有路线进行身份验证。
  • auth0Logout:当真实时,此启用Auth0的注销功能。
  • secret:这是一个长时间的随机生成的字符串,用于加密和签名会话cookie。重要的是要确保安全并且不将其检查到版本控件中。它应该存储在环境变量中。
  • baseURL:这是您应用程序的URL。中间件使用这来确定回调URL和logout后重定向URL。
  • clientID:这是您的auth0应用程序的客户ID。
  • issuerBaseURL:这是您的auth0租户的URL。

请注意,这些配置值,尤其是secretclientIDissuerBaseURL,因为它们是敏感的信息,因此不应被硬编码。它们应牢固地存储在环境变量中,并使用dotenv或类似的软件包加载到应用程序中。

require('dotenv').config();

dotenv软件包将环境变量从.env文件加载到process.env中。这意味着,当我们运行require('dotenv').config()时,我们可以访问.env文件中的值,就好像它们在系统的环境变量中一样。这是以安全,易于管理的方式处理配置的常见做法。

您可以在Auth0仪表板中调整登录页面的外观和设置。默认页面看起来像这样:

Building an Email Marketing Engine Part 3: Securing Your Frontend with Auth0

安装和初始化auth()

这是一个非常基本的设置。一旦我们安装并初始化auth(),后来初始化的所有路由将受到auth0s登录。

我们将此代码段插入我们的index.js中,我们在系列的前面部分设置了该代码:

const express = require('express');
const app = express();
const port = 3000;

const multer = require('multer');
const upload = multer({ dest: 'uploads/' });

const { sendEmails } = require('./server/api');
const { processContacts } = require('./server/utils');
const { uploadToDb } = require('./server/uploadToDb');
const { auth } = require('express-openid-connect');

require('dotenv').config();

const config = {
  authRequired: true,
  auth0Logout: true,
  secret: process.env.SECRET,
  baseURL: process.env.BASE_URL,
  clientID: process.env.CLIENT_ID,
  issuerBaseURL: process.env.ISSUER_BASE_URL
};

app.use(auth(config));

app.use(express.json());
app.use(express.static('public'));

app.all("*", (req, res, next) => {
  console.log(`Received a ${req.method} request on ${req.originalUrl}`);
  next();
});

app.post("/contacts", async (req, res) => {
  console.log(req.body);

  const { templateId } = req.body;

  try {
    const emailGroups = await processContacts(99);

    // Send emails to each group
    for (let group of emailGroups) {
        await sendEmails(group, templateId);
    }

    res.json(emailGroups);
  } catch (error) {
    res.status(500).json({ error: "An error occurred while fetching contacts" });
  }
});

app.post('/upload', upload.single('contacts-upload'), (req, res) => {

  uploadToDb(req.file.path);

  res.send('File uploaded successfully');

});

app.listen(port, () => {
  console.log(`Server is running at http://localhost:${port}`);
});

仅允许特定的电子邮件域

构建内部工具时,您可能只想将登录仅限于公司电子邮件。

不幸的是,Auth0不支持Google或GitHub(例如Google或GitHub)的OAuth2登录,但是,当使用常规电子邮件/密码登录时,您可以将登录限制为特定域或电子邮件。这是通过使用Auth0s操作流来完成的,该操作流可以使您可以在登录流的特定位置插入自定义Node.js代码。

要限制特定的用户电子邮件,您将使用“预注册”流量,当用户试图在完整注册之前注册时,该流程被称为。

Building an Email Marketing Engine Part 3: Securing Your Frontend with Auth0
auth0动作流菜单

然后,您可以使用auth0s整洁的拖放编辑器来插入预定义的操作或创建自定义操作。

Building an Email Marketing Engine Part 3: Securing Your Frontend with Auth0
auth0的拖放动作编辑器

要将电子邮件域限制为特定的白名单,您可以创建一个小的JS片段,然后在Auth0服务器上运行。

Building an Email Marketing Engine Part 3: Securing Your Frontend with Auth0

在我们的情况下,我们创建了以下自定义片段,该摘要仅允许用户使用“ codesphere.com”电子邮件注册:

exports.onExecutePreUserRegistration = async (event, api) => {
  console.log(event); // log the event object

  const whitelist = ['codesphere.com'];

  const emailSplit = event.user.email.split("@");
  const userDomain = emailSplit[emailSplit.length - 1].toLowerCase();

  // If userDomain is not part of the whitelist, deny access
  if (!whitelist.includes(userDomain)) {
    const LOG_MESSAGE = "User not part of Codesphere"
    const USER_MESSAGE = "Access to this tool is only available for employees of Codesphere"
    api.access.deny(LOG_MESSAGE, USER_MESSAGE);
  }
};

为了使其更加安全,建议仅允许特定的电子邮件并调整白名单以在需要时接受新用户。

结论

确保您的应用程序是一项关键任务,值得庆幸的是,对于Auth0和express-openid-connect之类的库,它变得更加简单。通过将Auth0集成到我们的电子邮件营销引擎中,我们仅使用几行代码添加了强大的安全层,并确保只有特定的域才能登录。