
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)
- …
- 6SAP identity propagation with Entra ID on-behalf-of | Agentic ERP Quickstart This article
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 thecognito-basicsetup , 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
STADtransaction, 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.
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:
| Profile | Who SAP sees | Path to SAP | Verification status |
|---|---|---|---|
cognito-basic | One technical user | Through AgentCore Gateway | Verified end to end as a Basic technical user |
cognito-m2m | One technical user | Through AgentCore Gateway | Deploys today, no live-SAP verification record |
entra-obo | The signed-in person | Direct to the MCP server | Verified 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:
- The browser signs the user in directly with Entra. There is no Cognito login on this profile.
- The runtime validates the user's Entra access token, then connects directly to the external AWS for SAP MCP Server.
- The external server exchanges that user token for a new SAP-scoped token, using AgentCore Identity.
- 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 isJWT_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.
| Owner | Responsibilities |
|---|---|
| SAP administrator | Configure STRUST (certificates), SOIDC (provider trust), SICF (service activation), SU01 user mapping, and PFCG authorizations. |
| Entra administrator | Register 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 operator | Deploy 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:
frontend_overrides.authorityis 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-emptyauthority,discovery_url, andclient_idbefore it writes the browser configuration.client_idis the browser application from Step 1.allowed_clientsholds 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 deployStep 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:
- 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. - Create the Entra provider trust in
SOIDC. The expected audience is the outbound exchange application's client ID, not the browser client's. - Map a stable human claim to the matching SU01 user. Good candidates are
preferred_username,email, orupn. - Activate the required OData services in
SICF, and give each mapped SU01 user the PFCG authorizations those services need.
WARNING
Do not map Entra'ssubclaim. Entra issues an opaquesubvalue 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_FLOWis set toON_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:
- Create the outbound Entra application and its secret.
- Deploy the credential provider.
- Add the returned
callbackUrlto 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:- Search a window of a few minutes around the UTC time of your test call.
- Leave the User filter blank. Filtering by the user you expect can hide a failed mapping.
- Find the
SAPMHTTP /sap/opu/odata/sap/<SERVICE>row for your request. - 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:
- The external MCP server decides which write tools exist, through its deploy-time
MCP_SERVER_WRITE_ENABLEDsetting and its per-operation flags. - 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
| Symptom | Start with |
|---|---|
| The runtime rejects the user token | Check the Entra discovery URL, the issuer, expiration, and that the token audience is the outbound application. |
| SAP returns 401 | Check the SOIDC issuer and outbound audience. Then check that SAP maps a stable human claim rather than sub. |
| SAP returns 403 | Check PFCG authorization for the mapped SU01 user, and that the OData service is activated. |
| The OBO exchange fails | Confirm the provider uses JWT_AUTHORIZATION_GRANT rather than RFC 8693 token exchange. |
| The application asks for a second login | Check Entra consent, plus any Conditional Access or multi-factor authentication claims challenge. |
Where to go next
- Full Entra OBO operator runbook , which you should read before attempting this in a production SAP environment.
- Authentication profile selection for the complete profile reference.
- AgentCore on-behalf-of token exchange and AWS for SAP MCP identity documentation.
Series: Building Production-Grade ERP Agents on AWS (18 articles)
- …
- 6SAP identity propagation with Entra ID on-behalf-of | Agentic ERP Quickstart This article
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article