Editor’’s note: This blog was coauthored with Mário Cunha, a tech lead in the OutSystems Professional Services organization.
As development teams expand across OutSystems 11 (O11) and OutSystems Developer Cloud (ODC), application architectures have shifted heavily toward service-oriented designs. REST APIs now form the connective tissue linking legacy core platforms, modern apps, and cross-platform integrations.
In today's "Agentic Era," these APIs that serve web screens also expose business logic directly to AI agents and external automated systems, along with serving web screens. If your endpoints lack robust protection, you risk handing sensitive enterprise data to unauthorized requests.
Here is a practical thinking framework, the AAA Standard (Authentication, Authorization, and APIs Security Patterns), to guide your security decisions every time you publish or consume a service in OutSystems.
1. AuthN vs. AuthZ: The common misconception
Developers frequently lump authentication and authorization into one bucket, but treating them as identical creates massive security gaps:
Authentication (AuthN): "Who are you?" AuthN verifies identity through credentials, biometrics, or machine keys. Its sole output is proof of identity.
Authorization (AuthZ): "What can you do?" AuthZ determines whether an already authenticated identity has permission to access a specific resource or execute a specific operation.
Write “Being authenticated is not being authorized” on your developer whiteboard.
According to OWASP, Broken Access Control is the #1 security vulnerability, showing up in 94% of tested applications. When you build loosely coupled services between O11 and ODC, failing to enforce authorization leaves severe logic and data vulnerabilities exposed.
2. Securing the perimeter: Token-based authentication
To validate incoming API requests, we use token-based authentication, which is typically JSON Web Tokens (JWT). A JWT carries data as a Base64URL-encoded JSON object split into three distinct parts: header, payload, and signature.
When handling token authentication, adhere to these non-negotiable rules:
Always sign tokens: Never accept an unsigned token. Cryptographic signatures (HMAC or RSA) prove token integrity.
Symmetric signing: Uses a single shared key for signing and verification. This works well in trusted, peer-to-peer environments.
Asymmetric signing: Uses a private key to sign the token and a public key to verify it. This approach offers enhanced security and decouples identity issuers from API consumers.
Support M2M and user flows: Differentiate between user authentication (where users log in directly) and machine-to-machine (M2M) authentication (where automated systems interact without user intervention).
3. Selecting your authorization strategy
Before writing logic, you must choose an authorization model that matches your organization's complexity:
Model
Mechanisms
Pros
Cons
Ideal Use Case
Role-based (RBAC)
High-level roles assigned to users and embedded in tokens.
Simple to implement; highly scalable for smaller orgs.
Rigid structure; leads to "role explosion" over time.
To protect business logic, implement the Authorization Wrapper Action Pattern at the start of every sensitive REST endpoint.
How the wrapper works:
First line of defense: The wrapper executes before any business logic touches database entities.
Fail-closed design: If a permission check fails, the wrapper halts execution immediately and returns a "No Permission" status.
Audit logging: Every authorization rejection triggers an audit log entry to track potential intrusion attempts.
Managing token claims: User ID vs. group claims
Inside your wrapper, how you extract identity dictates your architecture's performance:
User ID (reference-based): The token carries only a unique User ID. This keeps payload sizes minimal. The API looks up active permissions from a cache or database in real time. Choose this when you manage user permissions locally and need instant permission revocation.
Group claims (value-based): The token embeds user groups directly in its payload. Payload sizes grow slightly larger, but services don't need to hit a central database to check permissions. Choose this when integrating third-party Auth providers or scaling distributed microservices.
5. Record-level data security: The shadow entity pattern
Securing your API endpoints isn't enough if users can query records they don't own. Never fetch entire datasets to filter them on the client side. Filter data directly inside database Aggregates or SQL queries.
When managing dynamic record-level access, implement the shadow entity pattern.
Architectural Implementation:
Isolate Security Attributes: Create a secondary table as a "shadow entity" (for example, Document_ACL) that maps business record IDs to authorized organizational groups.
Filter at the data layer: In your OutSystems aggregate, join the main business entity directly with its shadow ACL entity. This guarantees the database returns only authorized records. These are filtered by the user groups.
Map permissions to groups: Assign ACL rights to organizational groups rather than individual User IDs. This prevents management gridlock when employees change roles or leave.
6. The golden rules recap
Keep this checklist handy whenever you design, review, or release an OutSystems API:
Trust no one: Treat every incoming payload and request as a potential threat.
Adopt a security mindset: Integrate security checkpoints directly into user stories from day one.
Server-side is law: Always perform authorization checks on the server; UI hide/show logic is cosmetic.
Isolate security layers: Use wrapper actions for action/operation security, and use Shadow Entities for record-level filtering.
Match strategy to scale: Pick the right mix of RBAC, ABAC, or permission claims based on your enterprise setup.
Mauro is an Application Security Subject Matter Expert and Enterprise Architect with over 25 years of experience driving impactful technology solutions across diverse market sectors. A developer at heart with strong roots in Java and advanced expertise in OutSystems, he bridges the gap between agile software engineering and enterprise security. Mauro excels at delivering strategic architectural guidance while embedding deep-domain security practices into the development lifecycle. He is driven by a core philosophy: rapid technical innovation must accelerate business growth without ever compromising a robust security posture.