跳转至

使用用户导入 API 导入用户

向 Authany 项目添加用户的方式有几种:使用 Authany 管理台里的 Add User 界面、使用 Admin API 里的 createUser() mutation,以及通过 AuthUI 的注册页面创建用户账号。

上述方法有一个共同的缺点:都不支持批量导入用户,也就是说您必须逐个添加用户。如果要把现有旧系统里的大量用户导入到 Authany,这种方式并不理想。要批量添加用户,可以使用用户导入 API。

接下来您将了解用户导入 API 是什么,并通过示例学习如何向 Authany 项目批量导入用户。

User Import API

用户导入 API 用于将用户从其他系统批量导入到 Authany 项目,它不属于 Admin API GraphQL 的一部分。不过,访问用户导入 API 的端点仍需要有效的 Admin API JWT 令牌。

Endpoints

以下是用户导入 API 的端点。

Initiate Import

使用此端点启动新的用户导入任务。

POST - /_api/admin/users/import
HTTP/1.1
Host: <Your Authgear Project domain>
Authorization: Bearer <Admin API JWT Token>
Content-type: application/json
Body: {
    "identifier": "email",
    "records": [
        {
            "email": "user@example.com",
            "email_verified": true,
            "password": {
                "type": "bcrypt",
                "password_hash": "$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy"
            }
        }
    ]
}

Check Status

使用此端点查询现有用户导入任务的状态。

GET - /_api/admin/users/import/{ID}
HTTP/1.1
Host: <Your Authgear Project domain>
Authorization: Bearer <Admin API JWT Token>

说明

要了解用户导入 API 的更多详情(如端点、输入和响应),请参阅用户导入 API 参考。

Usage Example

本节提供一个简单示例,演示如何使用用户导入 API 向 Authany 项目添加多个用户。

Prerequisites

要跟随本示例操作并在本地运行代码,您需要准备好以下内容:

  • 一个 Authany 账号。可以在这里免费注册。
  • 本地计算机上安装好 Node.js。
  • 在项目目录中运行以下命令安装 Express.js:npm install express。

Step 1: Get Admin API JWT

如前所述,访问用户导入 API 需要 Admin API JWT。这一步我们将使用 Node.js 生成 Admin API JWT。

首先,运行以下命令安装 JsonWebToken(一个用于生成 JWT 的 Node 包):

npm install jsonwebtoken

以下代码展示了如何获取该令牌:

function generateJWT() {
    const project_id = ""; //Your authgear app id
    const key_id = ""; //you authgear key ID
    const expiresAt = Math.floor(Date.now() / 1000) + (60 * 60); //the current value means token will expire in 1 hour.

    //Payload to include in JWT
    const claims = {
        aud: project_id,
        iat: Math.floor(Date.now() / 1000) - 30,
        exp: expiresAt
    }
    const privateKey = fs.readFileSync("key.pem"); //Read value from the downloaded key file
    const header = { "typ": "JWT", "kid": key_id, "alg": "RS256" }
    const jwt = node_jwt.sign(claims, privateKey, { header: header });

    return jwt;
}

关于如何获取密钥 ID 和私钥并生成 Admin API JWT 的详细说明(以及其他编程语言/框架的示例),请参阅Admin API 身份验证。

Step 2: Import Users from a JSON Document

要使用用户导入 API 向 Authany 项目导入用户,需要向 Initiate Import 端点(/_api/admin/users/import)发起 POST HTTP(S) 请求。

要导入的用户数据必须按照 API 输入格式 中的说明,以 JSON 格式放在 HTTP(S) 请求体中。

接下来的步骤中,我们将使用 node-fetch 包向用户导入 API 发起 HTTP 请求。请运行以下命令安装 node-fetch:

npm install node-fetch

以下示例代码演示了如何从存储在常量(const data)里的 JSON 文档导入 2 个用户:

const express = require("express");
const node_jwt = require('jsonwebtoken');
const fs = require('fs');
const fetch = require('node-fetch');
const app = express();
const port = 3002;

