HomeArticle
Yggdrasil: Scaling Authorization at iFood with Cedar and a Stateless Architecture
DADOS & IA23 fev.

Yggdrasil: Scaling Authorization at iFood with Cedar and a Stateless Architecture

In a microservices ecosystem as dynamic and complex as iFood’s, ensuring that people and systems have appropriate access to the right resources is a constant challenge. Historically, in most cases, authorization logic is implemented in a decentralized and inconsistent manner within each application, becoming a source of security vulnerabilities, technical debt, and audit difficulties. To address these challenges, iFood’s Technology team developed Yggdrasil, our authorization-as-a-service platform.

Yggdrasil centralizes and standardizes access control, making authorization more scalable, auditable, and reusable across the entire company. Inspired by AWS Verified Permissions, a fully managed authorization service that allows storing, managing, and evaluating granular access permissions, Yggdrasil uses the same open source policy language, AWS Cedar, to define policies. However, Yggdrasil offers native integration with iFood’s ecosystem, supporting various identity providers, audit, and observability capabilities.

In this article, we will explore the concepts behind Yggdrasil, from the attribute-based access control model known as ABAC, to the choice of a stateless architecture with Cedar, but primarily how this platform is transforming the way we handle authorization at iFood.

What is ABAC (Attribute-Based Access Control)?

It is common for many authorization systems to use the RBAC (Role-Based Access Control) model, in which permissions are granted based on predefined roles, such as “administrator” or “viewer”. While simple to understand, RBAC can become rigid and lead to role explosion as business rules become more complex.

Yggdrasil adopts a more flexible and granular approach: ABAC (Attribute-Based Access Control). Instead of static roles, ABAC makes access decisions based on attributes. These attributes can be associated with any element of the request:

  • Principal: Attributes of the user or system requesting access (e.g., position, team, location);
  • Resource: Attributes of the object being accessed (e.g., document type, privacy tag, cost center);
  • Action: The operation that the principal wants to perform (e.g., read, write, delete);
  • Context: Environmental attributes at the time of the request (e.g., time, IP address);

This flexibility allows for the creation of much richer and more dynamic access policies that more faithfully reflect business rules. For example, an ABAC policy could express a rule like: “Allow finance team managers to approve expenses above $5,000, only during business hours”.

Stateful vs. Stateless: The Choice for Cedar

One of the most important architectural decisions when designing an authorization platform is choosing between a stateful or stateless approach. The main difference between them is the source of entity attributes (user profiles, resource tags, environmental data): in the stateful model, most of these attributes are stored by the authorization platform, while in the stateless model this responsibility belongs to the client application, which sends the attributes in the call made to Yggdrasil.

Stateful solutions, like Google’s Zanzibar, maintain a massive centralized database with all access relationships (e.g., “user X is a member of group Y”) and various other attributes. This approach is powerful but introduces significant operational complexity, requiring asynchronous data ingestion, ETL maintenance, and a potential single point of failure.

Yggdrasil opted for a stateless approach with AWS Cedar. Cedar is an open source authorization policy language and engine that does not depend on centralized state. Instead, the application requesting authorization sends all relevant data, i.e., entities and their attributes, as part of the request. Cedar’s engine then evaluates policies based on this data to make a decision.

This architecture provides us with a much simpler and more resilient operational model, perfectly aligned with the distributed nature of our microservices.

A Cedar Policy: Practical Example

The Cedar language is designed to be secure, fast, and easy to learn. A Cedar policy has three main components: the effect (permit or forbid), the scope (principal, action, and resource), and conditions (when and unless clauses).

Let’s imagine a policy for a document management system. The rule is: “Allow any user who belongs to the ‘Auditors’ group to view a document, provided the document is not private.”

In Cedar, this policy would be written as follows:

@id("auditor_read")
@cacheTTL("20m")
permit (
  principal in Group::"Auditors",
  action == Action::"view",
  resource
)
when { !resource.private };
  • @id and @cacheTTL: policy annotations that add metadata to the final decision. The id annotation is mandatory in Yggdrasil.
  • permit: The policy effect is permission.
  • principal in Group::”Auditors”: The principal scope defines that they must be a member of the Auditors group.
  • action == Action::”view”: The action must be view.
  • resource: The resource scope is open, applying to any resource.
  • when { !resource.private }: The condition requires that the resource’s private attribute is false.

