M365 Show Podcast

Graph API Permissions & Consent Models Explained


Listen Later

Ever clicked 'Consent' in Azure and thought, 'Wait, what exactly am I allowing?' If you’ve struggled to figure out why your app demands admin approval—or why some permissions just seem to work and others don't—you're in the right spot. Today, we're cracking open what's *really* happening when Microsoft Graph asks for permissions and why the right consent model matters more than you think.The Permission Maze: Why Graph API Access Breaks When You Least Expect ItIf you've ever watched your Graph-powered app glide through every single test case in your dev tenant, only to detonate in production, you’re not alone. That silent optimism after a successful local run takes a pretty quick exit once actual users get involved, and the app suddenly greets everyone with a bland wall of “admin consent required” popups. For anyone who’s had the joy of a picture-perfect demo—and then been pulled into an incident call five minutes after launch—this is probably ringing all kinds of bells. Sometimes it feels like local environments are made out of trampoline mats, while production is a concrete bunker. The reality is, you can spend weeks building and testing, then face a production environment that blocks what worked fine on your developer tenant. And it’s somehow always just when people are actually watching.Let’s talk through that familiar story. You spin up a funky new app, wire up Graph to grab some data, maybe you use something like Power Automate to read everyone’s shared calendars—works the first time, looks good on your laptop, even the demo to the team goes off without a single glitch. But rollout day comes, and the app refuses to play ball. Instead of showing people’s calendars, you suddenly see requests for admin approval, or maybe you start picking apart cryptic error codes from Graph that basically translate to, “Permission denied.” And of course, this disaster didn’t show up when you tested with your dev accounts, which breezed through all the consent screens. The confusion spreads fast. Users ping support wondering why the process stalls. Your admin team quickly reminds you that nothing is getting past without compliance reviews and a dozen tickets. If it feels like you’re the only one, you’re not. According to recent data, over 60% of Graph API deployment issues trace straight back to misunderstood permission settings—not the Graph endpoints, authentication code, or even missing documentation.So what’s actually happening here? The difference between your playground dev tenant and the locked-down world of production is more dramatic than most people expect. In dev, almost everything defaults to open and easy, especially if you used the standard tenant creation tools. Default policies are lax. You, as the tenant admin, can click “Accept” for anything. Most permissions flow through with barely a question, and if you need to, you can flip a toggle and approve whatever you want. It’s paradise for building, but it leaves you completely insulated from what real-world deployment looks like.Production is a different game. Enterprises are terrified of apps gone rogue. Permissions are clamped down, and the ability to grant application-wide consent is usually restricted to a handful of global admins—people who do *not* want to see another third-party app sending mail to the CEO. Anything that could possibly expose organizational data to an outside party gets the brakes applied fast. Your innocent little Power Automate flow, which was just skimming calendars for team syncs, suddenly falls apart because the permissions you requested look completely different to the IT team than they did to your dev tenant.To put it in more concrete terms, the story usually plays out like this: You deploy a Power Automate flow that’s supposed to check when people are out of office. In test, it runs fine, reading calendar entries wherever you point it. In production, you see a stream of errors coming back from the Graph API. Maybe it’s Error AADSTS65001 or that classic “Need admin approval” message with no context. The support docs are vague, and the logs just end in dead ends. You dig around in Azure AD, start to realize that your app is asking for permissions that regular users can’t grant, and suddenly you’re making your first pitch to the security team about why you really, really need these rights.What’s really wild is how split the environments are. One feels permissive and helpful, the other is all locked doors and red tape—and most of the confusion has nothing to do with your code quality. It all comes back to how Graph handles permissions and, more specifically, the consent process. If you’re wondering what’s actually different between the setups, it’s not some hidden bug in the API. It all flows from which permissions your app is requesting, how those permissions interact with Microsoft’s consent system, and who gets to click ‘Accept.’Here’s the twist: almost every time permission errors show up, the problem isn’t really technical. It’s about how the permission model in Graph ties into consent, who owns that process, and how Microsoft expects you to walk the line between user empowerment and security. Once you understand that, things click into place.So, what’s the catch? Microsoft Graph actually has two separate permission models, and which path you choose can quietly determine whether your rollout flies or falls flat. In most cases, the setup you pick during your first week of development lives with you for the entire lifecycle of the app. Cut corners here, run into pain later.That’s why, before we build anything else, we need to break down how these two permission types frame everything your app can—and can’t—do. Let’s skip the jargon and actually look at what these permission models mean for real apps.Delegated vs. Application Permissions: What They Actually Mean For Your AppSo let's say you've built two apps, both want access to calendar data, but somehow they trigger completely different reactions when it’s time to let users in. One flows straight through the consent screen. The other? Suddenly hits an admin wall, no matter how many times you hit “Accept.” The docs might spell out permission types, but deciphering how they actually drive these different experiences in practice isn’t obvious until you run headfirst into the wall yourself.Here’s where things start to click: Microsoft Graph permissions branch down two very specific paths—delegated and application. Delegated permissions come into play when an actual user is signed in and using your app. You’re piggybacking off their identity, working in the bubble of what they’re already allowed to see and do. It’s like asking someone, “Can I use your key to check your mailbox?” and they say yes. You can only do what they’re allowed to do, no more. Application permissions, on the other hand, aren’t tied to anyone being logged in. These permissions let your app act as itself, all on its own—no user context required. This time, it’s like being handed the master key to the whole mailbox building, no oversight, no limit to which mailboxes you can open. That’s a massive leap in power.And here’s where most developers get tripped up. At a high level, delegated permissions seem friendlier—often, the user themselves can grant access just by signing in and clicking through the consent form. This lines up with what the typical user expects: “Sure, the app can read *my* calendar, because I’m the one using it.” There’s a kind of self-contained logic to it. Most people don’t realize that in the background, these delegated permissions keep your app tightly scoped to that single session and user identity. You want the calendar for Jane from Marketing? Jane has to sign in, and the app gets a token that only works for her data. It never sees anyone else’s mailbox, because it’s not allowed.But now let’s bounce to application permissions. The game changes. Instead of working under a user’s identity, application permissions let your app go to Graph on its own, whenever it wants—often as part of a background process, or an integration that syncs data overnight. Suddenly, the permission set isn’t limited to what a single person can access. The app could pull calendars for every employee, send messages on behalf of the whole org, or export data without anyone actively approving it in the moment. For obvious reasons, this is where the alarm bells go off in any security-conscious company.Microsoft isn’t subtle about the risks here, and for good reason. The documentation doesn’t bury the lead: application permissions give your app far more reach, and that’s where the heavy restrictions begin. In fact, research shows Microsoft continues to tighten default settings around app-only permissions almost every year, specifically because these represent the highest risk surface for enterprise data leaks. If you’re asking for a permission like Calendars.Read—all users—in an application context, it’s treated the same as asking for the root password.Let’s ground this in a real scenario. Imagine you’re building an Outlook add-in that lets users schedule meetings. With delegated permissions, each person signs in, gives your app access to *their* calendar, and that’s all the app touches. Consent is a breeze, because the risk is limited—only the signed-in user’s data is at stake, and they’re driving the consent themselves. Now, flip the script. You’re building an unattended export tool for HR that needs to process absence data for the whole organization. Now you’re venturing into application permissions: full org-wide calendar access, no user context, and no built-in oversight from individuals. This switch means it’s time for admin consent, security reviews, and often weeks of approval before rollout.This difference completely shapes the consent experience. With delegated permissions, users hold the keys—most can grant permission for themselves. But the second you need application permissions, everything stops for admin appr

Become a supporter of this podcast: https://www.spreaker.com/podcast/m365-show-podcast--6704921/support.
...more
View all episodesView all episodes
Download on the App Store

M365 Show PodcastBy Mirko