Skip to main content

Module dingtalk_auth

Module dingtalk_auth 

Source
Expand description

DingTalk authentication plugin (dingtalk-auth).

Validates a DingTalk authorization code by exchanging it, through DingTalk’s OAuth API, for the calling user’s identity, then attaches that identity to the request for downstream nodes. A request whose code is missing or that DingTalk actively rejects is denied with a 401 on the denied port; a DingTalk 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 dingtalk-auth is a session plugin: on the first request it reads a code, calls DingTalk, then stores the resolved userinfo in an encrypted dingtalk_session cookie so later requests skip the callout, 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:

  • Stateless (default) — when no session.secret is configured the node behaves exactly as before: every request must carry a code, which is validated against DingTalk 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 dingtalk_session cookie (cookie mode: the userinfo JSON is sealed directly in the cookie; redis mode via session.storage: redis + session.store: <name>: the cookie carries a bare id, the sealed userinfo lives server-side). A valid session attaches identity straight from the stored payload — no DingTalk 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). A code present runs the existing token+userinfo callouts unchanged, then establishes a new session (payload = the userinfo result JSON; subject = userid else unionid 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. The app-level access token is still cached in-process (7000s TTL, matching APISIX’s lrucache).

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.

Structs§

DingtalkAuthPlugin
Authenticates requests by resolving a DingTalk authorization code to a DingTalk user via the OAuth accessToken + getuserinfo APIs.
DingtalkSession 🔒
Session-mode settings (present when session.secret is configured).

Enums§

DingtalkError 🔒
Outcome of resolving a DingTalk code into userinfo. Unauthorized is a deliberate denial (exits denied, 401); Upstream is a genuine callout failure (exits error).

Constants§

ACCESS_TOKEN_TTL 🔒
DingTalk access tokens live 7200s; cache slightly shorter to avoid using a token that expires mid-flight (matches APISIX’s cache TTL).
DEFAULT_TOKEN_URL 🔒
DEFAULT_USERINFO_URL 🔒

Functions§

append_query 🔒
Appends key=value to url, choosing ? or & as needed.
attach_identity 🔒
Copies the resolved identity into context.message and optionally the X-Userinfo request header.
parse_access_token 🔒
Parses the accessToken from DingTalk’s token-endpoint response.
parse_userinfo 🔒
Parses DingTalk’s getuserinfo response, returning the result object on errcode == 0 and an DingtalkError::Unauthorized otherwise.
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 🔒
Extracts a required string config key.
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.
urlencode 🔒
Minimal percent-encoding for query values (access tokens are URL-safe-ish but may contain + / =).