Cedar operates with a deny-by-default principle. If no permit policy explicitly matches the request, access is denied. This makes the system inherently more secure and predictable.

Policy Store: The Basic Unit of Authorization

A Policy Store is essentially a container that groups a set of policies and configurations associated with a specific service or domain. Each authorization request to Yggdrasil must specify which policy store to use, not which policy.

This approach brings two crucial advantages:

  • Governance: since it’s not necessary to modify a client to enable or disable policies, onboarding updates is simpler and we ensure that forbid policies will always be executed.
  • Performance: By isolating policies by domain, the authorization engine only needs to evaluate a relevant subset of rules, instead of scanning all existing policies in the organization.
  • Security and Isolation: Isolating policies prevents a rule from one team from accidentally interfering with another’s behavior. Since Cedar is deny-by-default, ensuring that only relevant policies are evaluated prevents a permission policy from another context from granting improper access.

Yggdrasil Architecture

To meet the high performance and reliability requirements demanded by an environment like iFood’s, Yggdrasil was designed with a distributed and resilient architecture. Instead of a centralized service that could become a bottleneck or single point of failure, Yggdrasil’s authorization engine is distributed and runs close to the applications that consume it.

Yggdrasil distributed architecture diagram

Yggdrasil Architecture Details

  • Local Authorizer: Each account or cluster that hosts client applications has its own instance of the yggdrasil-authorizer. This ensures low latency, as communication between the application and the authorizer occurs locally, without the need for network calls outside the cluster.
  • Policy Stores in S3: Cedar policies are not stored within the authorizer. Instead, they are maintained in a centralized S3 bucket, which acts as the source of truth. Local Yggdrasil instances periodically update (every minute) their local copies of policies from this bucket, ensuring high availability and eventual consistency.
  • Decision Cache: Each authorizer uses a cache (Redis) to store already computed authorization decisions. This dramatically improves performance for repeated requests, a common scenario in high-volume systems.
  • Identity Providers (OIDC): When a request involves validating an identity token (through the IsAuthorizedWithToken call), Yggdrasil communicates with configured identity providers (like Keycloak) to validate the token and extract the claims (such as roles and other principal attributes) necessary for policy evaluation.

How Yggdrasil Makes Authorization Better

By adopting Cedar and a centralized service architecture, Yggdrasil brings tangible benefits in three main areas:

Scalability

  • High-Performance Engine: Cedar uses formal verification, a mathematical analysis technique, to guarantee properties such as termination. This proves that no policy can enter an infinite loop, ensuring that evaluation is always fast and predictable.
  • Caching Strategies: Yggdrasil implements an authorization decision cache. Once an ALLOW decision is made, it can be cached for a determined time (using the @cacheTTL annotation in the policy), drastically reducing latency for subsequent identical requests.

Auditability

  • Audit Logs: All authorization decisions (both allowed and denied) are logged, creating a complete and centralized audit trail. This is fundamental for security investigations, compliance, and understanding how access is being granted in practice.
  • Policy as Code: Yggdrasil policies are managed as code in a Git repository. This means that every policy change goes through a peer review process (Merge Request), with versioning and history. Policy validation is done during the CI/CD pipeline, ensuring that only syntactically correct and secure policies are deployed to production.

Reusability

  • Knowledge Sharing: By centralizing policies, we create a repository of institutional knowledge. Teams can learn from policies created by others, avoiding reinventing the wheel and spreading security best practices across the entire organization.
  • Best Practices Validation: The validation pipeline not only checks syntax but can also be extended to enforce business rules and security best practices, ensuring a high and consistent quality standard.

Conclusion

Yggdrasil represents a fundamental step in the maturity of iFood’s security architecture. By externalizing and centralizing authorization, we are not only mitigating security risks but also empowering our development teams so they can focus on what they do best: creating incredible products for our customers, partners, and delivery partners.

The journey is just beginning. We have plans to evolve Yggdrasil, adding more identity sources, refining our development tools, and exploring new policy patterns. We believe that by treating authorization as a first-class service, we are building a more secure, scalable, and resilient foundation for iFood’s future.

Share:
Caio Cavalcante

Caio Cavalcante

Security Engineer

Go to author page

Build the future at iFood

We are always looking for passionate developers, designers and data scientists to help us revolutionize the food delivery experience. Join iFood Tech and be part of building the future of food technology.

Discover our CareersArrow Right