AWS Builder Center
SAP identity propagation with Entra ID on-behalf-of | Agentic ERP Quickstart

SAP identity propagation with Entra ID on-behalf-of | Agentic ERP Quickstart

Make SAP record the signed-in person, not a shared service account. The two Entra app registrations, the claim you must not map, and how to prove it in STAD.

Series: Building Production-Grade ERP Agents on AWS (18 articles)

  1. …
  2. 6
    SAP identity propagation with Entra ID on-behalf-of | Agentic ERP Quickstart This article
Solutions Architect I @ AWS | Applied AI for SAP/ERP

SAP identity propagation with Entra ID on-behalf-of | Agentic ERP Quickstart

When an agent reads or writes SAP for someone, SAP normally records a service account, and every action the agent has ever taken collapses into one name in the audit log. On-behalf-of token exchange breaks that collapse: the person signs in once with Microsoft Entra, and SAP executes the request as their own SU01 user, with no second SAP login prompt. It is the most configuration-heavy path in this series, and it is the only one that lets you answer "who did this" from SAP's own records rather than from an application log you wrote yourself.
Series: Building governed ERP agents on AWS · Series guide → 
This post: How to make SAP execute the agent's calls as the signed-in person, and how to prove it from SAP's own records.
Prereq: A running deployment from the deploy walkthrough , working SAP OData connectivity as covered in the cognito-basic setup , and three people: an SAP administrator, a Microsoft Entra administrator, and the AWS operator who manages the AWS for SAP MCP Server.

What you get from this post

By the end, a person signs in with Microsoft Entra, asks the agent for SAP data, and SAP runs the request as that person's own SAP user. No second SAP login prompt appears, and you can prove the result from SAP records rather than from an application log. You also get:
  • The two Entra application registrations this path needs, and why one of them is the audience for the user's token.
  • The SAP trust and user-mapping steps to request from your SAP administrator.
  • The claim you must not map, which is the most common cause of a working login that still fails at SAP.
  • A step-by-step way to confirm the effective SAP user with the STAD transaction, plus the five failures you are most likely to hit.
Time: plan for a working session with all three administrators, not a solo afternoon.
You will need: an Entra tenant with admin consent rights, SAP administrator access, and a deployed AWS for SAP MCP Server.
IMPORTANT
This is the most configuration-heavy profile in the series. It is not a one-line switch. It needs two Entra app registrations, SAP trust and claim mapping, an external MCP deployment configured for Entra, and an on-behalf-of credential provider. Budget for the coordination, not just the config file.

New to this series? Start here

The Agentic ERP Automation Quickstart  is an open source reference implementation that deploys an AI agent for work your team does by hand from a written procedure, on Amazon Bedrock AgentCore. Accounts payable is the worked example, where a case looks like an invoice that does not match its purchase order. A new process type is a skill directory and your own SOPs. A few terms recur below:
  • OData is the REST-style API protocol SAP exposes for business data.
  • MCP is the Model Context Protocol, the standard the agent uses to call tools. The AWS for SAP MCP Server is a separate AWS-provided runtime that gives the agent its SAP tools. You deploy it yourself, and the Quickstart does not deploy it for you.
  • OBO means on-behalf-of. A server exchanges the token it received from a signed-in user for a second token, so a downstream system can act for that same person.
  • SU01 is the SAP transaction for user records. When this post says "the mapped SU01 user," it means the SAP user account that corresponds to a person in Entra.
  • STAD is the SAP transaction that lists statistics records for individual requests, including which SAP user actually ran each one.
One setting in cdk/config.yaml, called auth_profile, selects a matching set of identity choices across the whole deployment. This post covers entra-obo. The auth profile overview  explains the full profile model if you want that background first.

Why this profile exists

Every other profile in this series reaches SAP as one technical account. That works until an auditor asks who approved a posting, or until your SAP authorization model needs to differ from person to person. With entra-obo, the answer comes from SAP itself: the OData request runs as the mapped SU01 user, and STAD shows you that user.
Here is how the three main profiles compare:
ProfileWho SAP seesPath to SAPVerification status
cognito-basicOne technical userThrough AgentCore GatewayVerified end to end as a Basic technical user
cognito-m2mOne technical userThrough AgentCore GatewayDeploys today, no live-SAP verification record
entra-oboThe signed-in personDirect to the MCP serverVerified end to end in the tested SAP environment below
Only entra-obo changes the answer to "who was that?"

How the flow works

