跳转至

滚动迁移

通过滚动迁移,您可以将用户数据从旧系统逐步迁移到 Authany。例如,您可以迁移带有特定功能标记的用户,比如来自特定地区的用户。也可以将应用配置为让所有新注册用户都使用 Authany。

在本指南中,您将学习如何使用滚动迁移的方式,把用户从旧的身份验证系统迁移到 Authany。

在本指南中,我们将以一个 Express.js 演示应用的源代码为例。该演示应用正在将新用户注册从旧的身份验证系统迁移到 Authany。

何时使用滚动迁移

以下是一些适合使用滚动迁移的场景:

  • 当您希望同时使用 Authany 和您的旧身份验证系统时。
  • 当您只想将部分用户迁移到 Authany 时。例如,新用户、来自特定地区或位置的用户,或者需要用到 Authany 特定功能的用户。
  • 当您希望逐步迁移用户,以减少停机时间以及应用中其他与迁移相关的问题时。

优点

  • 滚动部署可以实现平缓过渡,用户所受的影响或停机时间都是可控的。

缺点

  • 这种方式使您可能需要无限期地继续支持旧的身份验证系统。

第 1 步:部署同时支持 Authany 会话和旧身份验证系统的中间件

搭建滚动迁移的第一步,是实现一个同时支持 Authany 会话和您旧的身份验证提供方的中间件及服务端逻辑。

为此,请实现代码来同时验证来自旧身份验证系统和 Authany 的访问令牌(会话):

const axios = require("axios");
const node_jwt = require("jsonwebtoken");
const jwksClient = require("jwks-rsa");

const appUrl = "<YOUR_AUTHGEAR_ENDPOINT>";
const getJwksUri = async (appUrl) => {
  const config_endpoint = appUrl + "/.well-known/openid-configuration";
  const data = await axios.get(config_endpoint);
  return data.data.jwks_uri;
};

// Verify access token from Authgear session.
const authenticateAuthgearToken = async (req, res, next) => {
  const requestHeader = req.headers;
  if (requestHeader.authorization == undefined) {
    return res.sendStatus(401);
  }
  const authorizationHeader = requestHeader.authorization.split(" ");
  const access_token = authorizationHeader[1];

  const decoded_access_token = node_jwt.decode(access_token, {
    complete: true,
  });
  const jwks_uri = await getJwksUri(appUrl);
  const client = jwksClient({
    strictSsl: true,
    jwksUri: jwks_uri,
  });
  const signing_key = await client.getSigningKey(
    decoded_access_token.header.kid
  );

  try {
    const verify = node_jwt.verify(access_token, signing_key.publicKey, {
      algorithms: ["RS256"],
    });
    console.log(JSON.stringify(verify));
  } catch (error) {
    return res.sendStatus(403);
  }

  next();
};

// Verify session from old authentication provider.
const authenticateOldProviderToken = (req, res, next) => {
    // ... logic for authenticating session from your old provider
    console.log("using old provider session");
    next();
}

第 2 步:为部分用户启用 Authany

现在您的应用已经设置为同时支持 Authany 和旧的身份验证系统,接下来需要决定让多大比例的用户使用 Authany。

在这个演示应用中,我们将为 2025 年 3 月 2 日(2025/03/02)之后注册的所有用户启用 Authany。您也可以使用其他功能标记,例如用户所在的地区或国家。

为了能在用户登录之前判断其注册时间(或所在地区、国家),您可能需要搭建一个外部数据库,记录用户的登录 ID(用户名、邮箱地址、手机号码等)以及功能标记(注册日期、国家等)。在我们的示例中,我们用一个简单的 JavaScript 对象来创建一个演示用户,该用户于 2025 年 3 月 20 日注册。

const user = { loginID: 'user1@example.com', signup_date: '2025/03/20' };

在中间件中启用 Authany 会话

在这个演示应用中,我们用一个简单的条件语句,为满足功能标记条件(在 2025/03/02 之后注册)的用户启用 Authany 会话。

let authenticateToken = authenticateOldProviderToken;
const featureFlagDate = new Date('2025/03/02');

const signupDate = new Date(user.signup_date);
if ( signupDate > featureFlagDate) {
    authenticateToken = authenticateAuthgearToken;
}

然后,authenticateToken 就可以用作中间件,来保护只允许已登录用户查看的页面。

app.get("/protected", authenticateToken, (req, res) => {
  res.json({ message: "This is a protected route"});
});

第 3 步:将您的应用配置为可以用 Authany 和旧的提供方注册/登录

更新您的应用,让用户可以使用 Authany 的身份验证流程进行注册和登录。同时,也要继续支持您旧的身份验证提供方,以便旧用户仍然可以登录。

不过,您应该禁用旧系统上的注册功能,让所有新用户数据都进入 Authany。

现在,我们再次使用功能标记,来判断向用户展示哪种身份验证流程:

app.get("/login", (req, res) => {
    if ( signupDate > featureFlagDate) {
        // TODO start Authgear Authentication flow
    } else {
        // ... logic for authenticating users with your old provider
    }

    res.send("Login")
});

我们为以下平台提供 SDK,方便您将 Authany 无缝集成到应用中:

您也可以将 Authany 作为 OAuth 2.0 提供方手动接入任意应用。

结语

在实施滚动迁移时,以下几点也值得注意:

  • 对于已经在旧系统中注册、并通过用户导入 API迁移到 Authany 的用户,需要先将其登出,之后他们必须通过 Authany 的身份验证流程重新登录,才能开始使用 Authany 会话。请记得为这些用户添加功能标记,以便您的应用能够为他们选用 Authany。
  • 未被打上功能标记的用户会继续使用旧的身份验证系统。他们不会被登出,可以继续使用现有会话。
  • 禁用旧系统中的新用户注册功能,让所有新注册都通过 Authany 完成。
  • 对于通过 Authany 新注册流程注册的新用户,旧系统中也应保留一条对应记录,以处理用户使用较旧版本应用在其他设备上尝试登录的边缘情况。