Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import com.sap.cloud.security.ams.api.*;
import com.sap.cloud.security.ams.cap.api.CdsAuthorizations;
import com.sap.cloud.security.ams.core.HybridAuthorizationsProvider;
import com.sap.cloud.security.token.SecurityContext;
import com.sap.cloud.security.token.XsuaaTokenExtension;
import jakarta.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
Expand Down Expand Up @@ -42,13 +45,25 @@ public class HybridAuthorizationsTestConfiguration {
private static final Logger LOG = LoggerFactory.getLogger(HybridAuthorizationsTestConfiguration.class);
private static final String XSAPPNAME = "bookshop";

/**
* Replaces the auto-configured {@code DefaultXsuaaTokenExtension} with a pass-through that
* returns the {@link com.sap.cloud.security.token.Token} previously placed by
* {@code SecurityContext.setXsuaaToken(...)} as-is without cache invalidation logic.
*/
@PostConstruct
void installPassThroughXsuaaTokenExtension() {
XsuaaTokenExtension passThrough = token -> token;
SecurityContext.registerXsuaaTokenExtension(passThrough);
LOG.info("Registered pass-through XsuaaTokenExtension; production DefaultXsuaaTokenExtension will not be used.");
}

@Bean
@Primary
public AuthorizationsProvider<CdsAuthorizations> hybridCdsAuthorizationsProvider(
AuthorizationManagementService ams,
@Value("${ams.combined-authorizations-enabled:false}") boolean combinedAuthorizationsEnabled) {

LOG.info("Creating HybridAuthorizationsProvider with combinedAuthorizationsEnabled={}",
LOG.info("Creating HybridAuthorizationsProvider with combinedAuthorizationsEnabled={}",
combinedAuthorizationsEnabled);

ScopeMapper scopeMapper = ScopeMapper.ofFunctionMultiple(scope -> switch (scope) {
Expand All @@ -61,10 +76,10 @@ public AuthorizationsProvider<CdsAuthorizations> hybridCdsAuthorizationsProvider
.withXsAppName(XSAPPNAME)
.withCombinedAuthorizationsEnabled(combinedAuthorizationsEnabled);
}

/**
* Provides mock policy assignments for IAS users.
*
*
* <p>This bean is used when combined authorizations is enabled to simulate
* policy assignments that would normally come from the AMS service.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,21 @@ public class TestSecurityContextHelper {
*/
public static final String SERVICE_BINDING_ROOT = "src/test/resources/customization/service-bindings";

/**
* Token TTL used for mocked JWTs in tests.
*
* <p>Set to 24 hours rather than the typical 1 hour because of a latent timezone bug in
* {@code com.sap.cloud.security:java-api}'s {@code Token.isExpired()} implementation, which
* compares the parsed {@code exp} claim against {@code LocalDateTime.now().toInstant(ZoneOffset.UTC)}.
* On a JVM whose default zone is UTC+N (e.g. CEST = UTC+2), that expression is N hours ahead
* of the real {@code Instant.now()}, so a token minted with a TTL shorter than N is reported
* as already expired the moment it's created.
*
* <p>Using 24h is safely larger than the maximum civil offset on Earth (+14h, Kiribati) and
* therefore makes these tests robust against the bug regardless of the JVM's default zone.
*/
private static final long TOKEN_TTL_SECONDS = 24L * 60 * 60;

private final CdsRuntime cdsRuntime;

public TestSecurityContextHelper(CdsRuntime cdsRuntime) {
Expand Down Expand Up @@ -263,8 +278,8 @@ public static String createXsuaaJwt(String userName, String... scopes) {
""",
userName,
scopesJson,
System.currentTimeMillis() / 1000 + 3600, // expires in 1 hour
System.currentTimeMillis() / 1000, // issued now
System.currentTimeMillis() / 1000 + TOKEN_TTL_SECONDS, // exp
System.currentTimeMillis() / 1000, // iat
userName);

return encodeJwt(payload);
Expand Down Expand Up @@ -306,13 +321,13 @@ public static String createIasJwt(String userName, String scimId) {
"email": "%s@example.com"
}
""",
scimId, // sub (same as scim_id for user tokens)
TEST_TENANT_ID, // app_tid (tenant ID)
scimId, // scim_id (user identifier for policy lookup)
scimId, // user_uuid
System.currentTimeMillis() / 1000 + 3600, // exp (expires in 1 hour)
System.currentTimeMillis() / 1000, // iat (issued now)
userName); // email
scimId, // sub (same as scim_id for user tokens)
TEST_TENANT_ID, // app_tid (tenant ID)
scimId, // scim_id (user identifier for policy lookup)
scimId, // user_uuid
System.currentTimeMillis() / 1000 + TOKEN_TTL_SECONDS, // exp
System.currentTimeMillis() / 1000, // iat
userName); // email

return encodeJwt(payload);
}
Expand Down
Loading