Four hops carry the person's identity to SAP:
  1. The browser signs the user in directly with Entra. There is no Cognito login on this profile.
  2. The runtime validates the user's Entra access token, then connects directly to the external AWS for SAP MCP Server.
  3. The external server exchanges that user token for a new SAP-scoped token, using AgentCore Identity.
  4. SAP validates the Entra issuer and maps a stable claim in that token to a SU01 user.
Two properties of this flow drive most of the configuration:
  • The exchange is a JWT bearer grant (RFC 7523, with requested_token_use=on_behalf_of), not the newer RFC 8693 token exchange. That is why the credential provider setting is JWT_AUTHORIZATION_GRANT.
  • The path is direct to the MCP server and bypasses Gateway. So Gateway Cedar policies are not a write gate here. The external MCP server owns the SAP-facing runtime, provider, scopes, credentials, and write configuration. This repository validates and assembles the matching adapter configuration.

Confirm this profile fits before you start

Use entra-obo when all of these are true:
  • Your frontend signs users in with Microsoft Entra.
  • You need SAP to attribute OData activity to individual people rather than one technical account.
  • A second SAP login prompt is not acceptable in the normal flow.
  • Your SAP and Entra administrators can configure the required trust, mapping, and consent.
Two limits to plan around:
  • Do not use OBO for unattended polling. OBO carries a user's identity, and a scheduled job has no user. The scheduled OData poller stays on the technical service-account path regardless of which profile you select.
  • The verification record covers one environment. It is a single S/4HANA 2023 system running SAP_BASIS 7.58. Before production use, confirm SAP_BASIS support, SOIDC feature-pack behavior, transaction field names, and your own authorization model on your release. The runbook makes no claim about testing against a production SAP system.

Who configures what

Three teams own parts of this path. Line them up before you begin.
OwnerResponsibilities
SAP administratorConfigure STRUST (certificates), SOIDC (provider trust), SICF (service activation), SU01 user mapping, and PFCG authorizations.
Entra administratorRegister the inbound browser application and the outbound exchange application, expose and consent the delegated scope, configure claims, and add the provider callback URL after deployment.
AWS operatorDeploy the external MCP server with Entra inbound validation, create the OBO credential provider, and keep write operations disabled until validation is complete.
Keep the operator runbook  open while you work. It carries the release-specific, field-level procedures this article deliberately does not duplicate.

Step 1: Register the two Entra applications

Start here, because the rest of the configuration needs the client IDs these produce. Create two registrations unless your topology has a documented reason for a third.
The inbound browser application is the client your users load. Register it as a single-page application, add the frontend login redirect URI, and record its client ID and tenant ID. It uses authorization-code flow with PKCE, the standard public-client pattern for browser apps.
The outbound exchange application is a confidential middle-tier client. Create a client secret and store it where your external MCP deployment expects it. Expose a delegated API scope, for example SAP.Access. Add the stable optional claim that SAP will map later, such as preferred_username, email, or upn.
Then connect the two: grant the browser application permission to the outbound application's delegated scope, and grant tenant-wide admin consent.
IMPORTANT
The browser application must request the outbound application's scope, so that the resulting access token carries the outbound application's audience. A token scoped to Microsoft Graph, or a raw ID token, cannot be redeemed by this OBO flow. This one detail causes a large share of first-attempt failures.
The SAP.Access scope is only a label for the exchange. It grants nothing in SAP. Access control stays with SAP authorizations.

Step 2: Select the profile and add the Entra values

Set auth_profile at the top level of cdk/config.yaml, and keep the frontend and inbound overrides at the top level too:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
auth_profile: entra-obo

sap:
base_url: https://your-sap-host:443

frontend_overrides:
discovery_url: https://login.microsoftonline.com/<tenant>/v2.0/.well-known/openid-configuration
authority: https://login.microsoftonline.com/<tenant>/v2.0
client_id: <spa-client-id>

inbound_overrides:
discovery_url: https://login.microsoftonline.com/<tenant>/v2.0/.well-known/openid-configuration
allowed_clients:
- <obo-app-client-id>
Three things to get right in that block:
  1. frontend_overrides.authority is required for a direct Entra frontend. Set it to the Entra issuer, https://login.microsoftonline.com/<tenant>/v2.0, not to the discovery URL. The deployment needs a non-empty authority, discovery_url, and client_id before it writes the browser configuration.
  2. client_id is the browser application from Step 1.
  3. allowed_clients holds the outbound application's client ID, not the browser client's. This is the audience of the user's access token, which is why the two values differ.
Then redeploy:
1
python3 launch.py deploy

Step 3: Configure SAP trust and user mapping

