Skip to content

✨ feat(cli): support api key auth in cli#13190

Merged
arvinxx merged 35 commits into
lobehub:canaryfrom
cy948:feat/cli-api-key-auth
Mar 26, 2026
Merged

✨ feat(cli): support api key auth in cli#13190
arvinxx merged 35 commits into
lobehub:canaryfrom
cy948:feat/cli-api-key-auth

Conversation

@cy948

@cy948 cy948 commented Mar 22, 2026

Copy link
Copy Markdown
Contributor

💻 Change Type

  • ✨ feat
  • 🐛 fix
  • ♻️ refactor
  • 💄 style
  • 👷 build
  • ⚡️ perf
  • ✅ test
  • 📝 docs
  • 🔨 chore

🔗 Related Issue

close LOBE-6247

🔀 Description of Change

  • apps/cli/src/commands/login.ts:为 lh login 增加环境变量读取,如果环境变量中有 LOBEHUB_CLI_API_KEY 则跳过登陆,只保存 --server (如有)。
  • apps/cli/src/auth/apiKey.ts:新增 API key 辅助模块,通过 /api/v1/users/me 校验 API key 并拿到 userId,供本地持久化和
    后续 connect 使用。
  • apps/cli/src/auth/credentials.ts:把本地凭证结构拆成 API key 和 JWT 两类,分别存 apiKey / accessToken,并在读取时基
    于 tokenType 做校验和解析。
  • apps/cli/src/auth/refresh.ts:统一从本地凭证取可用认证信息;API key 直接返回,JWT 过期时继续走原有 refresh token 刷
    新逻辑。
  • apps/cli/src/auth/resolveToken.ts:统一解析 CLI 运行时认证信息,返回 token + tokenType + userId;本地 API key 直接使
    用保存的 userId,JWT 则从 sub 里解析。
  • apps/cli/src/api/http.ts:保持 /webapi/* 仍然只支持 OIDC/JWT;如果当前登录态是 API key,这里会直接报错退出,不会误走
    旧链路。
  • apps/cli/src/api/client.ts:让 tRPC 客户端按认证类型自动切换请求头,API key 走 X-API-Key,JWT 继续走 Oidc-Auth,从而
    让 lh connect 能直接复用本地 API key 登录态。
  • apps/cli/src/commands/connect.ts:接入新的运行时认证解析结果,连接日志展示当前认证类型,并在鉴权失败/过期时按 JWT 与
    API key 的不同语义给出不同处理;JWT 仍可尝试 refresh,API key 只能重新登录。
  • src/libs/trpc/lambda/context.ts:服务端 tRPC lambda context 新增 X-API-Key 鉴权支持;收到 API key 时优先校验 key 并
    注入对应 userId;这次还修复了一个安全问题,API key 校验失败后不再回退到 OIDC 或 session。
  • tests:测试主要是同步新的凭证结构、tokenType 分支、API key 登录/连接链路,以及服务端 “无 API key fallback” 的安全回
    归用例;相对 canary 没发现还需要继续删掉的无用测试改动。

🧪 How to Test

  • Tested locally
  • Added/updated tests
  • No tests needed

📸 Screenshots / Videos

Before After
... ...

📝 Additional Information

@vercel

vercel Bot commented Mar 22, 2026

Copy link
Copy Markdown

@cy948 is attempting to deploy a commit to the LobeHub OSS Team on Vercel.

A member of the Team first needs to authorize it.

@lobehubbot

Copy link
Copy Markdown
Member

@tjx666 @nekomeowww - This PR adds API key auth support for the CLI and updates the server-side tRPC lambda context. Please coordinate on review.

@codecov

codecov Bot commented Mar 22, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 63.26531% with 36 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.25%. Comparing base (7af4562) to head (57ee0a0).
⚠️ Report is 50 commits behind head on canary.

Additional details and impacted files
@@            Coverage Diff             @@
##           canary   #13190      +/-   ##
==========================================
+ Coverage   72.16%   74.25%   +2.08%     
==========================================
  Files        1471     1553      +82     
  Lines      115393   127437   +12044     
  Branches    15171    14070    -1101     
==========================================
+ Hits        83275    94629   +11354     
- Misses      32007    32697     +690     
  Partials      111      111              
Flag Coverage Δ
app 67.26% <58.13%> (-0.03%) ⬇️
database 97.89% <100.00%> (?)
packages/agent-runtime 89.60% <ø> (ø)
packages/context-engine 83.59% <ø> (+0.05%) ⬆️
packages/conversation-flow 92.36% <ø> (ø)
packages/file-loaders 87.02% <ø> (ø)
packages/memory-user-memory 66.68% <ø> (ø)
packages/model-bank 99.85% <ø> (+0.01%) ⬆️
packages/model-runtime 84.53% <ø> (-0.26%) ⬇️
packages/prompts 74.60% <ø> (ø)
packages/python-interpreter 92.90% <ø> (ø)
packages/ssrf-safe-fetch 0.00% <ø> (ø)
packages/utils 90.34% <ø> (+0.24%) ⬆️
packages/web-crawler 88.82% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
Store 66.10% <ø> (+0.02%) ⬆️
Services 49.70% <ø> (-0.18%) ⬇️
Server 68.71% <ø> (-0.31%) ⬇️
Libs 44.98% <86.04%> (+2.77%) ⬆️
Utils 91.41% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cy948 cy948 marked this pull request as ready for review March 23, 2026 13:00

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @cy948, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ee4bb72eeb

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread apps/cli/src/auth/resolveToken.ts Outdated
Comment on lines +69 to +70
if (credentials.tokenType === 'apiKey') {
return { token: credentials.apiKey, tokenType: 'apiKey', userId: credentials.userId };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Prevent API keys from being sent to gateway auth

Returning stored API-key credentials here makes lh connect send a raw API key as the gateway auth token, but the gateway auth path only accepts SERVICE_TOKEN or a JWT (it calls verifyDesktopTokenjwtVerify in apps/device-gateway/src/DeviceGatewayDO.ts and apps/device-gateway/src/auth.ts). In the API-key-login flow this will consistently fail with auth_failed, so users who log in via --api-key cannot actually connect.

Useful? React with 👍 / 👎.

Comment thread apps/cli/src/auth/credentials.ts Outdated
Comment on lines +72 to +73
if (credentials.tokenType !== 'jwt') return null;
if (typeof credentials.accessToken !== 'string') return null;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve backward compatibility for legacy JWT credentials

This loader now rejects any decrypted credential object that lacks tokenType, but pre-change JWT credentials were persisted without that field. After upgrading, existing encrypted credential files are treated as invalid and all CLI commands behave as logged out until users manually run lh login again. Treating missing tokenType as legacy JWT would avoid this regression.

Useful? React with 👍 / 👎.

Comment thread src/libs/trpc/lambda/context.ts Outdated
Comment thread apps/cli/src/api/http.ts Outdated
}

export async function getAuthInfo(): Promise<AuthInfo> {
if (process.env[CLI_API_KEY_ENV]) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里不应该判,而是应该在 !result 后,如果检测到有 API_KEY ,才提醒。 当前的实现会挡住一些正常使用 oidc 登录的用户。

Comment thread apps/cli/src/auth/refresh.ts Outdated
}

// Token expired try refresh
// Token expired, try refresh

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里的变更没有必要

Comment thread apps/cli/src/auth/resolveToken.ts
Comment thread apps/cli/src/api/http.ts Outdated
import { loadSettings } from '../settings';
import { log } from '../utils/logger';

const CLI_API_KEY_ENV = 'LOBEHUB_CLI_API_KEY';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个抽一个const 变量出来

Comment thread apps/cli/src/auth/resolveToken.ts
Comment thread apps/cli/src/commands/status.ts Outdated
}

const timeout = Number.parseInt(options.timeout || '10000', 10);
const serverUrl = (settings?.serverUrl || OFFICIAL_SERVER_URL).replace(/\/$/, '');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

serverUrl 应该弄一个方法统一方法吧,目前看好多地方都加了这个处理逻辑,不干净

@arvinxx arvinxx changed the title ✨ feat(cli): support api key auth ✨ feat(cli): support api key auth in cli Mar 25, 2026
@arvinxx arvinxx merged commit 4dd271c into lobehub:canary Mar 26, 2026
19 of 21 checks passed
@lobehubbot

Copy link
Copy Markdown
Member

❤️ Great PR @cy948 ❤️

The growth of project is inseparable from user feedback and contribution, thanks for your contribution! If you are interesting with the lobehub developer community, please join our discord and then dm @arvinxx or @canisminor1990. They will invite you to our private developer channel. We are talking about the lobe-chat development or sharing ai newsletter around the world.

ONLY-yours added a commit that referenced this pull request Mar 27, 2026
# 🚀 release: 20260326

This release includes **91 commits**. Key updates are below.


- **Agent can now execute background tasks** — Agents can perform
long-running operations without blocking your conversation.
[#13289](#13289)
- **Better error messages** — Redesigned error UI across chat and image
generation with clearer explanations and recovery options.
[#13302](#13302)
- **Smoother topic switching** — No more full page reloads when
switching topics while an agent is responding.
[#13309](#13309)
- **Faster image uploads** — Large images are now automatically
compressed to 1920px before upload, reducing wait times.
[#13224](#13224)
- **Improved knowledge base** — Documents are now properly parsed before
chunking, improving retrieval accuracy.
[#13221](#13221)

### Bot Platform

- **WeChat Bot support** — You can now connect LobeChat to WeChat, in
addition to Discord.
[#13191](#13191)
- **Richer bot responses** — Bots now support custom markdown rendering
and context injection.
[#13294](#13294)
- **New bot commands** — Added `/new` to start fresh conversations and
`/stop` to halt generation.
[#13194](#13194)
- **Discord stability fixes** — Fixed thread creation issues and Redis
connection drops.
[#13228](#13228)
[#13205](#13205)

### Models & Providers

- **GLM-5** is now available in the LobeHub model list.
[#13189](#13189)
- **Coding Plan providers** — Added support for code planning assistant
providers. [#13203](#13203)
- **Tencent Hunyuan 3.0 ImageGen** — New image generation model from
Tencent. [#13166](#13166)
- **Gemini content handling** — Better handling when Gemini blocks
content due to safety filters.
[#13270](#13270)
- **Claude token limits fixed** — Corrected max window tokens for
Anthropic Claude models.
[#13206](#13206)

### Skills & Tools

- **Auto credential injection** — Skills can now automatically request
and use required credentials.
[#13124](#13124)
- **Smarter tool permissions** — Built-in tools skip confirmation for
safe paths like `/tmp`.
[#13232](#13232)
- **Model switcher improvements** — Quick access to provider settings
and visual highlight for default model.
[#13220](#13220)

### Memory

- **Bulk delete memories** — You can now delete all memory entries at
once. [#13161](#13161)
- **Per-agent memory control** — Memory injection now respects
individual agent settings.
[#13265](#13265)

### Desktop App

- **Gateway connection** — Desktop app can now connect to LobeHub
Gateway for enhanced features.
[#13234](#13234)
- **Connection status indicator** — See gateway connection status in the
titlebar. [#13260](#13260)
- **Settings persistence** — Gateway toggle state now persists across
app restarts. [#13300](#13300)

### CLI

- **API key authentication** — CLI now supports API key auth for
programmatic access.
[#13190](#13190)
- **Shell completion** — Tab completion for bash/zsh/fish shells.
[#13164](#13164)
- **Man pages** — Built-in manual pages for CLI commands.
[#13200](#13200)

### Security

- **XSS protection** — Sanitized search result image titles to prevent
script injection.
[#13303](#13303)
- **Workflow hardening** — Fixed potential shell injection in release
automation. [#13319](#13319)
- **Dependency update** — Updated nodemailer to address security
advisory. [#13326](#13326)

### Bug Fixes

- Fixed skill page not redirecting correctly after import.
[#13255](#13255)
[#13261](#13261)
- Fixed token counting in group chats.
[#13247](#13247)
- Fixed editor not resetting when switching to empty pages.
[#13229](#13229)
- Fixed manual tool toggle not working.
[#13218](#13218)
- Fixed Search1API response parsing.
[#13207](#13207)
[#13208](#13208)
- Fixed mobile topic menus rendering issues.
[#12477](#12477)
- Fixed history count calculation for accurate context.
[#13051](#13051)
- Added missing Turkish translations.
[#13196](#13196)

### Credits

Huge thanks to these contributors:

@bakiburakogun @hardy-one @Zhouguanyang @sxjeru @hezhijie0327 @arvinxx
@cy948 @CanisMinor @Innei @lijian @lobehubbot @neko @rdmclin2
@rivertwilight @tjx666
@cy948 cy948 deleted the feat/cli-api-key-auth branch April 1, 2026 07:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants