11 min read
sap
segurança
arquitectura
integração
portal cliente

Secure customer portal on SAP data

How to design a customer portal on SAP with APIs, authorisation, auditing, caching and integration without exposing the ERP or duplicating critical rules.

Mãos a desenhar uma arquitectura de portal e a colar notas de autorização num vidro, numa sala iluminada.

TL;DR

  • Do not expose SAP directly to the portal. Use an API layer or BFF to control authentication, authorisation, rate limits, auditing and data transformation.
  • If the portal is mostly read-only, create a read model outside SAP. Querying SAP in real time for every screen usually breaks latency, licensing and availability.
  • OAuth2 or SAML solve identity, they do not solve business authorisation. You need to map external users to SAP entities such as customer number, sales org, company code and roles.
  • SAP OData is useful for many scenarios, but it is not an architecture in itself. Be careful with pagination, expensive filters, CSRF tokens, ETags and error semantics.
  • The critical part is not the login. It is preventing a customer from seeing another customer's orders, invoices, prices or tickets, especially in accounts with business groups, branches and external users.

The real problem: a customer portal is not just a front-end on SAP

The question seems simple: “how do I build a secure customer portal on SAP data?” The short answer is: with a very clear boundary between the external world and the ERP.

A typical customer portal needs to show orders, invoices, credit notes, delivery status, contracts, prices, consumption, tickets or documentation. Almost all of this lives, directly or indirectly, in SAP. The common mistake is treating SAP as if it were a normal relational database and building the portal to call OData, RFC or BAPI services whenever the user opens a page.

That works in a demo. In production, the problems appear: p99 above 2 seconds, timeouts during peak load, queries that depend on SAP indexes and customising, external users who do not fit the internal authorisation model, and Basis teams that are not very happy with unpredictable traffic coming from the internet.

My view is simple: SAP should be the source of truth for business processes, but it should not be the main runtime for your portal. The portal needs its own layer, with API contracts designed for external users, explicit application security and independent observability.

The base architecture usually has these blocks:

  • Web or mobile portal.
  • External identity provider, for example Microsoft Entra ID, Auth0, Okta or SAP Cloud Identity Services.
  • Backend for Frontend or application API Gateway.
  • Integration layer with SAP, via OData, RFC, IDoc, SOAP or SAP Integration Suite.
  • Read model outside SAP, when there is volume, search or a need for low latency.
  • Dedicated auditing and monitoring.

The most important point: the portal must never trust only what the front-end sends. The backend must always validate who the user is, which account they represent, what permissions they have and which SAP objects they can view or change.

Choosing the integration pattern: real time, replica or hybrid

There are three realistic patterns for exposing SAP data to external customers.

PatternWhen to useAdvantagesRisks
Real-time calls to SAPCritical and infrequent data, such as order submission or credit validationImmediate source of truth, less duplicationHigh latency, direct dependency on SAP, lower fault tolerance
Replicated read modelListings, history, invoices, orders, tracking, cataloguesp95 below 200 ms is feasible, fast search, less load on SAPEventual consistency, needs synchronisation and reconciliation
HybridMost B2B portalsBalances performance and accuracyRequires a clear design of which data is synchronous and which is asynchronous

For a portal with 500 active customers and listing pages, I would avoid querying SAP in real time for everything. An invoice list with filters by date, status and customer reference may seem trivial, but it can generate many expensive calls. If each user makes 20 interactions per session and each interaction calls SAP, 300 concurrent users can easily become thousands of calls in a short interval.

A read model in PostgreSQL 16, SQL Server or Elasticsearch can keep the data needed for reading: invoice headers, order status, summary lines, amounts, currency, dates and references. SAP remains the source of truth. The portal only keeps a projection optimised for external querying.

Synchronisation can come in several forms:

  • SAP OData with incremental polling, if there are reliable change fields.
  • IDocs for existing business events.
  • Change pointers in SAP, where applicable.
  • SAP Event Mesh, in more modern architectures on SAP BTP.
  • Nightly jobs for data that is less time-sensitive, such as old documents.
  • Integration through SAP Cloud Integration, when orchestration and transformation are needed.

The relevant official documentation depends on the SAP landscape, but it is worth looking at SAP Gateway OData, SAP Cloud Connector, SAP Integration Suite and SAP Event Mesh. For authentication and authorisation, OAuth 2.0 is defined in RFC 6749 and OpenID Connect Core 1.0 is the practical reference for identity.

Security: identity, authorisation and data isolation

Authentication is knowing who has signed in. Authorisation is knowing what that person can do. In a portal on SAP, the second part is where the serious incidents are.

An OIDC token can say that the user is [email protected]. That is not enough to show invoices. The backend needs to know:

  • Which SAP customer numbers that person is associated with.
  • Whether they can see data for the whole company or only for one branch.
  • Whether they can view prices, invoices, contracts or only orders.
  • Whether they can submit requests that create documents in SAP.
  • Whether there is a relationship between the external account, sales organization, distribution channel and company code.

A practical approach is to maintain an external authorisation table, managed by the portal or synchronised from a master system. This table links external users and groups to SAP entities. Do not use email as the authorisation key for SAP data. Emails change, they can be reused, and they rarely model corporate structures.

A minimal example of useful claims in a token or internal session:

{
  "sub": "usr_12345",
  "tenant_id": "customer_group_987",
  "sap_customers": ["0001234567", "0001234568"],
  "permissions": ["orders:read", "invoices:read", "tickets:create"],
  "assurance_level": "mfa"
}

The detail of leading zeros is not cosmetic. In SAP, identifiers such as KUNNR are usually padded. I have seen integrations fail authorisation because the application compared 1234567 with 0001234567. The result can be a false negative, which annoys users, or worse, a badly implemented normalisation that mixes entities.

It is also not enough to hide buttons in the front-end. Every endpoint must validate authorisation at object level. For example, GET /invoices/90000123 has to verify that the invoice belongs to a customer number authorised for that user. Do not trust the filter from the previous listing.

Minimum rules I would apply:

  • Mandatory MFA for users with access to invoices, prices or personal data.
  • Short sessions for sensitive operations, for example reauthentication after 15 minutes for changing bank details.
  • Rate limiting by user, tenant and IP. A reasonable starting point: 60 requests per minute per user and separate limits for expensive endpoints.
  • Immutable auditing for viewing sensitive documents and changes.
  • Encryption in transit with TLS 1.2 at minimum, preferably TLS 1.3.
  • Secrets in a dedicated manager, such as AWS Secrets Manager, Azure Key Vault, HashiCorp Vault or SAP Credential Store.
  • Environment separation. Never use real customer data in development environments without anonymisation.

API and BFF: the boundary that protects SAP

The intermediate layer should not be a passive proxy. It should translate the SAP model into stable product contracts.

SAP has objects and structures designed for internal processes. The portal needs APIs oriented towards use cases: “list customer invoices”, “get order status”, “submit return request”, “download PDF document”. If you expose internal OData entities directly to the browser, you are coupling the product to SAP customising and increasing the attack surface.

Two common alternatives:

OptionProsCons
SAP BTP with SAP API Management and Integration SuiteGood integration with the SAP ecosystem, Cloud Connector, API policies, principal propagationCan become expensive and complex, requires SAP BTP skills, risk of product logic becoming scattered
Own backend in Node.js 22 LTS.NET 8 or Java 21Full control over UX, authorisation, caching, testing and observabilityYou have to manage operations, security and connectors with discipline

The choice is not religious. If the organisation already uses SAP BTP well, it makes sense to take advantage of SAP API Management, Cloud Integration and Cloud Connector. If the portal is a digital product with many UX, onboarding, permission and non-SAP integration rules, I usually prefer an in-house backend, even if it uses BTP for secure connectivity to SAP.

What I do not like: the browser calling SAP Gateway directly. Even with OAuth2, you are placing too much SAP surface area outside. I prefer SAP Gateway to be accessible only from the controlled network or via SAP Cloud Connector, and for the portal to talk to an API designed for it.

API contracts should include:

  • Cursor-based pagination where possible, not just offset.
  • ETags or versions to avoid lost updates.
  • Normalised errors, with clear application codes.
  • Idempotency keys for operations that create requests, orders or payments.
  • Short timeouts. For example, 3 seconds for synchronous reads and 10 seconds for rare critical operations.
  • Correlation ID propagated from the portal to SAP, logs and queues.

Data, cache and consistency: where many portals become slow

A secure customer portal also has to be predictable. Security without availability does not serve the business. The main question is: which data has to be absolutely current?

Not everything needs the same level of freshness:

Data typeAcceptable freshnessRecommended strategy
Order status1 to 15 minutesRead model with incremental synchronisation
Issued invoices15 minutes to a few hoursReplication and daily reconciliation
Personalised pricesDepends on the contractControlled SAP query or short cache
Credit limitSeconds to minutesReal time or very short cache
Order submissionImmediateSynchronous call or queue with clear confirmation
Legal PDFsDepends on issuanceSecure storage with temporary URLs

