Skip to main content

Module feishu_auth

Module feishu_auth 

Source
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.secret is 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 (or session_secret) to turn the flow back on: strip any client-supplied x-userinfo, then read the feishu_session cookie (cookie mode: the session payload is sealed directly in the cookie; redis mode via session.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 required redirect_uri (the redirect port, distinct from the always-required auth_redirect_uri token-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_id else open_id else union_id else empty; ttl = session.cookie.lifetime, APISIX’s cookie_expires_in, default 86400) and 302-redirects (the redirect port) to the current URL with the code query parameter stripped, carrying the session Set-Cookie — the graph wires success straight to upstream.in, which replaces ctx.response.headers wholesale, 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 a 503 (SESSION_STORE_ERROR) on the error port, 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§

FeishuAuthPlugin
Authenticates requests by exchanging a Feishu authorization code for a user access token, then resolving that token to a Feishu user.
FeishuSession 🔒
Session-mode settings (present when session.secret is configured).
FeishuSessionData 🔒
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§

FeishuError 🔒
Outcome of resolving a Feishu code. Unauthorized is a deliberate denial (exits denied, 401); Upstream is a genuine callout failure (exits error).

Constants§

DEFAULT_TOKEN_URL 🔒
DEFAULT_USERINFO_URL 🔒

Functions§

attach_identity 🔒
Copies the resolved identity into context.message and optionally the X-Userinfo request 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_in seconds.
parse_userinfo 🔒
Parses Feishu’s userinfo response, returning data.data on code == 0.
redirect_target 🔒
Rebuilds the current request’s path+query with the code query 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. Mirrors authz_casdoor.rs::reconstruct_uri.
require_string 🔒
session_cookie_str 🔒
Reads a string field from nested session.cookie.<key>, falling back to the flat session_cookie_<key> form (used by the UI schema).
session_cookie_u64 🔒
Reads a u64 field from nested session.cookie.<key>, falling back to the flat session_cookie_<key> form (used by the UI schema).
session_secret 🔒
Reads the session secret from session_secret or nested session.secret.