5 Warning Signs Your App Authorization is a Ticking Time Bomb

A poorly designed, implemented, or documented application authorization solution can lead to low feature velocity and serious security gaps. But how can you tell when your authorization logic is creating more problems than it solves?

At Oso, we’re obsessed with application authorization - we even wrote a datalog-inspired language to make creating and managing authorization policies a breeze.

In our time, we’ve helped companies like Wayfair, Oyster, and Duolingo re-architect their authorization systems. Through it all, we’ve seen some pretty gnarly authorization implementations. 

In this article, we hone in on five common code smells, architectural patterns, and business requirements that suggest your authorization solution is about to explode.

1. Your permissions “system” is a dictionary

It always starts out innocent enough. “Authorization is  simple”, they said. “Just use a dictionary. Fast lookups, easy to reference, import where needed”. 

Here's the problem - storing your access control policies in a dictionary or data class quickly becomes unmaintainable. As your application grows, so does the dictionary. 

You start out with some basic roles and permissions.

As your application grows, so does that dictionary. Maybe you need to add attribute-based access control (ABAC) or relationship-based access control (ReBAC). Soon, you’re writing nested dictionaries, complex conditional logic, all to add some basic access controls! What started as clean key-value pairs becomes a labyrinth of special cases and hard-coded exceptions. When a security audit comes knocking, good luck explaining why the VP of Sales can edit anyone's contact information, but only on Tuesdays.

Our recommendation at Oso is to implement a declarative authorization model that is built to express authorization logic. 

This is how we designed Oso’s authorization framework, so you can express complex permission logic in a readable, maintainable format that lives outside your app code, but integrates seamlessly with it. 

Example of ReBAC in Polar

2. You can’t update a role’s permissions without making changes in a dozen places

Your PM asks for a simple permission change: "Can we allow Editors to delete comments?". Cut to three days later, and you’re still hunting through controller methods, middleware functions, API endpoints, and UI components. 

A scattered approach to enforcement is a classic sign your authorization is reaching critical mass. Duplicated permissions logic makes even small changes expensive, and nearly guarantees inconsistencies. This can quickly lead to security vulnerabilities that won’t show up until your users stumble onto them.

Centralizing your authorization logic into its own service that serves as a single source of truth is the best way to create a maintainable permissions system. Roles and permissions are defined once, and enforced consistently.

Oso’s authorization API takes this approach, providing a single place to make permission changes that propagate through your application. Adding another service to your critical paths means latency and uptime are non-negotiable, which is why we designed Oso Cloud to be fault-tolerant and deployed on the edge, next to your other services.

3. Nobody can confidently answer “What exactly can an admin do again?”

It's the question that strikes fear into engineering teams: "Can you document all our permission models for compliance?" Cue the nervous laughter and sudden, prolonged PTO.

When your authorization model exists primarily in code and tribal knowledge, you're sitting on a compliance nightmare. SOC 2, GDPR, and HIPAA all require clear documentation of who can access what. If your answer involves tracing function calls across the codebase or saying "ask Dave, he built that part," you're in trouble. A proper authorization system doesn't just enforce rules—it makes them discoverable, auditable, and explainable to both engineers and auditors.

Oso provides not just policy enforcement, but tools to query and understand your authorization system. Policies are self-documenting and accessible to compliance teams. Oso also produces audit logs that explain exactly why an authorization decision was made, streamlining compliance.

4. Your customers will need custom roles and permissions in the near future

Great news! Your sales team just landed a major enterprise deal with one condition: the client needs custom role definitions. Your product team is ecstatic. Your engineering team is having heart palpitations.

If your authorization was built for a fixed set of roles, custom permissions will require a massive refactoring effort. Suddenly, hardcoded checks need to become dynamic evaluations. Your UI needs to adapt to permissions it didn't know could exist. All of this needs an admin interface that won't accidentally grant access to sensitive data. Without a flexible authorization framework designed for extensibility, you'll find yourself choosing between delaying launches, cutting corners on security, or turning down lucrative enterprise deals.

Instead, implement an authorization model designed for customization from the ground up. Oso's policy-as-code approach lets you define base roles and permissions while allowing for controlled extensibility. Its expression-based policies can accommodate customer-specific rules without major refactors, and its developer tools make it easy to test and validate custom roles before deployment. This approach lets you confidently offer enterprise-grade customization while maintaining security and avoiding engineering bottlenecks.

5. You're planning on breaking up your monolith into microservices

A microservices architecture promises scalability, team autonomy, and technological flexibility. What it doesn't advertise is the complexity of implementing authorization across those services.

When your monolith splits, your formerly centralized permissions must either fragment across services (leading to inconsistency) or become a dependency bottleneck (negating the benefits of microservices). Without a unified authorization approach that works across service boundaries, you'll be rebuilding the same permission logic in every language and framework your team adopts. Each service becomes its own authorization fiefdom, with different rules and security standards. Before your first microservice launches, you need an authorization strategy that maintains consistency.

We recommend deploying an authorization service designed for distributed systems. Oso Cloud provides a centralized authorization service with distributed enforcement points, allowing each microservice to make consistent permission decisions without tight coupling. Its language-agnostic API means teams can implement authorization in their service of choice, while policy management remains centralized. This approach gives you the best of both worlds: consistent security with the flexibility microservices demand.

Wrapping Up

If you recognized your codebase in these warning signs, you're not alone. Authorization is inherently complex, and every engineering team eventually hits these walls. The good news is that authorization patterns are well-understood. You don't have to reinvent the wheel.

At Oso, we've distilled these patterns into a sturdy and flexible framework. Our authorization platform provides a central source of truth for permissions, a declarative language for expressing complex rules, and integration points for any part of your stack. 

Whether you're fixing an authorization system on the brink or building one that will scale with your business, we're here to help. So, when it’s time to defuse that time bomb, reach out for a chat with one of our engineers, or Try Oso for free. In the meantime, check out The Authorization Academy to familiarize yourself with authz fundamentals.

Want us to remind you?
We'll email you before the event with a friendly reminder.

Write your first policy