Commit graph

142 commits

Author SHA1 Message Date
XiaoSeS
b459b1a82c Merge PR 664 observability into big-main for validation
# Conflicts:
#	server/skillhub-app/src/main/java/com/iflytek/skillhub/exception/GlobalExceptionHandler.java
#	server/skillhub-app/src/main/java/com/iflytek/skillhub/filter/RequestLoggingFilter.java
#	server/skillhub-app/src/test/java/com/iflytek/skillhub/exception/GlobalExceptionHandlerTest.java
#	server/skillhub-app/src/test/java/com/iflytek/skillhub/filter/RequestLoggingFilterTest.java
2026-08-03 19:35:49 +08:00
XiaoSeS
41e0776b4c test(auth): isolate security context between tests
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-08-03 16:36:52 +08:00
XiaoSeS
aeec9bd0aa test(auth): cover DingTalk callback identity flow
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-08-03 13:06:21 +08:00
XiaoSeS
b42ffde628 feat(auth): add DingTalk OAuth2 adapter to unified identity core
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-08-03 12:46:22 +08:00
XiaoSeS
3c8b62a664 fix(auth): harden LDAP identity assertions
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-31 21:54:49 +08:00
XiaoSeS
a35bdce3c6 feat(auth): add LDAP and Active Directory adapter
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-31 19:13:32 +08:00
XiaoSeS
c6b18c6be6 Merge pull request #668 from feature/identity-account-merge
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-31 17:17:36 +08:00
XiaoSeS
fd49ad9170 feat(auth): add secure account merging
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-31 17:07:43 +08:00
XiaoSeS
7f5d5466ff chore(integration): stage observability boundary fixes
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-31 15:52:20 +08:00
XiaoSeS
e9a913e30b fix(observability): tighten tracing integration boundaries
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-31 15:51:31 +08:00
XiaoSeS
e7bde3e177 chore(integration): stage CAS adapter on big-main
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-31 12:05:54 +08:00
XiaoSeS
85fb05ff8f chore(integration): stage observability validation on big-main
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-31 12:02:45 +08:00
XiaoSeS
2c1bcf3b22 fix(auth): harden CAS identity link flow
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-31 12:01:38 +08:00
XiaoSeS
91fb155ef1 feat(observability): propagate async trace context
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-31 11:22:12 +08:00
XiaoSeS
07c2c9d750 chore(auth): sync CAS adapter with big-main
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-31 10:35:48 +08:00
XiaoSeS
74fab9734c feat(auth): add CAS 2.0 and 3.0 login adapter
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-31 09:31:25 +08:00
XiaoSeS
9557478dd8 feat(auth): add explicit identity link and safe unlink flow
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-31 07:02:17 +08:00
XiaoSeS
2100c259c2 test(auth): use sealed provider handle fixture
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-31 02:10:04 +08:00
XiaoSeS
09a74cad1e fix(auth): harden provider adapter boundaries
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-31 02:06:58 +08:00
XiaoSeS
c6fe19e2c8 chore(auth): merge big-main into provider registry
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-31 01:46:38 +08:00
XiaoSeS
4108107c21 fix(auth): close profile provisioning guardrails
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-31 00:26:30 +08:00
XiaoSeS
2c7466118e feat(auth): add unified provider registry
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-30 23:31:36 +08:00
XiaoSeS
dd0b9d15a4 test(auth): align profile sync validation
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-30 22:13:34 +08:00
XiaoSeS
b217339012 feat(auth): add profile sync and provisioning policies
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-30 22:02:24 +08:00
XiaoSeS
bbffb3281c fix(auth): report unconfigured legacy identity providers
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-30 21:13:06 +08:00
XiaoSeS
35cfb9f3ea feat(auth): add identity binding v2 expand
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-30 20:34:47 +08:00
XiaoSeS
ed170a8fef test(auth): strengthen identity guardrail isolation
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-30 19:34:59 +08:00
XiaoSeS
8bca180a67 fix(auth): preserve provider readiness status
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-30 18:15:03 +08:00
XiaoSeS
fa1f9685b0 fix(auth): inspect OAuth routes by request URI
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-30 18:15:03 +08:00
XiaoSeS
ffc9e514e0 fix(auth): select trusted provider constructor
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-30 18:15:03 +08:00
XiaoSeS
a95d639eb7 test(auth): use concrete OAuth registrations
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-30 18:15:03 +08:00
XiaoSeS
9ef272e32b fix(auth): reject stale provider authority recovery
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-30 18:15:03 +08:00
XiaoSeS
c71828f980 feat(auth): introduce unified identity core
Refs #640

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-30 18:15:03 +08:00
ylhu16
a13429a95e fix(auth): isolate unsafe account merge flow
Keep the legacy routes fail-closed, remove the unsafe orchestration service, replace the UI controls with a security notice, and define the acceptance contract for the future safe merge flow.

