Logistics & supply chain / IT & data

Test client-portal access using another customer's shipment identifiers

By Vikasraj YadavPublished 8 min read

For cio / cto, integration architect, security lead with domain owners · Plan implementation

TL;DR — what you’ll learn

  • Never assume that hiding another client's shipments from the portal dashboard prevents access if an authenticated user changes the `lr_number`, `shipment_id` or `invoice_id` in the URL or API payload.
  • Run explicit cross-tenant authorisation tests between two controlled sandbox tenants (`Tenant A` and `Tenant B`) across every REST endpoint, export job and document download URL before launch.
  • Enforce server-side tenant ownership checks on POD images, signed invoices and commercial rate annexures—not just on the top-level shipment summary row.
  • Verify immediate session and token revocation when a client user leaves or switches accounts so cached bearer tokens cannot continue pulling shipment exports.

Topics: 3pl client portal security · logistics tenant isolation · shipment API access control · customer document permissions

Mezzanine operations desk with dual monitors, a coiled headset and a notebook overlooking a warehouse floor with pallet racking through an interior glass partition.

Illustrative logistics operations desk overlooking a warehouse floor; not a client facility.

All quantities, amounts, product codes and events are illustrative teaching examples.

Why UI filtering is not tenant isolation in a multi-client 3PL portal

When a third-party logistics provider (3PL) or multi-client warehouse builds a self-service portal for its enterprise customers, the most common security vulnerability does not show up during standard functional testing. In user acceptance testing, a tester logs in as Client A, clicks the "My Shipments" table, sees only Client A's lorry receipts, and passes the build.

The failure occurs one layer deeper in the backend API. While the list endpoint (/api/shipments?client_id=A) filters rows by tenant, the detail endpoint (/api/shipments/LR-2026-00492), the bulk CSV export endpoint or the proof-of-delivery (POD) image bucket often checks only that the caller holds a valid login token—not that LR-2026-00492 belongs to the caller's tenant. Because logistics identifiers such as LR numbers, gate-pass numbers and invoice sequences are frequently sequential (LR-00491, LR-00492, LR-00493), a curious user or automated script authenticated as Client A can increment the number and read Client B's consignee names, invoice values, SKU quantities and delivery photos.

In the OWASP — API Security Top 10 2023, this exact flaw is ranked number one: API1:2023 — Broken Object Level Authorization (BOLA). Preventing it in a logistics portal requires server-side tenant scoping on every object and attachment lookup, verified by deliberate cross-tenant test cases prior to production rollout.

Set up a two-tenant sandbox matrix before writing the test script

Never test authorisation by guessing identifiers on live customer data. Provision two isolated, realistic test tenants in your staging environment—Tenant A (Synth-Pharma Corp) and Tenant B (Synth-Auto Parts Ltd)—populated with synthetic shipments that share a similar multi-client warehouse (WH-BHIWANDI-01) and overlapping carrier trips:

  1. Direct single-client shipments: SHP-A-101 owned solely by Tenant A, and SHP-B-201 owned solely by Tenant B.
  2. Consolidated multi-client truckload: A shared linehaul trip TRP-SHARED-900 carrying LR-A-501 (Tenant A) and LR-B-502 (Tenant B) on the same physical vehicle.
  3. Sub-account / regional distributor roles: A regional branch user inside Tenant A (Branch-North) who is authorised to see North Zone dispatches (SHP-A-101) but not West Zone dispatches (SHP-A-109) or commercial freight rate cards.
  4. Attached binary documents: Signed POD scans, commercial tax invoices, packing lists and temperature logger PDFs stored in object storage.

Protecting consignee identities, delivery addresses and phone numbers across these boundaries also aligns directly with the personal-data safeguard obligations highlighted in the MeitY — Digital Personal Data Protection Rules 2025.

Illustrative example: running 60 cross-tenant authorisation checks before portal go-live

Suppose a 3PL engineering and QA team executes a pre-release security verification suite of 60 scripted API and attachment requests across Tenant A and Tenant B in staging. Every request in the matrix is evaluated against its expected HTTP authorisation outcome (200 OK for authorised own-tenant scope; 403 Forbidden or 404 Not Found with zero data leakage for cross-tenant or revoked requests).

Scroll horizontally to see all columns.

