身份验证

以 Markdown 格式查看
企业功能

此功能仅适用于企业计划。如需开始使用,请联系 support@buildwithfern.com

自托管 Fern 文档支持通过在 Dockerfile 中设置环境变量来进行身份验证。当没有配置身份验证环境变量时,您的文档完全公开。

有两种身份验证模式可用:

  • 密码身份验证 - 简单的共享密码保护
  • 基本令牌验证 - 基于 JWT 的身份验证,具有自定义登录流程

密码身份验证

密码身份验证通过简单的密码提示来保护您的文档。用户必须输入正确的密码才能查看文档。

将以下环境变量添加到您的 Dockerfile 中:

1FROM fernenterprise/fern-self-hosted:latest
2
3COPY fern/ /fern/
4
5ENV FERN_AUTH_TYPE="password"
6ENV FERN_AUTH_SECRET="<YOUR PASSWORD>"
7
8RUN fern-generate

<YOUR PASSWORD> 替换为用户访问文档时需要输入的密码。

当用户访问文档时,他们会被重定向到登录页面,必须在那里输入密码。输入正确密码后,他们可以自由浏览文档。

基本令牌验证

基本令牌验证使用 JWT(JSON Web Tokens)来验证用户身份。当您希望将文档与现有身份验证系统(如您自己的登录门户)集成时,这很有用。

工作原理

  1. 未经身份验证的用户访问文档并被重定向到您的登录页面(FERN_AUTH_REDIRECT)。
  2. 您的登录页面对用户进行身份验证(例如,根据您的数据库检查凭据)。
  3. 身份验证成功后,您的服务器使用共享密钥创建签名的 JWT。
  4. 您的服务器将用户发送到 Fern 回调端点(/api/fern-docs/auth/jwt/callback)并携带 JWT。这可以通过GET重定向与令牌作为查询参数,或通过POST请求与令牌在 application/x-www-form-urlencoded 主体中来完成。
  5. Fern 文档容器验证 JWT 签名和颁发者,设置会话 cookie,并将用户重定向到文档。

配置

将以下环境变量添加到您的 Dockerfile 中:

1FROM fernenterprise/fern-self-hosted:latest
2
3COPY fern/ /fern/
4
5ENV FERN_AUTH_TYPE="basic_token_verification"
6ENV FERN_AUTH_SECRET="my-test-secret-at-least-32-chars-long"
7ENV FERN_AUTH_ISSUER="https://my-test-issuer"
8ENV FERN_AUTH_REDIRECT="https://your-login-page.com/login"
9
10RUN fern-generate
变量描述
FERN_AUTH_TYPE必须是 basic_token_verification
FERN_AUTH_SECRET用于签名和验证 JWT 的共享密钥。必须至少 32 个字符长。
FERN_AUTH_ISSUERJWT 中的颁发者声明(iss)。您的签名服务器和 Fern 容器之间必须匹配。
FERN_AUTH_REDIRECT未经身份验证的用户被重定向到的登录 URL。

构建您的登录服务器

您的登录服务器负责验证用户身份并使用签名的 JWT 将他们重定向回文档。

