Skip to content

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

Description

@arnoweiss

Summary

In ams-spring-boot-shopping, calling GET /products (and GET /privileges) with a valid IAS token is rejected with HTTP 403, even though the app is bound, token is valid, policies are pushed.

Steps to reproduce

  1. Deploy the sample as single-tenant IAS app on CF. Bind the app to a IAS app, create app2app trust, create client credentials for the consumer app.
  2. Obtain a valid IAS token for the consumer app. Make sure to hit the right dependency. Should look like [1]
  3. curl -H "Authorization: Bearer <token>" https://<app>/products

Expected: 200 with the product list (the GetProducts API maps to internal.GetProductsshopping.ReadProductsGRANT read ON products).
Actual: 403.

Root cause

The request is authenticated but no AMS principal is ever established, so the AMS authorization check runs against empty authorizations and denies.

SecurityConfiguration#filterChain wires the resource server with:

With the default converter, Spring produces a plain org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken whose principal is a plain org.springframework.security.oauth2.jwt.Jwt, not a SAP com.sap.cloud.security.spring.token.authentication.AuthenticationToken.

The cloud-security JavaSecurityContextHolderStrategy only copies the SAP Token into com.sap.cloud.security.token.SecurityContext when the Spring Authentication's principal is a SAP Token. Because it isn't, SecurityContext.getToken() stays null, so com.sap.cloud.security.ams.api.Principal.fromSecurityContext() returns null, and SciAuthorizationsProvider short-circuits to empty authorizations. Every @CheckPrivilege then evaluates granted=false → 403. Logs here [2].

Direction for a fix

The app needs a jwtAuthenticationConverter that turns the validated IAS Jwt into a SAP AuthenticationToken, so the AMS principal is established. Worked for me afterwards.

[1]

{
  "ias_apis": [
    "GetProducts"
  ],
  "sub": "consumer",
  "aud": "ams-secured-app",
  "app_tid": "app-tid",
  "sap_id_type": "app",
  "azp": "consumer",
  "iss": "https://iasid.ondemand.com",
  "azpacr": "1",
  "exp": 1787302610,
  "iat": 1787299010,
  "jti": "096f3ac5-adf2-4516-845b-dd295afbfab0"
}

[2]

IasJwtDecoder            : The token of service IAS was successfully validated.
BearerTokenAuthenticationFilter : Set SecurityContextHolder to JwtAuthenticationToken
    [Principal=org.springframework.security.oauth2.jwt.Jwt@..., Granted Authorities=[]]
SciAuthorizationsProvider : No principal provided. Using empty authorizations.
...
horizationManagerBeforeMethodInterceptor : Failed to authorize ... ProductsService.getProducts()
    ... result AuthorizationDecision [granted=false]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions