Most security reviews I have sat through happen after the architecture is already frozen. The application team has picked the frameworks, drawn the boxes and arrows, and only then does someone ask how authentication and authorization actually work end to end. By that point, fixing a bad identity design usually means retrofitting workarounds instead of solving the problem properly.
Damien Bod’s article on application security context models proposes a fix for this sequencing problem: model the security architecture as a first-class part of the design, before the rest of the application gets built around it. I have used a similar approach on Azure projects for years, and this piece puts a name and a structure to something experienced architects often do informally. Below, I walk through the concept, why it matters more now than it did five years ago, and how to actually draw one of these models for a real solution.
Why the old perimeter model stopped being enough
Traditional application security thinking leaned heavily on network boundaries. Put a firewall at the edge, keep the database on a private subnet, and trust everything inside the perimeter. That model breaks down once you have SPAs calling APIs over the public internet, managed identities talking to Key Vault, and third party identity providers federating into your tenant.
Zero trust flips the emphasis from where a component sits on the network to how it proves who it is on every single call. Authentication and authorization become the actual security boundary, enforced locally by each component rather than assumed because of network placement. A security context model is simply a diagram and a supporting document that captures this: which identities exist, which flows they use, and which trust boundaries they cross.
What a security context model buys you
The value is mostly about moving effort earlier in the project, where it is cheaper. A few concrete benefits show up repeatedly on projects that adopt this practice.
- Security becomes part of the solution architecture instead of a patch applied after the fact, which avoids the usual pattern of duct-taped workarounds discovered during a pre-production review.
- Security reviews get faster and produce sharper findings, because the reviewer is reading a model that already reflects the real flows instead of reverse engineering them from code.
- Flawed security concepts, like mixing application and delegated permissions on one client, get caught on a whiteboard instead of in production.
- Ongoing support is simpler, since new engineers can look at one diagram to understand how identity flows through the system instead of tracing it through five repositories.
- SAST and other white box testing efforts have a map to follow, so testers know which flows and trust boundaries actually need scrutiny.
None of this is about producing more paperwork for its own sake. A model that nobody updates after month two is worse than no model, because it actively misleads people. Treat it as a living artifact that changes when the identity architecture changes, not a one time diagram for a design review deck.
What actually belongs in the diagram
A useful security context model needs to show a specific set of things, and it is tempting to either under-specify it into a generic box diagram or over-specify it into an unreadable mess. The article lays out six elements that should be present: interfaces to third party applications and their security definitions, the authentication and authorization clients, whether each client is an application type or a delegated type, the public, private and security zones, the authentication and authorization flow types used to acquire tokens, and an appendix that spells out each interface in plain language.
I will walk through each of these with the actual diagrams from the source article, since a text description of a security context model is far less useful than seeing one.
Showing interfaces to third party applications
The first thing worth capturing is which external identity providers and third party systems your solution talks to, and how. In the example below, a solution context uses Keycloak as its identity broker, which in turn federates to Azure AD and Azure B2C for two different user populations, plus an API that authenticates users directly through the same broker.

Just from this level of detail, a reviewer can already tell that Keycloak is the single point of federation and that neither Azure AD nor Azure B2C is called directly by the application components. That is a useful fact to know early, because it means a Keycloak outage takes down authentication for both user populations at once, which is exactly the kind of dependency you want flagged during design rather than discovered during an incident.
Marking clients as application type or delegated type
Every client in your architecture acquires tokens one of two ways. A delegated client gets a token on behalf of a signed in user, carrying that user’s identity and consented scopes. An application client, using something like the client credentials flow, gets a token that represents the application itself, with no user context at all.

The common mistake here is registering a single Azure App Registration and using it for both delegated and application permissions. It works technically, but it muddies the token, since a client credentials token issued from that registration would carry application permissions that were only ever meant for the delegated user flow, or vice versa. Keep application clients and delegated clients on separate registrations. It costs you one extra registration in the Azure portal and saves a genuinely confusing security review later.
Distinguishing application tokens from delegated tokens across multiple identity providers
Real solutions rarely stick to one identity provider. The diagram below shows a Blazor BFF and a separate ASP.NET Core Razor app, each acquiring delegated tokens from a different identity provider (Auth0 and Azure AD respectively), while both eventually call the same set of APIs using a mix of delegated and application tokens.

This is where the appendix becomes genuinely useful rather than decorative. Reading the diagram alone, it is not obvious which API endpoints accept an application token versus a delegated token. Write that down explicitly per interface. I have seen production incidents caused by an API accepting an application token for an endpoint that was only ever meant to be called with a delegated, user consented token, effectively bypassing per user authorization checks.
Marking public, private and security zones
Network zones still matter, just not as the primary security control. Showing which components sit in a public zone reachable from the internet versus a private zone reachable only internally helps a reviewer understand blast radius, even though each component is still expected to authenticate and authorize independently.

Note what this diagram is not claiming. It is not saying the APIs in the private zone are safe because they are unreachable from outside. It is saying that if an attacker did get into the private zone through some other path, these particular components would be the ones exposed, and each of them still needs its own authentication check. Zero trust does not mean you stop drawing network boundaries. It means you stop relying on them as your only line of defense.
Recording the actual flow types used
The flow type used to acquire a token matters as much as which client is asking for it. The client credentials flow, the authorization code flow with PKCE, and other OAuth2 grant types each carry different security guarantees, and mixing them up in a diagram or in an implementation is a common source of subtle bugs.

A rule worth stating plainly in your own model: a client application should never mint its own access tokens or invent a custom token format. Only standard, well reviewed OAuth2 and OpenID Connect flows should show up in these diagrams. If you find yourself needing a non-standard flow to make something work, that is usually a sign the architecture needs rethinking, not a sign you need a custom token.
Should network security components appear in the model at all?
This is a fair question, since the whole point of the model is to focus on authentication and authorization rather than network topology. The article’s answer, which matches my own experience, is to include network components only when they participate in identity flows. An API Management gateway that implements an OAuth2 client in front of your API belongs in the diagram. So does an application proxy that strips or injects HTTP security headers. A plain load balancer that does neither generally does not need to be there.
This keeps the diagram from turning into a full network topology map, which already exists elsewhere in most projects and serves a different audience. The security context model has one job: make identity and trust boundaries legible at a glance.
A complete worked example: Blazor BFF with Azure SQL
Putting all of the above together, here is a full security context model for a fairly common pattern: a Blazor application using the Backend for Frontend pattern, calling a downstream API that in turn talks to Azure SQL. The API and the database are both private, not reachable directly from the internet.

This single diagram already answers several questions a reviewer would otherwise have to dig for: the Blazor app is a confidential client using authorization code flow with PKCE, the token that reaches the API is a delegated user token rather than an application token, and neither component uses stored secrets to reach Key Vault or SQL, relying on managed identity instead. That last point alone removes an entire category of secret-leakage risk from the design conversation.
Writing the appendix
The diagram carries the shape of the system, but the appendix carries the detail a diagram cannot show cleanly. For the BFF example above, a reasonable appendix reads like this: the Blazor app reaches Key Vault using its own managed identity with restricted access, the API reaches Key Vault the same way with a separate managed identity, the Blazor app calls the API using a delegated user access token scoped and restricted to that specific App Registration client ID, the API reaches SQL using managed identity, and the Blazor app authenticates end users against Azure AD using the OpenID Connect code flow with PKCE as a confidential client.
Notice the appendix is written in plain sentences, not a table of acronyms. That is deliberate. A security reviewer who is not deeply embedded in your codebase should be able to read the appendix and understand exactly what each arrow in the diagram means, without needing a glossary.
Where this fits in a real project timeline
The honest answer is that most teams will not produce a perfect security context model on day one, and that is fine. Draw a rough version during initial architecture discussions, refine it once the identity providers and client registrations are actually decided, and treat it as a living document that gets updated whenever a new client, API, or third party integration is added. The cost of keeping it current is far lower than the cost of reconstructing it from scratch during an incident review.
One limitation worth naming: this approach works best for solutions where the team already has a baseline understanding of OAuth2 and OpenID Connect concepts. If your team is still learning the difference between an authorization code flow and a client credentials flow, invest in that foundation first. A security context model built on a shaky understanding of the underlying flows will just formalize the wrong assumptions.
Leave a Reply