当 Fern 容器重定向未经身份验证的用户时,它会将以下查询参数附加到 FERN_AUTH_REDIRECT

  • redirect_uri - Fern 文档容器上的回调 URL(例如,https://docs.example.com/api/fern-docs/auth/jwt/callback
  • state - 用户试图访问的页面

您的服务器必须:

  1. 验证用户身份。
  2. 创建使用相同 FERN_AUTH_SECRET 和 HS256 算法签名的 JWT。
  3. 将用户发送到 redirect_uri,携带 JWT 作为 fern_token 和原始 state 作为返回路径。您可以使用任一方法:
    • GET 重定向:将 fern_tokenstate 作为查询参数附加。
    • POST 表单提交:将 fern_tokenstate 作为 application/x-www-form-urlencoded 字段提交。POST 避免在 URL 和服务器日志中暴露令牌。

JWT 负载必须包括以下声明:

声明描述
fern空对象 {}(Fern 验证器要求)
iss颁发者,必须匹配 FERN_AUTH_ISSUER
iat颁发时间戳(自纪元以来的秒数)
exp过期时间戳(自纪元以来的秒数)

这是一个签名 JWT 并重定向到回调的 Node.js(Express)服务器示例:

1const express = require("express");
2const crypto = require("crypto");
3
4const app = express();
5
6const SECRET = "my-test-secret-at-least-32-chars-long";
7const ISSUER = "https://my-test-issuer";
8
9function base64url(input) {
10 const buf = Buffer.isBuffer(input) ? input : Buffer.from(input, "utf8");
11 return buf.toString("base64").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
12}
13
14function createFernJWT(secret, issuer) {
15 const header = { alg: "HS256", typ: "JWT" };
16 const now = Math.floor(Date.now() / 1000);
17 const payload = {
18 fern: {},
19 iat: now,
20 exp: now + 30 * 24 * 60 * 60, // 30 days
21 iss: issuer,
22 };
23
24 const headerB64 = base64url(JSON.stringify(header));
25 const payloadB64 = base64url(JSON.stringify(payload));
26 const signature = crypto
27 .createHmac("sha256", secret)
28 .update(`${headerB64}.${payloadB64}`)
29 .digest();
30
31 return `${headerB64}.${payloadB64}.${base64url(signature)}`;
32}
33
34app.get("/login", (req, res) => {
35 const redirectUri = req.query.redirect_uri;
36 const state = req.query.state || "/";
37
38 // TODO: Add your own authentication logic here
39 // (e.g., check session, verify credentials, show a login form, etc.)
40
41 const token = createFernJWT(SECRET, ISSUER);
42
43 const callbackUrl = new URL(redirectUri);
44 callbackUrl.searchParams.set("fern_token", token);
45 callbackUrl.searchParams.set("state", state);
46
47 res.redirect(callbackUrl.toString());
48});
49
50app.listen(3001, () => {
51 console.log("Login server running on http://localhost:3001");
52});

您的登录服务器中的 FERN_AUTH_SECRET 必须与 Dockerfile 中设置的密钥完全匹配。如果它们不同,JWT 验证将失败,用户将无法登录。

使用内置测试登录页面进行测试

自托管容器包括一个内置的测试登录页面,您可以在开发和测试中启用它。这让您可以在不构建自己的登录服务器的情况下验证身份验证流程。

将以下环境变量添加到您的 Dockerfile 中:

1FROM fernenterprise/fern-self-hosted:latest
2
3COPY fern/ /fern/
4
5ENV FERN_AUTH_TYPE="basic_token_verification"
6ENV FERN_AUTH_SECRET="my-test-secret-at-least-32-chars-long"
7ENV FERN_AUTH_ISSUER="https://my-test-issuer"
8ENV FERN_AUTH_REDIRECT="http://localhost:3000/__test-login"
9ENV FERN_AUTH_TEST_LOGIN="true"
10
11RUN fern-generate

设置 FERN_AUTH_TEST_LOGIN="true" 启用容器上的 /__test-login 端点。当 FERN_AUTH_REDIRECT 指向此端点时,未经身份验证的用户会看到一个测试登录页面,只有一个”使用测试登录”按钮。点击按钮会创建有效的 JWT 并完成身份验证流程。

测试登录页面仅用于开发和测试。不要在生产环境中启用 FERN_AUTH_TEST_LOGIN

页面级别访问控制

默认情况下,启用身份验证时所有页面都需要身份验证。使用 FERN_AUTH_ALLOWLISTFERN_AUTH_DENYLIST 来控制哪些页面需要登录。两者都接受逗号分隔的正则表达式模式,与页面路径匹配。

变量描述
FERN_AUTH_ALLOWLIST匹配这些模式的页面可以公开访问,无需登录。
FERN_AUTH_DENYLIST匹配这些模式的页面需要登录。优先于允许列表。

例如,要使所有页面都可以公开访问:

1ENV FERN_AUTH_ALLOWLIST="/(.*)"

要使只有 API Reference 页面需要登录:

1ENV FERN_AUTH_DENYLIST="/api-reference/(.*)"

API 密钥注入

您可以为自托管部署在 API Explorer 中启用 API 密钥注入。这在 API Explorer 中显示一个登录按钮,以便用户可以进行身份验证并自动填充其 API 密钥,而无需为整个文档站点要求登录。

FERN_API_KEY_INJECTION_ENABLED 与基本令牌验证变量一起添加到您的 Dockerfile 中:

1FROM fernenterprise/fern-self-hosted:latest
2
3COPY fern/ /fern/
4
5ENV FERN_AUTH_TYPE="basic_token_verification"
6ENV FERN_AUTH_SECRET="my-test-secret-at-least-32-chars-long"
7ENV FERN_AUTH_ISSUER="https://my-test-issuer"
8ENV FERN_AUTH_REDIRECT="https://your-login-page.com/login"
9ENV FERN_API_KEY_INJECTION_ENABLED="true"
10ENV FERN_AUTH_ALLOWLIST="/(.*)"
11
12RUN fern-generate

使用 FERN_AUTH_ALLOWLIST="/(.*)" 时,所有文档页面都可以公开访问(无登录墙),但 API Explorer 仍显示登录按钮。当用户登录时,会读取其 JWT 的 fern 负载,并将 API 密钥注入到 API Explorer 中。有关完整的 fern 负载参考,请参阅自动填充 API 密钥