Test cohort in the 60-request staging matrix Test requests Authenticate as Target resource & action Expected security outcome Verified staging result
1. Authorised own-tenant baseline queries 30 Tenant A active user Fetch Tenant A shipment details, inventory balances, ASN status & own POD files Return 200 OK with scoped Tenant A fields only 30 passed (30/30)
2. Cross-tenant object ID tampering (BOLA) 15 Tenant A active user Request Tenant B shipment IDs (SHP-B-201), sequential LR numbers (LR-B-502) & shared-truck sibling LRs via GET/POST Deny with 403/404; do not leak whether LR-B-502 exists 15 denied (15/15)
3. Direct attachment & object-storage URL replay 10 Tenant A active user (or unauthenticated browser) Request Tenant B POD image keys, invoice PDFs & presigned URLs after swapping file key parameters Deny with 403 Forbidden; enforce tenant check before signing URL 10 denied (10/10)
4. Revoked user / deactivated session token replay 5 Former Tenant A user token (revoked 2 mins ago) Call shipment search, webhook subscription & bulk CSV export endpoints Deny with 401 Unauthorized immediately upon revocation 5 denied (5/5)
Total pre-release authorisation test suite 60 — 30 positive baseline + 30 negative adversarial checks (15 + 10 + 5) 30 allowed + 30 blocked = 60 expected outcomes 60 / 60 verified

The 60-request test matrix reconciles cleanly across all four categories:

  • 30 authorised baseline requests confirm that legitimate Tenant A operations work without friction.
  • 15 cross-tenant object-ID tampering requests confirm that substituting Tenant B's shipment, LR or shared-trip identifiers is blocked at the data-access layer.
  • 10 direct attachment URL replay requests confirm that POD images and invoice PDFs cannot be fetched across tenants.
  • 5 revoked-session requests confirm that deactivated users lose API access immediately (30 + 15 + 10 + 5 = 60 requests).

Close the four most common bypass paths in logistics portals

When a test in Cohort 2 or Cohort 3 fails during staging, the root cause almost always sits in one of four places:

  1. Shared-vehicle and consolidated-trip lookups: When Tenant A queries the live GPS location of LR-A-501, the backend looks up the parent vehicle trip TRP-SHARED-900 and carelessly returns the entire trip object—including the stop list and consignee names for Tenant B's LR-B-502 riding on the same truck. Always project only the stops and cargo lines belonging to the authenticated tenant's consignment.
  2. Unscoped cloud storage buckets for PODs: Storing POD photos in a public or semi-public bucket with predictable paths like /pods/2026/10/LR-8802.jpg allows anyone to iterate file names. Keep the storage bucket private, validate shipment.tenant_id == user.tenant_id in your backend API first, and only then stream the file or mint a short-lived (for example, 60-second) single-object presigned URL.
  3. Asynchronous bulk export and report endpoints: Even when /api/shipments/{id} is secure, the background report generator (/api/reports/export-csv) sometimes accepts an array of warehouse_ids or lr_numbers in the JSON body without re-verifying tenant ownership for every item in the array.
  4. Property-level over-exposure (OWASP API3:2023): Returning the entire internal database row in the JSON response and relying on the React frontend to hide internal 3PL carrier cost, margin, broker phone numbers or internal audit notes. Inspect the raw network tab in browser developer tools to confirm that internal cost fields never leave the server.

Automate cross-tenant regression checks in CI

Access control is easy to break six months after launch when a developer adds a new "Download Packing List" button or a GraphQL resolver. Turn your two-tenant sandbox matrix into an automated integration test suite that runs on every pull request touching portal routes, shipment APIs or document storage handlers. If any new endpoint returns a 200 OK when called with Tenant A's token and Tenant B's resource ID, the build should fail automatically.

Next actions

  1. Inventory every client-facing API route, GraphQL query, CSV export job and document download link in your 3PL or warehouse portal.
  2. Set up two synthetic staging tenants (Tenant A and Tenant B) including a shared consolidated truckload scenario (LR-A and LR-B on one trip).
  3. Run the 60-request positive and negative authorisation test suite—specifically testing swapped LR IDs, shared-trip sibling payloads, POD file URLs and revoked tokens.
  4. Inspect raw JSON API responses in the browser network panel to verify that carrier buy-rates, margins and other clients' stops are stripped on the server.

Discuss this workflow

Describe your current systems, the recurring exception and the outcome you need. Keep shipment, customer and financial records out of the initial message.

Draft an assessment email

References

Sources checked 15 October 2026. Vendor documentation supports platform facts; the worked examples and diagrams are original.

About the author

Vikasraj Yadav writes about operational decisions, software and automation for NextEdge Labs.