This is the trust setup that OBO adds. It does not replace your existing OData connectivity or your technical-user configuration. Ask your SAP administrator for four things:
  1. Import the full Entra token-endpoint TLS chain in STRUST, including the leaf, intermediate, and root certificates. Importing only the root is a common cause of TLS failures.
  2. Create the Entra provider trust in SOIDC. The expected audience is the outbound exchange application's client ID, not the browser client's.
  3. Map a stable human claim to the matching SU01 user. Good candidates are preferred_username, email, or upn.
  4. Activate the required OData services in SICF, and give each mapped SU01 user the PFCG authorizations those services need.
WARNING
Do not map Entra's sub claim. Entra issues an opaque sub value that is unique per application pairing and identifies neither the person's email address nor their SAP user. Also confirm the claim you choose is actually present in the SAP-scoped token, because SAP cannot map a claim that never arrives.

Step 4: Configure the external MCP server and the OBO provider

The external AWS for SAP MCP Server must validate incoming tokens against Entra and use the on-behalf-of flow toward SAP. Your settings need to agree with the Entra and SAP work above on every one of these points:
  • The discovery URL points to your Entra tenant.
  • Allowed audiences contain the outbound exchange application's client ID.
  • The inbound token was requested for the outbound application's delegated scope.
  • SAP OData scopes are service names, such as API_PURCHASEORDER_PROCESS_SRV, not OAuth scope URIs.
  • MCP_SERVER_SAP_OAUTH_FLOW is set to ON_BEHALF_OF_TOKEN_EXCHANGE.
  • The OBO provider uses JWT_AUTHORIZATION_GRANT, which is the Entra grant type.
  • Write operations start disabled.
The credential provider creation order matters, because one value only exists after the fact. The AgentCore credential provider returns a callback URL after it is created, so work in this sequence:
  1. Create the outbound Entra application and its secret.
  2. Deploy the credential provider.
  3. Add the returned callbackUrl to the outbound application's Web redirect URIs.
That callback URL is not the same as the browser login redirect. The /auth/callback route belongs to a different flow, USER_FEDERATION, and is not part of OBO.

Step 5: Prove the identity reached SAP

Sign in as a mapped Entra test user and ask the agent for a read against an activated OData service:
1
Read the first five purchase orders from SAP.
On the happy path, you get data and no second SAP login prompt.
A successful response is not yet proof of attribution. The evidence has to come from SAP, so use STAD to confirm which SAP user actually ran the call:
  1. Search a window of a few minutes around the UTC time of your test call.
  2. Leave the User filter blank. Filtering by the user you expect can hide a failed mapping.
  3. Find the SAPMHTTP /sap/opu/odata/sap/<SERVICE> row for your request.
  4. Confirm that the row's User is the mapped human SU01 user.
Do not use SM20 as your proof. Successful OIDC bearer logons over HTTP may not appear there at all. STAD records the authenticated ABAP user for HTTP and ICF requests without needing an audit class turned on ahead of time.

What controls SAP writes on this path

Start with reads only. When you do enable writes, two layers govern them, and neither of them lives in this repository:
  1. The external MCP server decides which write tools exist, through its deploy-time MCP_SERVER_WRITE_ENABLED setting and its per-operation flags.
  2. SAP authorizations for the mapped SU01 user are the final word, and the only layer SAP enforces itself.
There is no local runtime write switch for this profile. Gateway Cedar policies do not apply, because this topology bypasses Gateway. Even on a Gateway path, Cedar can block a request only when the relevant target and the policy engine are deployed and enforcement is set to ENFORCE.
Scope your expectations to what was actually tested. The tested OBO environment exercised one odata_update through a dedicated write-enabled external MCP deployment. Create, delete, and function-import operations were not exercised. That is evidence for one setup, not a general certification of SAP writes.

Troubleshooting the common failures

SymptomStart with
The runtime rejects the user tokenCheck the Entra discovery URL, the issuer, expiration, and that the token audience is the outbound application.
SAP returns 401Check the SOIDC issuer and outbound audience. Then check that SAP maps a stable human claim rather than sub.
SAP returns 403Check PFCG authorization for the mapped SU01 user, and that the OData service is activated.
The OBO exchange failsConfirm the provider uses JWT_AUTHORIZATION_GRANT rather than RFC 8693 token exchange.
The application asks for a second loginCheck Entra consent, plus any Conditional Access or multi-factor authentication claims challenge.

Where to go next

Series: Building Production-Grade ERP Agents on AWS (18 articles)

  1. …
  2. 6
    SAP identity propagation with Entra ID on-behalf-of | Agentic ERP Quickstart This article
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article