Skip to content

Fix 403 for IAS tokens in spring-boot shopping sample - #117

Open
NiklasHerrmann21 wants to merge 3 commits into
mainfrom
fix/issue-99-403
Open

NiklasHerrmann21 wants to merge 3 commits into
mainfrom
fix/issue-99-403

Conversation

@NiklasHerrmann21

@NiklasHerrmann21 NiklasHerrmann21 commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes #99: GET /products (and other protected endpoints) always returned 403 when called with a valid IAS token in a deployed environment.

Root cause

The resource server was configured with the default Spring Security JWT converter (Customizer.withDefaults()), which produces a plain JwtAuthenticationToken whose principal is a plain Jwt.

The cloud security library (JavaSecurityContextHolderStrategy) only copies the token into its SecurityContext when the principal is a SAP Token. Without that, the AMS library cannot derive the caller principal (SciAuthorizationsProvider: No principal provided. Using empty authorizations.) and every privilege check evaluates to denied.

Changes

  • IasJwtAuthenticationConverter (new): converts the validated IAS Jwt into a SAP AuthenticationToken (authorities derived from the groups claim, following the CSSIL IAS sample pattern).
  • SecurityConfiguration: wires the converter into oauth2ResourceServer().jwt(); corrected the stale Javadoc.
  • IasJwtAuthenticationConverterTest (new): unit tests proving the converter establishes the token as an AMS principal.
  • IasJwtFlowTest (new): end-to-end regression tests for the production token flow — the test decoder intentionally does not populate the cloud security SecurityContext (like the production IAS decoder), so only the converter + strategy path can authorize the request. Fails with 403 without the fix, passes with it. The JavaSecurityContextHolderStrategy is activated via an ApplicationContextInitializer because the resourceserver-security-spring-boot-starter (which normally activates it via an EnvironmentPostProcessor) is excluded from the test classpath by the surefire configuration.
  • /health route (found while reviewing the upcoming README PR): the custom /health endpoint fell through to anyRequest().denyAll() and was unreachable (401/403) although it is documented as a public health check. It is now explicitly permitted, in line with /actuator/health.

Verification

mvn clean test
Tests run: 18, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS

(12 pre-existing + 6 new tests)

The default Spring Security JwtAuthenticationConverter produces a plain
JwtAuthenticationToken whose principal is a Jwt. The cloud security
library only copies the token into its SecurityContext when the
principal is a SAP Token, so the AMS principal was never established
and every privilege check was denied with HTTP 403.

Add an IasJwtAuthenticationConverter that converts the validated IAS
Jwt into a SAP AuthenticationToken and wire it into the resource
server configuration. Add unit tests for the converter and an
end-to-end regression test for the production token flow.

Fixes #99
The custom /health endpoint fell through to anyRequest().denyAll() and
was unreachable (401/403), although the sample documents it as a public
health check. Permit it explicitly, in line with /actuator/health.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ams-spring-boot-shopping: /products always returns 403

1 participant