Closes #634

Parent: #628

Signed-off-by: ylhu16 <ylhu16@iflytek.com>
2026-07-30 15:57:43 +08:00
ylhu16
8b09a1330a chore(integration): stage issue #632 on big-main
Signed-off-by: ylhu16 <ylhu16@iflytek.com>

# Conflicts:
#	docs/02-domain-model.md
#	server/skillhub-auth/src/test/java/com/iflytek/skillhub/auth/identity/IdentityBindingServiceTest.java
2026-07-30 15:29:05 +08:00
ylhu16
fe1c6e718b fix(auth): harden approved account activation flow
Signed-off-by: ylhu16 <ylhu16@iflytek.com>
2026-07-30 15:20:12 +08:00
ylhu16
3f1eebd1e6 fix(auth): enforce trusted OAuth identity attributes
Signed-off-by: ylhu16 <ylhu16@iflytek.com>
2026-07-30 14:33:34 +08:00
XiaoSeS
19c3070291
Merge pull request #607 from gale-popai/fix/device-auth-redis-typing
fix(auth): read device-code state via ObjectMapper conversion, not cast
2026-07-29 03:37:25 +08:00
gale-popai
d977ea9dc4
fix(api): tell callers why a request was forbidden (#610)
* fix(api): tell callers why a request was forbidden

The scope filter already computes an exact reason ("Missing API token
scope: skill:delete", "API token cannot access endpoint: /x") and the
access-denied handler discarded it, returning a bare "Forbidden" for
every case: missing scope, endpoint closed to API tokens, and paths
that simply don't exist. Clients cannot tell those apart, so they
guess — the published CLI reports every 403 as "token may lack
required scope", which sent us debugging token scopes for an hour when
the real causes were a revoked token and a mistyped namespace path.

The reason now rides in the response via a new error.forbidden.detail
message (en + zh), and is logged alongside the exception type.

Signed-off-by: Gal Eyal <gal.e@popai.health>

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(api): safely expose API token denial reasons

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>

---------

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
2026-07-28 17:42:20 +08:00
Gal Eyal
8435ee1ab1 fix(auth): read device-code state via ObjectMapper conversion, not cast
The shared RedisTemplate uses GenericJackson2JsonRedisSerializer with
the application ObjectMapper, which embeds no type information, so
stored DeviceCodeData deserializes as a LinkedHashMap. The typed casts
in pollToken and authorizeDeviceCode then throw ClassCastException on
every call, making the whole device authorization flow unusable
(every poll returns 500).

Convert the raw value with ObjectMapper.convertValue instead of
casting; this reads both the current untyped map format and any typed
format, so no stored-data migration is needed. Adds bean setters to
DeviceCodeData for map conversion and regression tests that feed the
service exactly what Redis returns in production (untyped maps).

Fixes #604

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Gal Eyal <gal.e@popai.health>
2026-07-28 10:27:37 +03:00
dongmucat
665ee0499a feat(auth): add ISSUE-60 password capability field
Signed-off-by: dongmucat <1127093059@qq.com>
2026-06-22 12:40:01 +08:00
dongmucat
b56973fb80 fix(auth): fail closed invalid cli bearer tokens
Signed-off-by: dongmucat <1127093059@qq.com>
2026-06-17 11:35:16 +08:00
dongmucat
40d7de8462 fix(security): harden review findings
Signed-off-by: dongmucat <1127093059@qq.com>
2026-06-12 14:40:30 +08:00
dongmucat
4776550391
Merge pull request #498 from iflytek/feature/cloud-url-builtin-skills
feat(bootstrap): sync built-in skills from cloud manifest
2026-06-11 17:27:26 +08:00
dongmucat
0298823d06 fix(skill): remove namespace bundle backend residues
Signed-off-by: dongmucat <1127093059@qq.com>
2026-06-10 19:48:27 +08:00
dongmucat
973c336c82 fix(auth): protect builtin system account boundaries
Signed-off-by: dongmucat <1127093059@qq.com>
2026-06-08 18:01:20 +08:00
dongmucat
6bb89b1c89 fix(skill): address namespace bundle review findings
Signed-off-by: dongmucat <1127093059@qq.com>
2026-06-04 17:12:44 +08:00
wrj97
21456b9929
fix(auth): use SimpleUrlAuthenticationSuccessHandler for OAuth2 login (#266)
* fix(auth): use SimpleUrlAuthenticationSuccessHandler for OAuth2 login

Replace SavedRequestAwareAuthenticationSuccessHandler with
SimpleUrlAuthenticationSuccessHandler to prevent redirecting to
saved API requests after OAuth2 login.

Previously, when a user accessed a protected API endpoint (e.g.,
/api/web/skills) without authentication, Spring Security would save
that request. After OAuth2 login, the handler would redirect back to
the API endpoint instead of the dashboard.

Now the handler only uses:
- returnTo parameter from session (if present)
- default target URL (/dashboard) as fallback

* test(auth): add regression for OAuth2 success redirect; restore clearAuthenticationAttributes

Cover the no-returnTo + cached-API-request branch with HttpSessionRequestCache so
the original bug (post-login redirect resolving to /api/web/skills) cannot be
silently reintroduced. Also restore clearAuthenticationAttributes() in the
returnTo branch so it stays symmetric with the default branch (super clears it).

---------

Co-authored-by: xiose <huyanlin@nuaa.edu.cn>
2026-05-19 10:59:46 +08:00
dongmucat
d7d0790b28 fix(auth): close API token scope filter gap on /api/cli/ routes
ApiTokenAuthenticationFilter authenticates /api/cli/** Bearer tokens
but ApiTokenScopeFilter.shouldNotFilter() previously skipped them.
The result: API token requests on CLI routes were authenticated and
authorization-policy-checked, but scope enforcement never ran. Tokens
without skill:publish or skill:delete could call /publish, /publish/validate,
and DELETE despite the policy table requiring those scopes.

Add /api/cli/ to the scope filter's covered prefixes and a filter-level
test that confirms a token missing skill:publish is rejected on the new
validate endpoint. Update the existing CLI controller tests to grant
the appropriate SCOPE_* authorities to their api_token principals so
they continue to pass under enforced scopes.
2026-05-18 15:51:19 +08:00
dongmucat
943294b558 fix(publish): address Codex review findings for dry-run
Fix three blockers and one contract drift issue surfaced in code review:

1. API token policy: add skill:publish scope policy and authentication
   policy for /api/cli/v1/skills/*/publish/validate. Without these the
   AntPathMatcher pattern /publish would not cover /publish/validate,
   so Bearer-token requests would be rejected by the scope filter.

2. Warnings semantics: dry-run now treats warnings as making valid=false.
   The CLI publish flow uses confirmWarnings=false, so the real publish
   rejects any warnings; dry-run must mirror that to avoid false positives.

3. Visibility parameter: validate endpoint now accepts the same
   visibility multipart field as publish. The CLI forwards --visibility
   so invalid values are caught at dry-run time rather than at publish.

4. Schema drift: resolvedSlug and resolvedVersion are nullable in
   practice (returned as null when validation fails before resolution).
   Updated schema.d.ts to reflect string | null instead of optional string.

Tests added:
- RouteSecurityPolicyRegistryTest: validate endpoint scope check
- CliDryRunValidateTest: custom + invalid visibility cases
- publish-dry-run.test.ts: --visibility forwarded to server
2026-05-18 14:50:14 +08:00