feat: add feishu-auth plugin#13382
Open
AlinsRan wants to merge 11 commits into
Open
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new feishu-auth authentication plugin for APISIX that integrates Feishu/Lark OAuth 2.0 login, session-cookie caching, and optional upstream forwarding of authenticated user info.
Changes:
- Implements the
feishu-authplugin and registers it in default plugin lists. - Adds mock Feishu token/userinfo helpers and plugin tests.
- Adds English/Chinese documentation and navigation entries.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
apisix/plugins/feishu-auth.lua |
Implements Feishu OAuth token exchange, userinfo retrieval, session handling, and upstream header injection. |
apisix/cli/config.lua |
Adds feishu-auth to the built-in plugin list. |
conf/config.yaml.example |
Adds feishu-auth to the example enabled plugin list. |
t/admin/plugins.t |
Adds feishu-auth to the admin plugin-list expectations. |
t/lib/server.lua |
Adds mock Feishu token and userinfo endpoints for tests. |
t/plugin/feishu-auth.t |
Adds route setup and authentication/session behavior tests. |
docs/en/latest/plugins/feishu-auth.md |
Adds English plugin documentation. |
docs/zh/latest/plugins/feishu-auth.md |
Adds Chinese plugin documentation. |
docs/en/latest/config.json |
Adds the English docs navigation entry. |
docs/zh/latest/config.json |
Adds the Chinese docs navigation entry. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Add the feishu-auth plugin which authenticates requests using the Feishu (Lark) OAuth 2.0 authorization flow. Key features: - Exchanges authorization code for access token via Feishu OAuth API - Caches user info in an encrypted session cookie (resty.session v4) - Supports custom code extraction from query param or request header - Forwards user info to upstream via X-Userinfo header (Base64 JSON) - Supports session key rotation via secret_fallbacks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add feishu-auth to default plugin list in apisix/cli/config.lua - Add _M.feishu_token and _M.feishu_userinfo to t/lib/server.lua - Rewrite test to use /feishu/token and /feishu/userinfo paths instead of extra_init_by_lua dynamic assignment Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fix lint: wrap long lines in t/lib/server.lua mock functions - Add no_shuffle() to feishu-auth tests (stateful test ordering) - Add secret_fallbacks to encrypt_fields for consistent encryption - Clear client-supplied X-Userinfo header before authentication - Add canonical <head> links to EN/ZH plugin docs - Add encrypt_fields note to English docs (already in ZH docs) - Update ZH docs encrypt note to include secret_fallbacks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
888fd5a to
689cfa6
Compare
- Restore extra_init_by_lua mock approach (works in OSS as well)
- Restore /token and /userinfo mock paths to match EE test
- Restore log_level('debug') to match EE test
- Remove unnecessary _M.feishu_token/_M.feishu_userinfo from server.lua
- Keep no_shuffle() for correct stateful test ordering
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Verify that: 1. A session cookie created with secret-v1 is still accepted after rotating to secret-v2 with secret-v1 in secret_fallbacks. 2. After removing secret_fallbacks entirely, the old cookie is rejected and returns a 302 redirect. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Verify that a forged inbound X-Userinfo header cannot bypass authentication: a request with only a forged header is redirected (302), while a request with both a valid session cookie and a forged header succeeds only because of the cookie. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Verify secret_fallbacks elements are encrypted in etcd while the Admin API returns decrypted plaintext values. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assert secret_fallbacks[1] is present in the etcd payload before comparing, preventing false positives when the value is nil. Also use body2 directly from Admin API GET to avoid decoding issues. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add server.hello_echo handler and extend TEST 13: - Create a route with set_userinfo_header=false pointing to the echo handler - Verify that a forged X-Userinfo header is stripped before reaching upstream (upstream receives 'none', not the forged value) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Adds a new
feishu-authplugin that authenticates browser-based API requests using the Feishu (Lark) OAuth 2.0 authorization code flow.Problem
Teams using Feishu (Lark) as their enterprise collaboration platform need a way to protect internal APIs and developer portals so that only authenticated Feishu users can access them — without building a custom auth layer in each upstream service.
Solution
The
feishu-authplugin handles the complete OAuth 2.0 authorization code flow at the gateway level:redirect_uri(your app's OAuth entry point) with HTTP 302.code.access_token_url, then fetches user information fromuserinfo_url.feishu_session, powered byresty.sessionv4). Subsequent requests with a valid cookie skip the OAuth round-trip entirely.X-Userinfoheader.Configuration attributes
app_idapp_secretsecretauth_redirect_uriredirect_urisecret_fallbackscode_query"code"code_header"X-Feishu-Code"access_token_urluserinfo_urlset_userinfo_headertrueX-Userinfo.cookie_expires_in86400timeout6000ssl_verifytrueUsage examples
Prerequisites
https://your-domain.com/api/callback) to the app's Redirect URLs list.admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')Example 1: Basic setup
Protect a route so only authenticated Feishu users can access it. After login, the user's Feishu profile is forwarded to the upstream via
X-Userinfo.The first time a browser hits
/api/*:https://your-domain.com/oauth/feishu.https://your-domain.com/api/callback?code=<auth-code>.X-Userinfoheader with the Base64-encoded Feishu user profile:{ "open_id": "ou_8fc70d9ea27111749a71eb", "name": "Alice", "en_name": "Alice", "avatar_url": "https://...", "tenant_key": "1224d18e8d" }Subsequent requests with the session cookie bypass the OAuth flow entirely.
Example 2: Receive the auth code via HTTP header (non-browser clients)
For API clients that handle OAuth externally and pass the auth code as a header:
The client then authenticates by passing the code in the header:
curl http://your-gateway/api/resource -H "X-Feishu-Code: <auth-code>"Example 3: Session secret rotation with
secret_fallbacksRotate the session signing secret without invalidating existing user sessions.
Step 1 — promote the new secret, keep the old one as a fallback:
New sessions are signed with
my-session-secret-2. Existing sessions signed withmy-session-secret-1are still accepted and automatically re-signed with the new secret on next access.Step 2 — once old sessions have expired, remove the fallback:
Changes
apisix/plugins/feishu-auth.luaapisix/cli/config.luaconf/config.yaml.examplet/plugin/feishu-auth.tt/admin/plugins.tdocs/en/latest/plugins/feishu-auth.mddocs/zh/latest/plugins/feishu-auth.mddocs/en/latest/config.jsondocs/zh/latest/config.jsonRelated
cas-auth,authz-casdoor