Expand description
Feishu / Lark authentication plugin (feishu-auth).
Validates a Feishu authorization code by exchanging it, through Feishu’s
OAuth v2 token endpoint, for a user access token, then calls Feishu’s
userinfo endpoint to resolve the calling user’s identity and attaches it to
the request. A missing code, or a code/token Feishu actively rejects, is
denied with a 401 on the denied port; a Feishu callout that fails
outright (network error, non-200, unparseable body) is a genuine
infrastructure failure and stays on the error port.
§Ported subset / deviations from APISIX
APISIX’s feishu-auth is a session plugin: on the first request it
reads a code, exchanges it for a user access token and userinfo, then
stores both in an encrypted feishu_session cookie so later requests skip
the callouts, and it 302-redirects to redirect_uri when no code and no
session are present. That session machinery is now restored on an opt-in
basis, sharing the same cookie /
server-store primitives as
cas-auth/openid-connect/authz-casdoor/dingtalk-auth:
- Stateless (default) — when no
session.secretis configured the node behaves exactly as before: every request must carry a code, which is exchanged and validated against Feishu on each request. No cookie is read or set. - Session (opt-in) — set
session.secret(orsession_secret) to turn the flow back on: strip any client-suppliedx-userinfo, then read thefeishu_sessioncookie (cookie mode: the session payload is sealed directly in the cookie; redis mode viasession.storage: redis+session.store: <name>: the cookie carries a bare id, the sealed payload lives server-side). A valid session attaches identity straight from the stored userinfo — no Feishu callout. An undecodable payload (corrupt/stale format) is destroyed and treated as no session rather than failing the request. No session and no code 302-redirects to the requiredredirect_uri(theredirectport, distinct from the always-requiredauth_redirect_uritoken-exchange field below). A code present runs the existing token+userinfo callouts unchanged, then establishes a new session (payload = userinfo JSON plus the exchanged access token and its expiry; subject =user_idelseopen_idelseunion_idelse empty; ttl =session.cookie.lifetime, APISIX’scookie_expires_in, default86400) and 302-redirects (theredirectport) to the current URL with thecodequery parameter stripped, carrying the sessionSet-Cookie— the graph wiressuccessstraight toupstream.in, which replacesctx.response.headerswholesale, so a Set-Cookie attached on that path would never reach the browser. The browser’s follow-up request then hits the session-read fast path above and attaches identity. A session-store outage is a503(SESSION_STORE_ERROR) on theerrorport, never a silent re-login.
Remaining deviation: secret_fallbacks (APISIX’s multi-secret key
rotation) is not supported — the sealer is a single session.secret,
same as every other session plugin in this codebase. auth_redirect_uri
is retained (and still always required) because it is part of the
authorization_code token-exchange body, not the interactive redirect.
Structs§
- Feishu
Auth Plugin - Authenticates requests by exchanging a Feishu authorization code for a user access token, then resolving that token to a Feishu user.
- Feishu
Session 🔒 - Session-mode settings (present when
session.secretis configured). - Feishu
Session 🔒Data - Session payload: the resolved userinfo plus the exchanged access token and its expiry, cached per APISIX’s original so a future re-exchange (after a userinfo failure) can reuse a still-valid token.
Enums§
- Feishu
Error 🔒 - Outcome of resolving a Feishu code.
Unauthorizedis a deliberate denial (exitsdenied,401);Upstreamis a genuine callout failure (exitserror).
Constants§
Functions§
- attach_
identity 🔒 - Copies the resolved identity into
context.messageand optionally theX-Userinforequest header. - now_
unix 🔒 - parse_
access_ 🔒token - Parses the user access token from Feishu’s v2 token response, returning
the token and (when present) its
expires_inseconds. - parse_
userinfo 🔒 - Parses Feishu’s userinfo response, returning
data.dataoncode == 0. - redirect_
target 🔒 - Rebuilds the current request’s path+query with the
codequery parameter stripped, for the post-establish redirect (so the browser’s follow-up GET doesn’t resubmit the one-time code). If the code was read from the header rather than the query string, there is nothing to strip and the query comes back unchanged. Mirrorsauthz_casdoor.rs::reconstruct_uri. - require_
string 🔒 - session_
cookie_ 🔒str - Reads a string field from nested
session.cookie.<key>, falling back to the flatsession_cookie_<key>form (used by the UI schema). - session_
cookie_ 🔒u64 - Reads a u64 field from nested
session.cookie.<key>, falling back to the flatsession_cookie_<key>form (used by the UI schema). - session_
secret 🔒 - Reads the session secret from
session_secretor nestedsession.secret.