//TODO Place declaration of generateJWT() function here

app.get('/', (request, response) => {

    const jwt = generateJWT();
    const data = {
        "identifier": "email",
        "records": [
            {
                "email": "user1@example.com",
                "email_verified": true,
                "password": {
                    "type": "bcrypt",
                    "password_hash": "$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy"
                }
            },
            {
                "email": "user2@example.com",
                "email_verified": false,
                "name": "John Doe",
                "given_name": "John",
                "family_name": "Doe",
                "password": {
                    "type": "bcrypt",
                    "password_hash": "$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy"
                }
            }
        ]
    }

    const options = {
        method: 'POST',
        headers: { 'Content-type': 'application/json', 'Authorization': 'Bearer ' + jwt },
        body: JSON.stringify(data)
    };

    const appUrl = 'https://your-project.authanyid.com'; // replace wuth your authgear project url

    fetch(`${appUrl}/_api/admin/users/import`, options)
        .then(result => result.json())
        .then(result => console.log(JSON.stringify(result)));

    response.send("Request sent using the follow JWT as Bearer: " + jwt + "See console for result");
});

app.listen(port, () => {
    console.log("server started! PORT: " + port);
});

如果用户导入任务成功启动,您将收到类似下面的响应:

{
  "id": "task_4WZ0V7EPT4GZ2ABVN03QXYZ122W835C1",
  "created_at": "2024-04-04T06:56:36.02508096Z",
  "status": "pending"
}

下一步,我们将使用上述响应中 id 字段的值来查询导入任务的状态。

Step 3: Get the Status of the Import Task

这一步我们将向 Check Status 端点(/_api/admin/users/import/{ID})发起 GET HTTP(S) 请求,以获取上一步启动的用户导入任务的状态。您需要把 URL 中的 {ID} 替换成前一个响应里 id 的值。

为此,需要在 Express 应用中添加一个新路由,接收任务 id 作为参数,并用它查询任务状态。该路由的代码如下:

app.get("/status/:id", (request, response) => {
    const jwt = generateJWT()

    const options = {
        method: 'GET',
        headers: { 'Content-type': 'application/json', 'Authorization': 'Bearer ' + jwt }
    };

    const appUrl = 'https://your-project.authanyid.com';

    fetch(`${appUrl}/_api/admin/users/import/${request.params.id}`, options)
        .then(result => result.json())
        .then(result => console.log(JSON.stringify(result)));

    response.send("Request sent using the follow JWT as Bearer: " + jwt + "See console for result");
});

查询导入任务状态的响应类似下面这样:

{
  "id": "task_4WZ0V7EPT4GZ2ABVN03QXYZ122W835C1",
  "created_at": "2024-04-04T06:56:36.02508096Z",
  "status": "completed",
  "summary": {
    "total": 2,
    "inserted": 2,
    "updated": 0,
    "skipped": 0,
    "failed": 0
  },
  "details": [
    {
      "index": 0,
      "record": {
        "email": "user1@example.com",
        "email_verified": true,
        "password": {
          "password_hash": "REDACTED",
          "type": "bcrypt"
        }
      },
      "outcome": "inserted",
      "user_id": "0f0f65ee-4c7d-45a0-a740-bcbbfd3fcf06"
    },
    {
      "index": 1,
      "record": {
        "email": "user2@example.com",
        "email_verified": false,
        "family_name": "Doe",
        "given_name": "John",
        "name": "John Doe",
        "password": {
          "password_hash": "REDACTED",
          "type": "bcrypt"
        }
      },
      "outcome": "inserted",
      "user_id": "9c71fc29-6db6-4a18-aa73-774139fed16d",
      "warnings": [
        {
          "message": "email_verified = false has no effect in insert."
        }
      ]
    }
  ]
}

从响应中可以看到整个任务的 status(导入已 completed),以及一份汇总信息( { "total": 2, "inserted": 2, "updated": 0, "skipped": 0, "failed": 0 } )。

details 字段包含一个详情数组,例如原始 JSON 文档中每个用户的 outcome。