skillhub/web
XiaoSeS 96f244b416 feat(auth): add DingTalk as a public login provider
Adds DingTalk (钉钉) as a public sign-in option: it authenticates a SkillHub
platform account and nothing more. No Organization membership, no directory
sync, no Namespace grants.

DingTalk deviates from standard OAuth at all three stages, one strategy each:

- authorize: its endpoint wants scope=openid, but declaring that scope in
  configuration makes Spring treat the registration as OIDC and attach a
  nonce, which DingTalk rejects. The scope is added by
  DingTalkAuthorizationRequestCustomizer instead, keeping this a plain OAuth2
  client. A test asserts the scope is present and the nonce is not.
- token: credentials go in a JSON body rather than a form, handled by
  DingTalkTokenResponseClient.
- userinfo: the token travels in x-acs-dingtalk-access-token rather than
  Authorization: Bearer.

Subject and email semantics, which decide whether a login can reach an
existing account:

- unionId is the only accepted subject. DingTalk also returns openId and
  userId, but they must not act as fallbacks: openId is scoped per app and
  userId per organization, so a login falling back to either would bind a
  different identity than a later login carrying unionId, splitting one
  person across two platform accounts.
- A blank or missing unionId fails the login.
- emailVerified is always false. DingTalk returns the email an organization
  admin recorded without attesting the user controls it.

The userinfo service only fetches attributes; account matching, provisioning
and session creation stay with the unified identity core. The reference
implementation called OAuthLoginFlowService.authenticate() from inside
loadUser, which decided the account before the core's gate ran.

Operational bounds match the Feishu adapter: connect and read timeouts, a
64 KB response cap, error descriptions and logs carrying only the exception
class or provider error code, and no logging in the claims extractor.
Unused PII is dropped rather than carried into the principal -- notably
mobile and stateCode.

Adds ProviderStrategyWiringTest, which loads the real application context.
The unit tests call package-visible constructors and so cannot catch Spring
wiring faults; a component with two constructors and no @Autowired marker
unit-tests green and then fails at startup. That happened during this work.

Adapted from the implementation in #467 by @konglong87, re-extracted onto
current main with the subject, structure and bounds changes above.

Part of R1-A2 (public Provider adapters) per
openspec/changes/enterprise-identity-platform/rollout-plan.md.

Co-authored-by: konglong87 <konglong87@users.noreply.github.com>
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-09-21 15:15:41 +08:00
..
docker-entrypoint.d fix(skill): harden SkillHub CLI guide bootstrap (#842) 2026-09-09 20:25:50 +08:00
e2e feat(frontend): render mermaid markdown diagrams (#892) 2026-09-21 14:08:41 +08:00
public feat(auth): add DingTalk as a public login provider 2026-09-21 15:15:41 +08:00
src fix(suite): support bundle import over plain HTTP (#890) 2026-09-21 14:14:23 +08:00
.browserslistrc fix(web): restore compatibility with Chromium 83 (Debian 10) 2026-05-09 13:55:50 +08:00
.dockerignore feat(ops): improve Dockerfile caching, add dockerignore, docker profile, Makefile help 2026-03-12 17:50:34 +08:00
.eslintrc.cjs refactor: address code review findings from 2026-03-22 2026-03-23 13:48:23 +08:00
base-path-config.test.ts feat(skill): add first-party SkillHub CLI guide 2026-09-09 09:24:21 +08:00
base-path-config.ts feat(skill): add first-party SkillHub CLI guide 2026-09-09 09:24:21 +08:00
components.json feat(web): implement login page, dashboard, and API token management 2026-03-12 00:13:50 +08:00
Dockerfile feat: add initial RISC-V image support (#725) 2026-08-24 16:37:34 +08:00
index.html fix(web): self-host Inter and JetBrains Mono fonts (#753) 2026-08-25 13:49:08 +08:00
LANDING_PAGE_REDESIGN.md feat(web): redesign homepage with modern landing page 2026-03-12 22:27:58 +08:00
nginx.conf.template fix(skill): harden SkillHub CLI guide bootstrap (#842) 2026-09-09 20:25:50 +08:00
package.json feat(frontend): render mermaid markdown diagrams (#892) 2026-09-21 14:08:41 +08:00
playwright.config.ts fix(skill): harden SkillHub CLI guide bootstrap (#842) 2026-09-09 20:25:50 +08:00
playwright.smoke.config.ts test(e2e,ci): migrate web e2e to real API and add PR e2e workflow (#198) 2026-04-01 14:41:23 +08:00
pnpm-lock.yaml feat(frontend): render mermaid markdown diagrams (#892) 2026-09-21 14:08:41 +08:00
postcss.config.js feat(web): implement login page, dashboard, and API token management 2026-03-12 00:13:50 +08:00
PREVIEW.md docs: add landing page preview guide 2026-03-12 22:28:31 +08:00
runtime-config.js.template Add extensible auth compatibility layer for private SSO 2026-03-13 18:00:22 +08:00
tailwind.config.ts feat(web): unify landing, dashboard, and paginated lists (#825) 2026-09-09 18:31:18 +08:00
TODO.md fix(web): fix i18n language switching and add translations 2026-03-13 13:42:57 +08:00
tsconfig.json fix(web): isolate ambient types (ISSUE-92) 2026-07-29 10:44:49 +08:00
vite.config.ts feat(auth): add Feishu as a public login provider (R1-A2) (#877) 2026-09-21 14:39:22 +08:00