metabase-embedding-sso-implementation
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseExecution contract
执行约定
Follow the workflow steps in order — do not skip any step. Create the checklist first, then execute each step and explicitly mark it done with evidence. Each step's output feeds into the next, so skipping steps produces incorrect implementations.
If you cannot complete a step due to missing info or tool failure, you must:
- record the step as ❌ blocked,
- explain exactly what is missing / what failed,
- stop (do not proceed to later steps).
Each workflow step must end with or . Steps are sequential — do not start a step until the previous one is complete. Each step must include evidence (detected code patterns, file paths, diffs applied, pass/fail results).
Status: ✅ completeStatus: ❌ blocked请按顺序执行工作流步骤,不要跳过任何步骤。首先创建检查清单,然后逐个执行步骤并明确标注完成状态及证据。每个步骤的输出会作为后续步骤的输入,跳过步骤会导致实现错误。
如果因信息缺失或工具故障无法完成某个步骤,你必须:
- 将该步骤标记为 ❌ 阻塞
- 明确说明缺失的信息/故障原因
- 停止执行(不要继续后续步骤)
每个工作流步骤结尾必须标注 或 。步骤是串行的,上一步完成前不要开始下一步。每个步骤必须包含证据(检测到的代码模式、文件路径、应用的变更 diff、通过/失败结果)。
Status: ✅ 已完成Status: ❌ 阻塞Architectural conformance
架构一致性要求
Follow the app's existing architecture, template engine, layout/partial system, code style, and route patterns. Do not switch paradigms (e.g., templates to inline HTML or vice versa). If the app has middleware for shared template variables, prefer that over duplicating across route handlers.
The JWT SSO endpoint must integrate with the app's existing authentication system. The endpoint must only issue Metabase JWTs for users who are already authenticated in the host app. Never create an endpoint that issues tokens without verifying the user's session first.
SSO requests to the Metabase instance must be proxied through the app's backend (FE → BE → Metabase ). This keeps the Metabase instance URL and JWT tokens off the client, avoids CORS issues, and ensures auth is always validated server-side. The JWT shared secret must never be exposed to the frontend.
/auth/sso遵循应用现有的架构、模板引擎、布局/组件系统、代码风格和路由规范,不要切换开发范式(比如将模板改为内联HTML,或是反过来)。如果应用有用于共享模板变量的中间件,优先使用该能力而非在不同路由处理器中重复定义。
JWT SSO端点必须与应用现有认证系统集成,仅为在宿主应用中已经完成认证的用户签发Metabase JWT,绝对不能创建无需验证用户会话就可以签发令牌的端点。
发往Metabase实例的SSO请求必须通过应用后端代理(前端 → 后端 → Metabase )。这种方式可以避免Metabase实例URL和JWT令牌暴露到客户端,解决跨域问题,同时确保认证始终在服务端校验。JWT共享密钥绝对不能暴露给前端。
/auth/ssoImportant performance notes
重要性能注意事项
- Maximize parallelism within each step. Use parallel Grep/Glob/Read calls in a single message wherever possible.
- Do not use sub-agents for project scanning — results need to stay in the main context for cross-referencing in later steps.
- Do not parse repo branches, commits, PRs, or issues.
- 最大化每个步骤内的任务并行度,尽可能在单次请求中并行调用Grep/Glob/Read能力
- 不要使用子Agent做项目扫描,结果需要保留在主上下文中方便后续步骤交叉引用
- 不要解析仓库分支、提交记录、PR或Issue
Scope
适用范围
This skill implements JWT SSO authentication for Metabase embedding. It supports all three embedding types that use SSO:
| Embedding type | Delivery mechanism | Frontend auth config |
|---|---|---|
| Modular embedding (embed.js) | Web components ( | |
Modular embedding SDK ( | React components ( | |
| Full App embedding | iframe with full Metabase UI | iframe |
The SSO endpoint response format (JSON, redirect, proxy to Metabase , etc.) varies by embedding type and Metabase version — consult the fetched docs to determine the correct behavior.
/auth/ssoThe consumer's app may be written in any backend language (Node.js, Python, Ruby, PHP, Java, Go, .NET, etc.). Keep instructions language-agnostic unless a specific language is detected in Step 1.
本技能用于为Metabase嵌入实现JWT SSO身份验证,支持以下三类使用SSO的嵌入方式:
| 嵌入类型 | 交付形式 | 前端认证配置 |
|---|---|---|
| 模块化嵌入(embed.js) | Web组件( | |
模块化嵌入SDK( | React组件( | |
| 全应用嵌入 | 承载完整Metabase UI的iframe | iframe |
SSO端点的响应格式(JSON、重定向、代理到Metabase 等)根据嵌入类型和Metabase版本有所不同,请参考拉取的文档确认正确的行为。
/auth/sso用户的应用可使用任意后端语言(Node.js、Python、Ruby、PHP、Java、Go、.NET等),除非步骤1中检测到特定语言,否则请给出与语言无关的操作指引。
What this skill handles
本技能覆盖的能力
- Creating a JWT signing endpoint that maps the app's authenticated user to Metabase JWT fields (,
email,first_name,last_name,groups)exp - Configuring the frontend auth layer based on the detected embedding type
- Adding the environment variable
METABASE_JWT_SHARED_SECRET - Installing a JWT signing library if one is not already present
- Producing Metabase admin configuration instructions (JWT settings, group mappings, CORS)
- 创建JWT签名端点,将应用已认证用户的信息映射到Metabase JWT字段(、
email、first_name、last_name、groups)exp - 根据检测到的嵌入类型配置前端认证层
- 添加环境变量
METABASE_JWT_SHARED_SECRET - 如果项目中没有JWT签名库则进行安装
- 生成Metabase管理员配置指引(JWT设置、用户组映射、CORS)
What this skill does NOT handle
本技能不覆盖的能力
- Setting up the embedding itself (web components, SDK, or iframes) — use the migration skills for that
- Upgrading the embedding version — use the skill
metabase-modular-embedding-version-upgrade - Guest embeds auth (uses with
METABASE_SECRET_KEYpayloads, not SSO){resource, params} - SAML or LDAP authentication — this skill covers JWT SSO only
- 实现嵌入本身(Web组件、SDK或iframe)—— 请使用迁移类技能完成该操作
- 升级嵌入版本—— 请使用技能
metabase-modular-embedding-version-upgrade - 访客嵌入认证(使用和
METABASE_SECRET_KEYpayload,不属于SSO范畴){resource, params} - SAML或LDAP认证—— 本技能仅覆盖JWT SSO
JWT payload structure (SSO)
JWT payload结构(SSO)
The JWT signed with must contain these fields:
METABASE_JWT_SHARED_SECRET| Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | User's email — Metabase uses this as the unique identifier. Auto-provisions account on first login. |
| string | Yes | User's first name — synced on every login. |
| string | Yes | User's last name — synced on every login. |
| string[] | Yes | Array of group names — Metabase syncs group memberships on every login when group sync is enabled. |
| number | Yes | Token expiration as Unix timestamp. Recommend 10 minutes: e.g. |
Additional user attributes can be included as extra key/value pairs in the JWT — Metabase will store them as user attributes for use in sandboxing and data permissions.
使用签名的JWT必须包含以下字段:
METABASE_JWT_SHARED_SECRET| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| 字符串 | 是 | 用户邮箱,Metabase将其作为唯一标识,用户首次登录时会自动创建账号 |
| 字符串 | 是 | 用户名字,每次登录时同步 |
| 字符串 | 是 | 用户姓氏,每次登录时同步 |
| 字符串数组 | 是 | 用户组名称数组,开启组同步功能后,Metabase会在每次登录时同步用户组成员关系 |
| 数字 | 是 | 令牌过期时间,Unix时间戳格式,建议设置为10分钟有效期,例如: |
可以在JWT中添加额外的用户属性键值对,Metabase会将其存储为用户属性,用于沙箱隔离和数据权限控制。
Allowed documentation sources
允许的文档来源
Fetch the version-specific using this URL:
llms-embedding-full.txthttps://www.metabase.com/docs/v0.{VERSION}/llms-embedding-full.txtThe version in the URL uses the format (normalize: strip leading or , drop patch — e.g., → → URL uses ). This single file contains all embedding documentation for that version, optimized for LLM consumption.
v0.58v0.0.58.158v0.58Other constraints:
- No GitHub PRs/issues or npm pages
- Do not follow changelog links to GitHub or guess URLs
使用以下URL拉取对应版本的文档:
llms-embedding-full.txthttps://www.metabase.com/docs/v0.{VERSION}/llms-embedding-full.txtURL中的版本格式为(标准化规则:去掉开头的或,丢弃补丁版本号,例如 → → URL使用)。该文件包含对应版本所有嵌入相关的文档,针对LLM消费做了优化。
v0.58v0.0.58.158v0.58其他约束:
- 不要访问GitHub PR/Issue或npm页面
- 不要点击跳转到GitHub的更新日志链接,也不要猜测URL
AskUserQuestion triggers
询问用户的触发条件
Use AskUserQuestion and halt until answered if:
- No Metabase embedding code is detected in the project (ask which embedding type the user plans to use)
- The Metabase instance URL cannot be determined from project code or environment variables
- The Metabase instance version cannot be determined from the project code
- The app's user authentication mechanism cannot be determined (how do users log in? session? cookie? token?)
- The user model/schema cannot be identified (where are email, name, and group/role stored?)
- The user's group/role model does not clearly map to Metabase groups (ask the user how they want to map roles → Metabase groups)
- The backend language cannot be determined
出现以下情况时请使用AskUserQuestion能力,暂停执行直到获得用户答复:
- 项目中没有检测到Metabase嵌入代码(询问用户计划使用哪种嵌入类型)
- 无法从项目代码或环境变量中获取Metabase实例URL
- 无法从项目代码中确定Metabase实例版本
- 无法确定应用的用户认证机制(用户如何登录?session?cookie?token?)
- 无法识别用户模型/表结构(邮箱、姓名、用户组/角色存储在哪里?)
- 用户的用户组/角色模型无法清晰映射到Metabase用户组(询问用户希望如何将角色映射到Metabase用户组)
- 无法确定后端语言
Implementation Plan Checklist
实现计划检查清单
Create a checklist to track progress. In Claude Code, use TaskCreate/TaskUpdate tools:
- Step 0: Detect embedding type and Metabase version
- Step 1: Scan project + fetch detected version docs
- Step 2: Design auth architecture
- Step 3: Plan implementation changes
- Step 4: Apply code changes
- Step 5: Validate changes
- Step 6: Final summary
创建清单跟踪进度,在Claude Code中使用TaskCreate/TaskUpdate工具:
- 步骤0:检测嵌入类型和Metabase版本
- 步骤1:扫描项目 + 拉取对应版本的文档
- 步骤2:设计认证架构
- 步骤3:规划实现变更
- 步骤4:应用代码变更
- 步骤5:验证变更
- 步骤6:最终总结
Workflow
工作流
Step 0: Detect embedding type and Metabase version
步骤0:检测嵌入类型和Metabase版本
0a: Detect embedding type
0a:检测嵌入类型
Grep the project for these patterns (in parallel) to determine which embedding type is in use:
Modular embedding (embed.js):
- or
embed.jsin HTML/template files/app/embed.js - or
window.metabaseConfigdefineMetabaseConfig - e.g. ,
<metabase-dashboard,<metabase-question<metabase-browser
Modular embedding SDK:
- in
@metabase/embedding-sdk-reactor import statementspackage.json - or
MetabaseProviderdefineMetabaseAuthConfig - e.g. ,
InteractiveDashboard,InteractiveQuestion, etc.CollectionBrowser
Full App embedding:
- with Metabase URLs (look for the instance URL or
<iframe,/dashboard/,/question/)/auth/sso - redirect logic
/auth/sso - parameter construction
return_to
If no embedding code is found → AskUserQuestion: which embedding type does the user plan to use?
If multiple types are detected, the SSO endpoint must handle all of them (see dual-mode endpoint in Step 2).
Record the detected embedding type(s) — this controls the entire implementation.
并行在项目中搜索以下模式,确定当前使用的嵌入类型:
模块化嵌入(embed.js):
- HTML/模板文件中的或
embed.js/app/embed.js - 或
window.metabaseConfigdefineMetabaseConfig - 例如:、
<metabase-dashboard、<metabase-question<metabase-browser
模块化嵌入SDK:
- 或导入语句中的
package.json@metabase/embedding-sdk-react - 或
MetabaseProviderdefineMetabaseAuthConfig - 例如:、
InteractiveDashboard、InteractiveQuestion等CollectionBrowser
全应用嵌入:
- 包含Metabase URL的(查找实例URL或
<iframe、/dashboard/、/question/路径)/auth/sso - 重定向逻辑
/auth/sso - 参数构造逻辑
return_to
如果没有找到嵌入代码 → 询问用户:计划使用哪种嵌入类型?
如果检测到多种嵌入类型,SSO端点必须支持所有类型(参考步骤2中的双模式端点说明)。
记录检测到的嵌入类型,这将决定整个实现方案。
0b: Detect Metabase instance version
0b:检测Metabase实例版本
The Metabase instance version determines which auth config fields, function signatures, and SSO behavior are available. Always AskUserQuestion for the instance version — even if a version appears in Docker tags, env vars, or package.json, confirm it with the user. The instance version is the source of truth for fetching docs.
SDK/instance version mismatch check: If the project uses (npm package), compare the SDK package version with the instance version. The SDK package version must match the instance version — e.g., SDK v0.52.x requires instance v0.52.x. If they don't match, stop and tell the user to align the versions before proceeding with SSO. Suggest using the skill to upgrade.
@metabase/embedding-sdk-reactmetabase-modular-embedding-version-upgradeMetabase实例版本决定了可用的认证配置字段、函数签名和SSO行为。即便是Docker标签、环境变量或package.json中出现了版本,也必须向用户确认实例版本,实例版本是拉取文档的唯一依据。
SDK/实例版本不匹配校验:如果项目使用了(npm包),请比对SDK包版本和实例版本,两者必须匹配,例如SDK v0.52.x需要实例版本为v0.52.x。如果版本不匹配,停止执行并告知用户先对齐版本再进行SSO配置,建议使用技能完成升级。
@metabase/embedding-sdk-reactmetabase-modular-embedding-version-upgradeStep 1: Scan the project + fetch docs
步骤1:扫描项目 + 拉取文档
Perform the project scan and doc fetch concurrently — they are independent. Use parallel tool calls within a single message wherever there are no dependencies.
并行执行项目扫描和文档拉取,两者互不依赖。只要没有依赖关系,尽可能在单次请求中并行调用工具。
1a: Fetch docs for the Metabase instance version
1a:拉取Metabase实例版本对应的文档
Fetch for the instance version confirmed in Step 0b (see "Allowed documentation sources" for URL format). Search within it for , , , , , and to find the relevant auth documentation.
llms-embedding-full.txtfetchRequestTokenauthProviderUrijwtProviderUridefineMetabaseAuthConfigJWTSSOThese docs are the authoritative source for auth configuration options, function signatures, deprecated fields, and endpoint response formats for the detected version. Use them in Step 2 when designing the auth architecture.
Launch this concurrently with the project scan steps below.
拉取步骤0b中确认的实例版本对应的文档(URL格式参考「允许的文档来源」章节),在文档中搜索、、、、和找到相关的认证文档。
llms-embedding-full.txtfetchRequestTokenauthProviderUrijwtProviderUridefineMetabaseAuthConfigJWTSSO这些文档是对应版本下认证配置选项、函数签名、废弃字段和端点响应格式的权威来源,步骤2设计认证架构时请以文档为准。
请与下面的项目扫描步骤并行执行本操作。
1b: Identify backend language and framework
1b:识别后端语言和框架
- Check for dependency/build files (,
package.json,requirements.txt,Gemfile,pom.xml,go.mod, etc.).composer.json - Identify the web framework (Express, Fastify, Flask, Django, Rails, Spring, Gin, Laravel, ASP.NET, etc.).
- Record the language, framework, and any middleware patterns.
- 检查依赖/构建文件(、
package.json、requirements.txt、Gemfile、pom.xml、go.mod等)composer.json - 识别Web框架(Express、Fastify、Flask、Django、Rails、Spring、Gin、Laravel、ASP.NET等)
- 记录语言、框架和所有中间件模式
1c: Find existing authentication code
1c:查找现有认证代码
This is critical — the SSO endpoint must integrate with the app's existing auth. Search for:
- Session middleware (,
express-session,cookie-session,flask-login,devise,Passport, etc.)next-auth - Auth middleware patterns (,
req.user,req.session,current_user,@login_required, etc)[Authorize] - User model/schema definitions (look for fields: ,
email,name,first_name,last_name,role, etc)group - Login routes (,
/login,/auth,/signin, etc)/api/auth - Token/cookie based auth (JWT verification middleware, cookie parsers, etc)
For each matching file, read the entire file.
这一步非常关键,SSO端点必须与应用现有认证体系集成。搜索以下内容:
- Session中间件(、
express-session、cookie-session、flask-login、devise、Passport等)next-auth - 认证中间件模式(、
req.user、req.session、current_user、@login_required等)[Authorize] - 用户模型/表结构定义(查找字段:、
email、name、first_name、last_name、role等)group - 登录路由(、
/login、/auth、/signin等)/api/auth - 基于Token/Cookie的认证(JWT校验中间件、Cookie解析器等)
每个匹配到的文件请读取完整内容。
1d: Find existing Metabase embedding code
1d:查找现有Metabase嵌入代码
Read all files identified in Step 0a. Extract:
- The Metabase instance URL (env var or hardcoded)
- Current auth configuration (if any — may already have partial SSO setup)
- Layout/head files where embed.js or metabaseConfig is configured
- Any existing SSO/JWT endpoint for Metabase
- Environment variables related to Metabase (,
METABASE_)MB_
读取步骤0a中识别到的所有文件,提取以下信息:
- Metabase实例URL(环境变量或硬编码)
- 当前的认证配置(如果有,可能已经有部分SSO配置)
- 配置embed.js或metabaseConfig的布局/head文件
- 任何已有的Metabase SSO/JWT端点
- 与Metabase相关的环境变量(、
METABASE_)MB_
1e: Find user model and group/role structure
1e:查找用户模型和用户组/角色结构
Search for the user model to understand available fields:
- Database schema files, ORM models, or type definitions containing user fields
- Group/role definitions (enums, database tables, constants)
- How the current user is attached to the request (e.g., , session store)
req.user
搜索用户模型了解可用字段:
- 包含用户字段的数据库 schema 文件、ORM模型或类型定义
- 用户组/角色定义(枚举、数据库表、常量)
- 当前用户信息如何挂载到请求上(例如:、session存储)
req.user
Output: Structured Project Inventory
输出:结构化项目清单
Backend: {language}, {framework}
Auth system: {mechanism} (e.g., express-session + Passport, next-auth, Django sessions)
User model: {file}:{line} — fields: {email, first_name, last_name, role, ...}
User on request: {how to access} (e.g., req.user, request.user, session[:user])
Groups/roles: {source} — values: {list of group/role names}
Embedding type: {modular | sdk | full-app | multiple}
Metabase URL: {env var or value}
Metabase version: {version}
Existing SSO endpoint: {file}:{line} or "none"
Existing auth config: {description} or "none"Backend: {language}, {framework}
Auth system: {mechanism} (例如:express-session + Passport, next-auth, Django sessions)
User model: {file}:{line} — fields: {email, first_name, last_name, role, ...}
User on request: {获取方式} (例如:req.user, request.user, session[:user])
Groups/roles: {来源} — values: {用户组/角色名称列表}
Embedding type: {modular | sdk | full-app | multiple}
Metabase URL: {环境变量或值}
Metabase version: {版本号}
Existing SSO endpoint: {file}:{line} 或 "none"
Existing auth config: {描述} 或 "none"Step 2: Design auth architecture (only after Step 1 ✅)
步骤2:设计认证架构(仅在步骤1 ✅ 完成后执行)
Based on the project inventory, design the SSO implementation. This step produces the design — no code changes yet.
基于项目清单设计SSO实现方案,本步骤仅输出设计,暂不修改代码。
2a: JWT endpoint design
2a:JWT端点设计
Design the SSO endpoint route:
-
Route: Choose a route that fits the app's existing patterns. Common choices:,
/sso/metabase,/api/auth/metabase. Follow the app's existing route naming conventions./auth/metabase-sso -
HTTP method: GET (Metabase's SDK/embed.js sends GET requests to the JWT provider URI)
-
Auth guard: The endpoint MUST be protected by the app's existing auth middleware. Only authenticated users should receive a Metabase JWT. Specify which middleware/decorator to use based on Step 1c findings.
-
User mapping: Define how to extract user fields from the request:
email ← {source} (e.g., req.user.email) first_name ← {source} (e.g., req.user.firstName or req.user.name.split(' ')[0]) last_name ← {source} (e.g., req.user.lastName or req.user.name.split(' ')[1]) groups ← {source} (e.g., [req.user.role] or req.user.groups) -
Group mapping strategy: If the app's roles/groups don't directly match desired Metabase groups, define a mapping:
App role "admin" → Metabase group "Administrators" App role "analyst" → Metabase group "Analysts" App role "viewer" → Metabase group "Viewers"If the mapping is unclear → AskUserQuestion. -
Token expiration: 10 minutes (e.g.) unless the app has a specific session timeout that should be matched.
Math.round(Date.now() / 1000) + 600
设计SSO端点路由:
- 路由:选择符合应用现有规范的路由,常见选择:、
/sso/metabase、/api/auth/metabase,遵循应用现有的路由命名规则/auth/metabase-sso - HTTP方法:GET(Metabase的SDK/embed.js会向JWT提供商URI发送GET请求)
- 认证保护:端点必须通过应用现有认证中间件保护,仅已认证用户可以获取Metabase JWT,根据步骤1c的结果指定要使用的中间件/装饰器
- 用户字段映射:定义如何从请求中提取用户字段:
email ← {来源} (例如:req.user.email) first_name ← {来源} (例如:req.user.firstName 或 req.user.name.split(' ')[0]) last_name ← {来源} (例如:req.user.lastName 或 req.user.name.split(' ')[1]) groups ← {来源} (例如:[req.user.role] 或 req.user.groups) - 用户组映射策略:如果应用的角色/用户组与预期的Metabase用户组不能直接匹配,定义映射规则:
如果映射规则不明确 → 询问用户。
应用角色 "admin" → Metabase用户组 "Administrators" 应用角色 "analyst" → Metabase用户组 "Analysts" 应用角色 "viewer" → Metabase用户组 "Viewers" - 令牌有效期:10分钟(例如),除非应用有特定的会话超时要求需要对齐。
Math.round(Date.now() / 1000) + 600
2b: Endpoint response behavior
2b:端点响应行为
Consult the fetched docs to determine what the SSO endpoint should return for the detected embedding type and Metabase version. The response format (JSON with a signed JWT, redirect to Metabase , server-side proxy, etc.) varies — do not assume a fixed pattern. The docs describe how the SDK/embed.js/iframe expects to receive the authentication token for the detected version.
/auth/ssoIf the project uses multiple embedding types, the endpoint may need to support multiple response modes (e.g., distinguishing via a query parameter). Check the docs for how each embedding type calls the JWT provider.
参考拉取的文档,确定检测到的嵌入类型和Metabase版本对应的SSO端点返回内容。响应格式(带签名JWT的JSON、重定向到Metabase 、服务端代理等)各版本有所不同,不要假设固定模式,文档会说明对应版本下SDK/embed.js/iframe期望接收认证令牌的方式。
/auth/sso如果项目使用多种嵌入类型,端点可能需要支持多种响应模式(例如通过查询参数区分),请查阅文档了解每种嵌入类型调用JWT提供商的方式。
2c: Frontend auth configuration
2c:前端认证配置
Decide the frontend auth approach based on embedding type. Consult the docs fetched in Step 1a to determine which auth config fields are available for the detected version — field names, signatures, and supported options vary across versions. The exact code patterns are specified in Step 3d.
根据嵌入类型确定前端认证方案,参考步骤1a拉取的文档确定对应版本下可用的认证配置字段,字段名、签名和支持的选项不同版本会有差异,具体代码模式会在步骤3d中说明。
2d: JWT library selection
2d:JWT库选择
If the project doesn't already have a JWT library:
| Language | Library | Install command |
|---|---|---|
| Node.js | | |
| Python | | |
| Ruby | | |
| PHP | | |
| Java | | Add to Maven/Gradle |
| Go | | |
| .NET | | |
If a JWT library is already in the project, use it.
如果项目中还没有JWT库,按以下规则选择:
| 语言 | 库 | 安装命令 |
|---|---|---|
| Node.js | | |
| Python | | |
| Ruby | | |
| PHP | | |
| Java | | 添加到Maven/Gradle |
| Go | | |
| .NET | | |
如果项目中已有JWT库,直接使用即可。
Step 3: Plan implementation changes (only after Step 2 ✅)
步骤3:规划实现变更(仅在步骤2 ✅ 完成后执行)
Create a complete file-by-file change plan. Every change should be specified with the target file, the old code (if modifying), and the new code.
创建完整的逐文件变更计划,每个变更都要指定目标文件、原有代码(如果是修改)和新代码。
3a: Environment variable
3a:环境变量
- Add to the project's environment configuration (
METABASE_JWT_SHARED_SECRET,.env,.env.example, or wherever other Metabase env vars are defined)docker-compose.yml - Value: placeholder string with a comment explaining it must match the key generated in Metabase admin
- 在项目的环境配置文件中添加(
METABASE_JWT_SHARED_SECRET、.env、.env.example或其他Metabase环境变量的存储位置)docker-compose.yml - 值为占位字符串,附带注释说明必须与Metabase管理员后台生成的密钥一致
3b: JWT library installation
3b:JWT库安装
- If no JWT library is present: specify the install command
- If one exists: skip this step
- 如果没有JWT库:指定安装命令
- 如果已有JWT库:跳过本步骤
3c: SSO endpoint implementation
3c:SSO端点实现
Specify the exact code for the new endpoint:
- File: where to add the route (existing routes file, or new file if the app separates routes by feature)
- Auth middleware applied to the route
- User field extraction (from Step 2a mapping)
- JWT signing with
METABASE_JWT_SHARED_SECRET - Response format as determined in Step 2b (from the fetched docs)
The endpoint must:
- Read from environment
METABASE_JWT_SHARED_SECRET - Extract the authenticated user from the request (using the app's existing auth mechanism)
- Build the JWT payload with ,
email,first_name,last_name,groupsexp - Sign the token using the HS256 algorithm (Metabase's default)
- Return the response appropriate for the embedding type
The endpoint must NOT:
- Accept user identity from the request body or query params (security vulnerability — user could forge identity)
- Issue tokens without checking authentication
- Hardcode user information
- Use a different signing algorithm unless specifically configured in Metabase admin
指定新端点的具体代码:
- 文件:添加路由的位置(现有路由文件,或如果应用按功能拆分路由则新建文件)
- 路由上应用的认证中间件
- 用户字段提取逻辑(来自步骤2a的映射规则)
- 使用签名JWT的逻辑
METABASE_JWT_SHARED_SECRET - 步骤2b确定的响应格式(来自拉取的文档)
端点必须满足:
- 从环境变量读取
METABASE_JWT_SHARED_SECRET - 从请求中提取已认证用户信息(使用应用现有认证机制)
- 构造包含、
email、first_name、last_name、groups字段的JWT payloadexp - 使用HS256算法签名令牌(Metabase默认算法)
- 返回适配嵌入类型的响应
端点禁止:
- 从请求体或查询参数中读取用户身份信息(存在安全漏洞,用户可以伪造身份)
- 未校验认证就签发令牌
- 硬编码用户信息
- 除非Metabase管理员后台有特殊配置,否则不要使用其他签名算法
3d: Frontend auth configuration
3d:前端认证配置
Use the docs fetched in Step 1a as the authoritative source for auth config fields, function signatures, and deprecated options for the target Metabase version. Config fields, parameter signatures, and deprecated options change across versions — do not assume any specific field exists without confirming it in the docs.
Modular embedding (embed.js):
- Check the docs for which auth-related fields supports in the detected version (e.g.,
window.metabaseConfigmay or may not be available).jwtProviderUri - If the docs do not list a frontend auth config field, the JWT Identity Provider URI must be configured in Metabase admin only.
Modular embedding SDK:
- Check the docs for the options and the
defineMetabaseAuthConfigfunction signature — especially whether it receives parameters or not.fetchRequestToken - The endpoint URL should be hardcoded in the body unless the docs say otherwise.
fetchRequestToken - Remove any deprecated auth config fields that the existing code uses (e.g., was removed in later versions). The docs for the detected version are the source of truth for what fields are valid.
authProviderUri
Full App embedding:
- Update iframe to route through the SSO endpoint or Metabase's
srcpath with a/auth/ssoparameter containing the URL-encoded destination path (e.g.,return_to).%2Fdashboard%2F1
以步骤1a拉取的文档作为目标Metabase版本下认证配置字段、函数签名和废弃选项的权威来源,配置字段、参数签名和废弃选项不同版本会有差异,未在文档中确认不要假设某个字段存在。
模块化嵌入(embed.js):
- 查阅文档确认对应版本下支持的认证相关字段(例如
window.metabaseConfig可能存在也可能不存在)jwtProviderUri - 如果文档中没有列出前端认证配置字段,说明JWT身份提供商URI仅需在Metabase管理员后台配置
模块化嵌入SDK:
- 查阅文档确认的选项和
defineMetabaseAuthConfig的函数签名,特别是是否接收参数fetchRequestToken - 除非文档另有说明,否则端点URL应该硬编码在函数体中
fetchRequestToken - 移除现有代码中使用的废弃认证配置字段(例如在后续版本中已被移除),对应版本的文档是有效字段的唯一依据
authProviderUri
全应用嵌入:
- 更新iframe 使其通过SSO端点或Metabase的
src路径访问,附带/auth/sso参数,值为URL编码后的目标路径(例如return_to)%2Fdashboard%2F1
3e: Remove development-only and deprecated auth (if present)
3e:移除仅用于开发的废弃认证配置(如果存在)
Remove any auth config fields that are not listed in the detected version's docs. Common examples:
- — API keys are for local dev only, not production SSO
apiKey - — uses the admin browser session, not for production
useExistingUserSession - Any other fields present in the existing code but absent from the detected version docs (they were likely deprecated or removed)
移除所有未在对应版本文档中列出的认证配置字段,常见例子:
- — API密钥仅用于本地开发,不适用于生产环境SSO
apiKey - — 使用管理员浏览器会话,不适用于生产环境
useExistingUserSession - 现有代码中存在但对应版本文档中没有的其他字段(很可能已经被废弃或移除)
3f: Metabase admin configuration notes (manual steps)
3f:Metabase管理员配置说明(手动步骤)
List these as part of the plan — they will be included in the final summary:
- Enable JWT authentication: Admin > Settings > Authentication > JWT > enable
- Set JWT signing key: Paste the same value as
METABASE_JWT_SHARED_SECRET - Set JWT Identity Provider URI: The full URL of the SSO endpoint (e.g., ) — check the fetched docs to determine whether this is required or optional for the detected version (it depends on whether the frontend config supports a JWT provider field).
http://localhost:9090/sso/metabase - Configure group sync:
- Enable "Synchronize Group Memberships"
- Create matching groups in Metabase, or set up group mappings if names differ
- Configure CORS (for modular embedding only): Admin > Embedding > Modular embedding > add the host app's domain
- SameSite cookie setting (for cross-domain deployments): Admin > Embedding > set to "None" (requires HTTPS)
将以下内容列入计划,会包含在最终总结中:
- 启用JWT认证:管理员后台 > 设置 > 认证 > JWT > 启用
- 设置JWT签名密钥:粘贴与相同的值
METABASE_JWT_SHARED_SECRET - 设置JWT身份提供商URI:SSO端点的完整URL(例如)—— 查阅拉取的文档确认对应版本下该配置是必填还是选填(取决于前端配置是否支持JWT提供商字段)
http://localhost:9090/sso/metabase - 配置用户组同步:
- 开启「同步用户组成员关系」
- 在Metabase中创建匹配的用户组,或者如果名称不同则配置组映射
- 配置CORS(仅适用于模块化嵌入):管理员后台 > 嵌入 > 模块化嵌入 > 添加宿主应用的域名
- SameSite Cookie设置(适用于跨域部署):管理员后台 > 嵌入 > 设置为「None」(需要HTTPS)
Step 4: Apply code changes (only after Step 3 ✅)
步骤4:应用代码变更(仅在步骤3 ✅ 完成后执行)
Apply all changes from Step 3 in this order:
- Add environment variable (Step 3a)
- Install JWT library if needed (Step 3b)
- Create the SSO endpoint (Step 3c) — this is the core change
- Configure frontend auth (Step 3d)
- Remove dev-only auth if present (Step 3e)
Constraints:
- Use the Edit tool with precise /
old_stringfor every change to existing filesnew_string - Use the Write tool only for new files
- Do not change the app's existing authentication system — only add the Metabase SSO layer on top
- Do not change environment variable names that already exist in the project
- If a file requires multiple edits, apply them top-to-bottom to avoid offset issues
按以下顺序应用步骤3中的所有变更:
- 添加环境变量(步骤3a)
- 按需安装JWT库(步骤3b)
- 创建SSO端点(步骤3c)—— 核心变更
- 配置前端认证(步骤3d)
- 移除仅用于开发的认证配置(步骤3e)
约束:
- 对现有文件的所有变更都使用Edit工具,指定精确的/
old_stringnew_string - 仅当创建新文件时使用Write工具
- 不要修改应用现有认证体系,仅在其之上添加Metabase SSO层
- 不要修改项目中已存在的环境变量名称
- 如果一个文件需要多次修改,从上到下依次应用变更避免偏移问题
Step 5: Validate changes (only after Step 4 ✅)
步骤5:验证变更(仅在步骤4 ✅ 完成后执行)
Perform all of these checks. Each check should have an explicit pass/fail result.
执行所有以下检查,每个检查必须有明确的通过/失败结果。
5a: SSO endpoint exists and is auth-protected
5a:SSO端点存在且受认证保护
Read the SSO endpoint file. Verify:
- The route exists with the planned path
- Auth middleware is applied (the endpoint is protected)
- The JWT payload includes all required fields: ,
email,first_name,last_name,groupsexp - The token is signed with from environment
METABASE_JWT_SHARED_SECRET - The response format matches what the fetched docs specify for the embedding type
Pass criteria: endpoint is complete and auth-protected.
读取SSO端点文件,验证:
- 路由路径与规划一致
- 已应用认证中间件(端点受保护)
- JWT payload包含所有必填字段:、
email、first_name、last_name、groupsexp - 令牌使用环境变量中的签名
METABASE_JWT_SHARED_SECRET - 响应格式与拉取的文档中对应嵌入类型的要求一致
通过标准:端点完整且受认证保护。
5b: Frontend auth is configured
5b:前端认证已配置
Verify the frontend auth config uses only fields listed in the detected version's docs. No deprecated or removed fields should remain.
- embed.js: auth fields match what the docs support
window.metabaseConfig - SDK: options and
defineMetabaseAuthConfigsignature match the docsfetchRequestToken - Full App: iframe src routes through SSO
Pass criteria: frontend auth matches the embedding type and detected version docs.
验证前端认证配置仅使用对应版本文档中列出的字段,没有保留废弃或已移除的字段:
- embed.js:的认证字段与文档支持的一致
window.metabaseConfig - SDK:的选项和
defineMetabaseAuthConfig的签名与文档一致fetchRequestToken - 全应用嵌入:iframe src通过SSO端点访问
通过标准:前端认证配置匹配嵌入类型和对应版本文档要求。
5c: No dev-only or deprecated auth remains
5c:没有保留仅用于开发的废弃认证配置
Use Grep to search for across all project files (excluding , ). Also search for near or — a bare grep is too broad and will match unrelated code. Also verify no deprecated config fields remain (compare against the detected version docs).
useExistingUserSessionnode_modules.gitapiKeymetabaseConfigdefineMetabaseAuthConfigapiKeyPass criteria: no Metabase-specific development-only or deprecated auth methods remain.
使用Grep在所有项目文件中搜索(排除、)。同时在或附近搜索(直接全局搜索范围太广会匹配无关代码)。另外验证没有保留废弃的配置字段(与对应版本文档比对)。
useExistingUserSessionnode_modules.gitmetabaseConfigdefineMetabaseAuthConfigapiKeyapiKey通过标准:没有保留Metabase专属的仅用于开发或废弃的认证方式。
5d: JWT library is available
5d:JWT库已可用
Check that the JWT library is in the project's dependencies (e.g., , ).
package.jsonrequirements.txtPass criteria: library is listed or was already present.
检查JWT库是否在项目依赖中(例如、)。
package.jsonrequirements.txt通过标准:库已列在依赖中或之前已经存在。
5e: Spot-check the endpoint code
5e:端点代码抽查
Verify the endpoint does NOT:
- Accept user identity from request body/query params
- Issue tokens without auth middleware
- Hardcode user information
- Use a signing key other than
METABASE_JWT_SHARED_SECRET
Pass criteria: all security checks pass.
If any check fails:
- Fix the issue immediately
- Re-run the specific check
- If unable to fix after 3 attempts, mark Step 5 ❌ blocked and report which check failed and why
验证端点没有以下问题:
- 从请求体/查询参数中获取用户身份信息
- 没有认证中间件就签发令牌
- 硬编码用户信息
- 使用以外的签名密钥
METABASE_JWT_SHARED_SECRET
通过标准:所有安全检查通过。
如果任何检查失败:
- 立即修复问题
- 重新执行对应检查
- 如果尝试3次仍无法修复,将步骤5标记为 ❌ 阻塞并报告哪个检查失败及原因
Step 6: Output summary
步骤6:输出总结
Organize the final output into these sections:
- Changes applied: list every file modified/created and a one-line description of each change
- SSO endpoint: route path, HTTP method, response behavior, which auth middleware protects it
- JWT payload mapping: table showing how app user fields map to Metabase JWT fields:
| Metabase field | Source | Example value | |---|---|---| | email | req.user.email | "jane@example.com" | | first_name | req.user.firstName | "Jane" | | last_name | req.user.lastName | "Doe" | | groups | [req.user.role] | ["Analyst"] | | exp | Date.now()/1000 + 600 | 1700000600 | - Group mapping: how app roles/groups map to Metabase groups
- Manual steps required (Metabase admin configuration from Step 3f):
- Enable JWT authentication and set signing key
- Set JWT Identity Provider URI
- Configure group sync and mappings
- Configure CORS (if modular embedding)
- Set SameSite cookie (if cross-domain)
- Security notes:
- The endpoint is protected by — only authenticated users can obtain a Metabase JWT
{middleware} - must be kept secret and match the value in Metabase admin
METABASE_JWT_SHARED_SECRET - Each user gets their own Metabase account (auto-provisioned on first login)
- Token expiration is set to {N} minutes
- The endpoint is protected by
将最终输出整理为以下章节:
- 应用的变更:列出所有修改/创建的文件,以及每个变更的一行说明
- SSO端点:路由路径、HTTP方法、响应行为、保护端点的认证中间件
- JWT payload映射:表格展示应用用户字段如何映射到Metabase JWT字段:
| Metabase字段 | 来源 | 示例值 | |---|---|---| | email | req.user.email | "jane@example.com" | | first_name | req.user.firstName | "Jane" | | last_name | req.user.lastName | "Doe" | | groups | [req.user.role] | ["Analyst"] | | exp | Date.now()/1000 + 600 | 1700000600 | - 用户组映射:应用角色/用户组如何映射到Metabase用户组
- 需要手动执行的步骤(来自步骤3f的Metabase管理员配置):
- 启用JWT认证并设置签名密钥
- 设置JWT身份提供商URI
- 配置用户组同步和映射
- 配置CORS(如果是模块化嵌入)
- 设置SameSite Cookie(如果是跨域部署)
- 安全注意事项:
- 端点受保护 —— 仅已认证用户可以获取Metabase JWT
{middleware} - 必须保密,且与Metabase管理员后台中的值一致
METABASE_JWT_SHARED_SECRET - 每个用户会获得独立的Metabase账号(首次登录时自动创建)
- 令牌有效期设置为{N}分钟
- 端点受
Retry policy
重试策略
Doc fetching:
- If fetching returns 404, verify the Metabase version number and retry. If still failing, mark Step 1 ❌ blocked.
llms-embedding-full.txt
Validation:
- If AskUserQuestion is not answered, remain blocked on that step — do not guess or proceed with assumptions.
- If any validation check in Step 5 fails after 3 fix attempts, mark Step 5 ❌ blocked and report which check failed and why.
文档拉取:
- 如果拉取返回404,验证Metabase版本号后重试,如果仍然失败,将步骤1标记为 ❌ 阻塞。
llms-embedding-full.txt
验证:
- 如果用户没有答复询问的问题,保持阻塞状态,不要猜测或基于假设继续执行。
- 如果步骤5中的任何验证检查尝试3次修复后仍失败,将步骤5标记为 ❌ 阻塞并报告哪个检查失败及原因。