* fix(web): refresh API proxy DNS after backend redeploy
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
* test(web): stabilize DNS replacement coverage
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
* test(web): allow early resolver refresh after DNS change
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
* test(web): use dynamic ports for nginx smoke
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
---------
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
The DingTalk login could not complete. Adding openid to the authorization
request's scope set avoided the nonce at the authorize step but broke the
callback: OAuth2LoginAuthenticationProvider.authenticate returns null when
getScopes() contains "openid", handing the exchange to
OidcAuthorizationCodeAuthenticationProvider, which fails with
invalid_id_token because DingTalk returns no id_token. Neither the token
client nor the user service was ever reached. spring-security-oauth2-jose is
on the runtime classpath, so that provider is registered.
The scope now goes onto the outgoing authorization URI directly, leaving
getScopes() empty. Both openid-keyed mechanisms are then avoided: no nonce,
because the registration still declares no scope in configuration, and no
OIDC routing, because the request carries no openid scope.
The previous test asserted getScopes() contains "openid" -- the exact state
that breaks the callback -- so it locked the bug in. It now asserts the
inverse, and restoring the old implementation makes it fail.
Also switches the registration from client-authentication-method: none to
client-secret-post. "none" made Spring apply PKCE and emit a code_challenge
that DingTalkTokenResponseClient cannot answer, since its JSON token request
sends no code_verifier. It was also semantically wrong: DingTalk is a
confidential client that carries its secret in the request body.
Verified against a local staging instance: the authorization URI now carries
scope=openid with no nonce and no code_challenge, and a callback with a fake
code fails in the token exchange with no OIDC provider involvement in the
logs.
Drops SUBJECT_ATTRIBUTE, which lost its last reference when the user service
stopped pre-resolving the subject.
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
Two gaps from reviewing this batch against the Feishu adapter it mirrors.
The token exchange had no response size limit while the userinfo call did,
so the same hostile or misconfigured endpoint was bounded on one call and
unbounded on the other. Adds the same 64 KB cap through a RestTemplate
interceptor, which keeps the existing tests working against an injected
template. buildRestTemplate becomes package-visible so one test can exercise
the production template, cap included; removing the interceptor makes that
test fail.
A missing unionId threw without logging, unlike the equivalent Feishu
branch. This is a reachable failure -- DingTalk omits unionId for some app
configurations -- and an operator seeing every login rejected needs to know
why. Logs the claim name only, which says nothing about the user.
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
Adds the DingTalk credentials to every path that actually delivers
configuration: compose.release.yml (which has no env_file, so variables must
be listed explicitly), the Helm secret template and values, the k8s
deployment and its secret example. validate-release-config.sh gains DingTalk
in its provider loop, so a half-configured pair is rejected the same way.
Documents the three-stage strategy contract in the authentication design: a
table mapping each deviation -- authorize parameters, token exchange,
userinfo loading -- to its interface and current implementations, plus the
rule that a provider must never make account decisions itself.
Deployment notes and both FAQs now cover DingTalk, including the shared trap
with Feishu: their emails are admin-recorded and never confirmed, so
emailVerified is always false and an EMAIL_DOMAIN access policy would reject
every login through either provider.
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>