Summary
During a recent production deployment for a client using SAP CAP (Cloud Application Programming Model) on BTP Cloud Foundry, we encountered a critical integration gap. While the application successfully authenticated users via Identity Authentication Service (IAS) through OpenID Connect (OIDC), the application layer was unable to retrieve extended user attributes such as Login Name or Custom Attributes. The application was restricted to the standard scopes provided by the default JWT, leading to failures in business logic that required identity-based authorization and personalization.
Root Cause
The failure stems from a misunderstanding of how Identity Tokens (ID Tokens) and Access Tokens interact within the OIDC flow in a multi-tenant or federated environment.
- Default Scope Limitation: By default, the OIDC handshake only requests standard scopes (like
openid,profile, andemail). Custom attributes in IAS are not included in these basic scopes. - Token Mapping Gap: Even if attributes exist in the IAS user store, the SAP BTP XSUAA service acts as a proxy. If the mapping between IAS claims and XSUAA claims is not explicitly configured, the downstream CAP application receives a “stripped” JWT.
- Identity Provider (IdP) Configuration: The IAS must be configured to release specific attributes in the assertion, and the BTP subaccount must be configured to trust those specific claims.
Why This Happens in Real Systems
In complex enterprise architectures, identity is rarely a single point of truth.
- Protocol Translation: Systems often translate between SAML (common in legacy IdPs) and OIDC/OAuth2 (common in modern cloud apps). During this translation, metadata is often lost if not explicitly mapped.
- Security Hardening: Most identity providers follow the Principle of Least Privilege. They will not broadcast sensitive or custom user data unless the client application explicitly requests it via Scopes and the administrator grants permission.
- Abstraction Layers: Developers often treat the
req.userobject in CAP as a “magic” object, forgetting that it is merely a decoded representation of a cryptographically signed string (the JWT) passed from a distant server.
Real-World Impact
- Broken Business Logic: Applications that rely on
user.loginNamefor workflow routing or audit logging fail silently or throwundefinederrors. - Degraded User Experience: Personalized dashboards fail to load because the application cannot retrieve the user’s preferred language or department from the IAS attributes.
- Security Vulnerabilities: If an application attempts to perform manual lookups in a database to “supplement” identity data instead of using the signed JWT, it opens the door to identity spoofing or race conditions.
Example or Code
To solve this, you must first ensure the xs-security.json is configured to handle the necessary scopes, and then access the claims within the CAP service implementation.
srv.on('READ', 'MyEntity', async (req) => {
const user = req.user;
// Standard OIDC claims are usually available here
const email = user.id;
// Custom attributes are found in the 'custom' or specific claim keys
// provided by the XSUAA/IAS mapping
const loginName = user.custom?.['login_name'] || user.custom?.['loginName'];
const customAttr = user.custom?.['custom_attribute_key'];
if (!loginName) {
console.error('Missing critical identity attribute: loginName');
return req.reject(403, 'User identity incomplete');
}
return SELECT.from('MyEntity').where({ owner: loginName });
});
How Senior Engineers Fix It
A senior engineer looks beyond the code and addresses the Infrastructure-as-Code (IaC) and Identity Configuration:
- IAS Configuration: Access the IAS Administration Console and ensure the Attribute Mapping is configured so that the desired attributes are sent in the OIDC assertion.
- XSUAA Scopes: Update the
xs-security.jsonfile to include the necessary scopes if the custom attributes are used for authorization. - JWT Inspection: Use tools like
jwt.ioor intercept the network traffic to inspect the raw JWT. If the attribute isn’t in the raw token, no amount of Node.js code will fix it. - Claims Transformation: Use the BTP Connectivity/Destination service or specific XSUAA configurations to map incoming IAS claims to specific JSON keys that the CAP application expects.
Why Juniors Miss It
- Focusing on the Wrong Layer: Juniors often spend hours trying to write complex
if/elsestatements or database queries to “find” the user, rather than realizing the data is missing from the Authentication Token itself. - Assuming “Authenticated” means “Authorized”: They assume that because
req.useris not null, all user data is automatically available. - Ignoring the Manifest: They overlook the
xs-security.jsonand the BTP Cockpit configurations, treating the application as an isolated unit rather than part of a distributed identity ecosystem.