If you use cache, be explicit about invalidation. Generic 30-minute caches can create legal or commercial problems if they show wrong prices, outdated payment status or revoked documents. For sensitive data, I prefer cache by tenant and by permission, with keys that include the authorisation context.

Another critical point is search. SAP is not the ideal place for free search by reference, text, date range, status and customer order number. For that, PostgreSQL with appropriate indexes may be perfectly sufficient. Elasticsearch or OpenSearch make sense when there is heavy text search or larger volumes. Do not add Elasticsearch just because it seems modern. For 10 GB of portal data and structured filters, a well-indexed PostgreSQL 16 database is often enough.

For synchronisation, always design reconciliation. Events get lost, jobs fail, IDocs get stuck, and someone changes customising. A daily process that compares counts and checksums by period can save days of investigation. It does not need to be sophisticated at the start. It needs to exist.

Sensitive operations: writing to SAP without creating duplicates

Reading data is half the problem. The other half is allowing customers to take actions: create a support request, submit an order, update an address, request a duplicate copy, accept a quotation or initiate a return.

Three rules apply here.

First: operations that change SAP must be idempotent. If the user clicks the button twice, if the browser repeats the request or if there is a timeout between the backend and SAP, you cannot create two orders.

Second: the confirmation shown to the user must reflect reality. If the operation has been queued, say “request received” and show a pending status. Do not say “order created” before you have the SAP number.

Third: critical business validations should stay close to the source of truth. The portal can validate format, mandatory fields and permissions. But credit, final availability, customer blocks and tax rules must be confirmed by SAP or by an authorised service.

A pattern that works well:

  1. Portal sends request with idempotency key.
  2. Backend validates identity, authorisation and schema.
  3. Request is persisted with received status.
  4. Worker processes creation in SAP.
  5. Result stores SAP number, messages and final status.
  6. Portal checks status by API or receives a notification.

For operations that have to be synchronous, define timeouts and compensation. If SAP does not respond within 10 seconds, the portal should store the request and continue asynchronously, or fail with an honest message. The worst scenario is the user not knowing whether they have created the document or not.

Observability, auditing and production gotchas

A portal on SAP fails in non-obvious ways. That is why instrumentation is not optional.

Minimum metrics:

  • p50, p95 and p99 latency per endpoint.
  • Error rate per SAP integration, separating 4xx, 5xx, timeouts and business errors.
  • Number of SAP calls per user and per tenant.
  • Queue size and age.
  • Synchronisation lag by entity, for example orders 4 minutes, invoices 32 minutes.
  • Cache hit ratio by data type.
  • Denied access attempts to objects.

Logs should include correlation ID, tenant, internal portal user, business object and result. They should not include unnecessary personal data, tokens, passwords, cookies or PDFs in base64.

Auditing is different from logging. Auditing answers questions such as: “who viewed this invoice?”, “who downloaded this document?”, “who changed the delivery address?”, “which external user submitted this request?”. It should be difficult to alter and have a clear retention policy. In regulated sectors or where personal data is involved, align this with GDPR and the legal teams.

Gotchas that deserve attention:

  • CSRF in SAP OData. Many write operations require a CSRF token obtained beforehand. Ignoring this generates intermittent errors and poor retry solutions.
  • SAP timezones and dates. A delivery date without a timezone is not the same as a UTC timestamp. Define semantics per field.
  • Authorisation by corporate hierarchy. A group may have several SAP accounts, but not all users can see all of them.
  • Pagination with $skip on large datasets. It can become slow and inconsistent. Prefer cursors or replication.
  • SAP messages are not UX. Technical codes and texts should be translated into useful messages, while keeping detail in the logs.
  • SAP environments are not the same. DEV, QA and PRD may have different customising, data and authorisations. Tests only in DEV do not prove much.

Conclusion

Building a secure customer portal on SAP is less about “connecting an API” and more about designing a reliable boundary between external customers and internal processes. The right architecture separates identity, authorisation, integration, read models, auditing and operations. SAP remains in charge of critical processes, but the portal cannot be hostage to the latency and internal model of the ERP.

If you are facing a similar problem, book a call at https://impact-origin.com/agendamento.

Impact OriginEnjoyed this article?At Impact Origin we help founders and teams build and scale custom software, from a startup MVP to the next step. If you have a project in mind, let's talk.