Fix 403 for IAS tokens in spring-boot shopping sample - #117
Open
NiklasHerrmann21 wants to merge 3 commits into
Open
NiklasHerrmann21 wants to merge 3 commits into
NiklasHerrmann21 wants to merge 3 commits into
Conversation
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.
NiklasHerrmann21
force-pushed
the
fix/issue-99-403
branch
from
September 24, 2026 12:04
1b2b4e3 to
d6f93e0
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 plainJwtAuthenticationTokenwhose principal is a plainJwt.The cloud security library (
JavaSecurityContextHolderStrategy) only copies the token into itsSecurityContextwhen the principal is a SAPToken. 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 IASJwtinto a SAPAuthenticationToken(authorities derived from thegroupsclaim, following the CSSIL IAS sample pattern).SecurityConfiguration: wires the converter intooauth2ResourceServer().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 securitySecurityContext(like the production IAS decoder), so only the converter + strategy path can authorize the request. Fails with 403 without the fix, passes with it. TheJavaSecurityContextHolderStrategyis activated via anApplicationContextInitializerbecause theresourceserver-security-spring-boot-starter(which normally activates it via anEnvironmentPostProcessor) is excluded from the test classpath by the surefire configuration./healthroute (found while reviewing the upcoming README PR): the custom/healthendpoint fell through toanyRequest().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
(12 pre-existing + 6 new tests)