Travel expense Fiori apps return 401 error on OData calls after SSO enablement

We recently enabled SAML2 SSO for our travel management Fiori apps in S/4HANA 1809 cloud environment. Now users are getting 401 Unauthorized errors when submitting expense reports. The Fiori app loads fine, but any OData call to submit or approve expenses fails.

Checking the browser console shows:


POST /sap/opu/odata/sap/TRIP_APPROVE_SRV/TripApprovalSet 401
WWW-Authenticate: Bearer realm="SAP NetWeaver"
Response: {"error":{"code":"401","message":"Unauthorized"}}

The SSO works for initial login - users authenticate via our IdP successfully. Gateway trace shows the session is established, but subsequent OData service calls aren’t passing authentication. Is this related to SAML2 session handling or do we need additional OData authentication configuration for cloud deployment?

Check if your SAP Cloud Connector is properly configured to handle authentication forwarding. In cloud scenarios with SSO, the principal propagation settings matter. Navigate to Cloud Connector admin UI and verify the ‘Principal Type’ is set to match your SAML assertion format. Also check if the OData service endpoint is registered in the destination configuration with ‘Authentication: SAMLAssertion’ property.

After reviewing all the symptoms, here’s the complete solution addressing your Fiori OData authentication issue, SAML2 SSO session handling, and proper Gateway trace analysis:

Root Cause Analysis: Your issue stems from three configuration gaps in the cloud SSO setup:

  1. Fiori OData Authentication Flow: The destination configuration needs ‘OAuth2SAMLBearerAssertion’ instead of ‘PrincipalPropagation’ for cloud Fiori apps. This ensures the SAML assertion is exchanged for an OAuth bearer token that can be used for OData calls.

  2. SAML2 SSO Session Handling: Configure these critical parameters in your destination:


Authentication: OAuth2SAMLBearerAssertion
tokenServiceURL: https://<tenant>.authentication.sap.hana.ondemand.com/oauth/token
clientKey: <your-oauth-client>
authnContextClassRef: urn:oasis:names:tc:SAML:2.0:ac:classes:X509
  1. SAP Gateway Trace Analysis: In /IWFND/ERROR_LOG, filter by your user and timestamp. Look for entries showing ‘Authentication Method: OAuth2’. If you see ‘Anonymous’ or ‘Basic’, the bearer token isn’t reaching the gateway.

Complete Solution Steps:

A. Update Cloud Connector Configuration:

  • Set Principal Type to ‘None’ (let destination handle authentication)
  • Ensure cloud-to-onpremise mapping includes your backend system
  • Verify protocol is HTTPS for token exchange

B. Reconfigure BTP Destination:

  • Change Authentication from ‘PrincipalPropagation’ to ‘OAuth2SAMLBearerAssertion’
  • Add the tokenServiceURL for your BTP subaccount
  • Set nameIdFormat: ‘urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress’
  • Enable ‘Use default JDK truststore’

C. Update Fiori App xs-app.json:

Ensure your route forwards authentication:


{
  "source": "^/sap/opu/odata/(.*)",
  "authenticationType": "xsuaa",
  "destination": "S4HANA_BACKEND"
}

D. Gateway Service Configuration (SICF):

  • Transaction SICF → navigate to /sap/opu/odata/sap/TRIP_APPROVE_SRV
  • Handler List → Select service handler
  • Security Requirements → Enable ‘OAuth 2.0’ in addition to SSO
  • Save and activate

E. Verify OAuth Scope:

In BTP Cockpit → Security → OAuth Clients, ensure your client has the scope ‘uaa.resource’ and the OData service technical user has the required authorizations (transaction SU01, role SAP_GATEWAY_USER).

Testing & Validation:

  1. Clear browser cache and cookies completely
  2. Login via Fiori launchpad - you should see OAuth token exchange in browser network tab
  3. Submit expense report - OData POST should include ‘Authorization: Bearer ’ header
  4. Check /IWFND/ERROR_LOG - authentication method should show ‘OAuth2’ with your user principal
  5. If still failing, check /IWFND/GW_CLIENT → Test Service → use ‘OAuth’ authentication type

Gateway Trace Analysis Commands:


/IWFND/TRACES - Enable trace for user, run transaction, analyze
Look for: 'OAuth Token Validation: Success'
If you see 'Token expired' - check token lifetime in OAuth client config

The key insight is that cloud Fiori apps require OAuth bearer token flow, not direct cookie-based SSO. The SAML assertion authenticates the user initially, then gets exchanged for an OAuth token that travels with each OData request. This solves the cross-origin cookie issues and provides proper token-based authentication for microservices architecture.

After implementing these changes, your 401 errors should resolve and Gateway traces will show successful OAuth authentication for all OData calls.

Thanks for the quick response. I checked the Cloud Connector - principal propagation is set to ‘X509 Certificate’. Should this be ‘SAML Assertion’ instead? Our destination has Authentication set to ‘PrincipalPropagation’. The backend system is S/4HANA 1809 cloud edition, and the IdP is Azure AD. Would changing the principal type break existing integrations that are working?

The 401 on OData calls typically indicates the bearer token isn’t being forwarded properly. In your Gateway trace (/IWFND/ERROR_LOG), look for the authentication context of the failing requests. You should see whether the SAML assertion is being received and validated. Also check transaction SICF for the OData service node - verify that the service has ‘Security Requirements’ set to allow SSO logon tickets. Sometimes the service handler is configured to require basic auth even when SSO is enabled at the gateway level. Check the ‘Logon Data’ tab in SICF for your TRIP_APPROVE_SRV service path.

Update: checked the SICF service configuration - security settings looked correct with SSO enabled. However, I found that in /IWFND/ERROR_LOG the authentication context shows ‘Anonymous’ for the failed OData calls. The MYSAPSSO2 cookie is present in browser but seems like it’s not being sent with XHR requests. Could this be a CORS or SameSite cookie issue in the cloud environment?

I’ve seen this exact issue before with Fiori apps after SSO migration. The problem is usually session cookie scope. When SAML2 authenticates, it creates a session on the gateway, but the OData backend service might be on a different host/port combination in cloud deployments. Check your browser’s cookie storage - you should see MYSAPSSO2 cookies. If the cookie domain is too restrictive, subsequent OData calls won’t include it. In your Fiori launchpad configuration, verify that the ‘sap-system’ parameter in the app intent matches the destination system ID exactly. Also examine the response headers from the initial successful login - the Set-Cookie should have the correct domain and path attributes for your cloud landscape.