Skip to main content
Version: 3.17

dingtalk-auth

Description#

The dingtalk-auth Plugin integrates DingTalk OAuth 2.0 authentication into APISIX routes. It validates a DingTalk authorization code, exchanges it for an access token, and retrieves user information from the DingTalk open platform. Verified user information is cached in a secure cookie session so that subsequent requests are not interrupted.

Attributes#

NameTypeRequiredDefaultDescription
app_keystringTrueDingTalk application App Key (client ID).
app_secretstringTrueDingTalk application App Secret (client secret). This field is stored encrypted.
secretstringTrueKey used to sign and encrypt the cookie session (8–32 characters). This field is stored encrypted.
redirect_uristringTrueURI to redirect the user to when no valid authorization code or session is present.
code_headerstringFalseX-DingTalk-CodeHTTP request header name from which to read the DingTalk authorization code.
code_querystringFalsecodeQuery parameter name from which to read the DingTalk authorization code.
access_token_urlstringFalsehttps://api.dingtalk.com/v1.0/oauth2/accessTokenDingTalk endpoint used to obtain an access token.
userinfo_urlstringFalsehttps://oapi.dingtalk.com/topapi/v2/user/getuserinfoDingTalk endpoint used to retrieve user information.
set_userinfo_headerbooleanFalsetrueWhen true, the verified user information is Base64-encoded and forwarded to the upstream in the X-Userinfo header.
timeoutintegerFalse6000Timeout in milliseconds for HTTP calls to DingTalk APIs.
ssl_verifybooleanFalsetrueWhether to verify the SSL certificate when calling DingTalk APIs.
cookie_expires_inintegerFalse86400Cookie session validity period in seconds.
secret_fallbacksarrayFalseList of fallback secrets used during key rotation (each 8–32 characters).
note

encrypt_fields = {"app_secret", "secret"} is defined in the schema, which means both fields are stored encrypted in etcd. See encrypted storage fields.

Authentication flow#

Client                     APISIX (dingtalk-auth)            DingTalk
│ │ │
│──── GET /resource ───────────►│ │
│ │ (no session, no code)
│◄─── 302 → redirect_uri ───────│ │
│ │ │
│──── GET /resource?code=xxx ──►│ │
│ │──── POST /accessToken ───────►│
│ │◄─── {"accessToken": "..."} ───│
│ │──── POST /getuserinfo ────────►│
│ │◄─── {"result": {...}} ─────────│
│ │ (save userinfo in session)
│◄─── 200 + Set-Cookie ─────────│ │
│ │ │
│──── GET /resource (Cookie) ──►│ │
│ │ (session valid, skip auth)
│◄─── 200 ──────────────────────│ │

Enable Plugin#

You can enable the Plugin on a specific Route as shown below:

note

You can fetch the admin_key from config.yaml and save to an environment variable with the following command:

admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')
curl http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: $admin_key" \
-X PUT \
-d '{
"methods": ["GET"],
"uri": "/anything/*",
"plugins": {
"dingtalk-auth": {
"app_key": "<your-app-key>",
"app_secret": "<your-app-secret>",
"secret": "<session-secret-key>",
"redirect_uri": "https://login.dingtalk.com/oauth2/auth?..."
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

Example usage#

Once you have enabled the Plugin, incoming requests to the Route are processed as follows:

  1. No session and no code: The user is redirected to redirect_uri (typically a DingTalk OAuth login page) with a 302 response.
  2. Authorization code present (in the code query parameter or X-DingTalk-Code header): The Plugin exchanges the code for an access token via access_token_url, then retrieves user information from userinfo_url. On success, the user information is stored in an encrypted cookie session and the original request proceeds.
  3. Valid session cookie: Subsequent requests carrying the session cookie bypass DingTalk API calls entirely and proceed directly to the upstream.

When set_userinfo_header is true (the default), the upstream receives the DingTalk user information in the X-Userinfo header as a Base64-encoded JSON object.

Custom code extraction#

By default the Plugin reads the authorization code from the code query parameter or the X-DingTalk-Code header. You can customize both names:

curl http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: $admin_key" \
-X PUT \
-d '{
"methods": ["GET"],
"uri": "/anything/*",
"plugins": {
"dingtalk-auth": {
"app_key": "<your-app-key>",
"app_secret": "<your-app-secret>",
"secret": "<session-secret-key>",
"redirect_uri": "https://login.dingtalk.com/oauth2/auth?...",
"code_query": "dt_code",
"code_header": "X-Custom-DT-Code"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

Key rotation#

Use secret_fallbacks to rotate the session signing key without invalidating existing sessions:

curl http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: $admin_key" \
-X PUT \
-d '{
"methods": ["GET"],
"uri": "/anything/*",
"plugins": {
"dingtalk-auth": {
"app_key": "<your-app-key>",
"app_secret": "<your-app-secret>",
"secret": "<new-secret-key>",
"secret_fallbacks": ["<old-secret-key>"],
"redirect_uri": "https://login.dingtalk.com/oauth2/auth?..."
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

Delete Plugin#

To remove the dingtalk-auth Plugin, delete the corresponding JSON configuration from the Plugin configuration. APISIX will automatically reload and you do not have to restart for this to take effect.

curl http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: $admin_key" \
-X PUT \
-d '{
"methods": ["GET"],
"uri": "/anything/*",
"plugins": {},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'