<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://knowledgebase.pirho.net/index.php?action=history&amp;feed=atom&amp;title=Choosing_the_Right_OAuth_2.0_Flow</id>
	<title>Choosing the Right OAuth 2.0 Flow - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://knowledgebase.pirho.net/index.php?action=history&amp;feed=atom&amp;title=Choosing_the_Right_OAuth_2.0_Flow"/>
	<link rel="alternate" type="text/html" href="https://knowledgebase.pirho.net/index.php?title=Choosing_the_Right_OAuth_2.0_Flow&amp;action=history"/>
	<updated>2026-07-11T15:39:49Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://knowledgebase.pirho.net/index.php?title=Choosing_the_Right_OAuth_2.0_Flow&amp;diff=397&amp;oldid=prev</id>
		<title>Dex: Created page with &quot;= Choosing the Right OAuth 2.0 Flow = == A Capability-Driven Approach ==  &#039;&#039;&#039;Summary:&#039;&#039;&#039;   OAuth 2.0 defines multiple authorization flows, each designed for a specific combination of identity type, risk profile, and operational context. Problems arise when these flows are treated as interchangeable or selected based purely on convenience. This article reframes OAuth flow selection as a capability- and channel-driven architectural decision.  ----  == Context ==  OAuth 2.0...&quot;</title>
		<link rel="alternate" type="text/html" href="https://knowledgebase.pirho.net/index.php?title=Choosing_the_Right_OAuth_2.0_Flow&amp;diff=397&amp;oldid=prev"/>
		<updated>2026-04-20T05:36:09Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;= Choosing the Right OAuth 2.0 Flow = == A Capability-Driven Approach ==  &amp;#039;&amp;#039;&amp;#039;Summary:&amp;#039;&amp;#039;&amp;#039;   OAuth 2.0 defines multiple authorization flows, each designed for a specific combination of identity type, risk profile, and operational context. Problems arise when these flows are treated as interchangeable or selected based purely on convenience. This article reframes OAuth flow selection as a capability- and channel-driven architectural decision.  ----  == Context ==  OAuth 2.0...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;= Choosing the Right OAuth 2.0 Flow =&lt;br /&gt;
== A Capability-Driven Approach ==&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Summary:&amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
OAuth 2.0 defines multiple authorization flows, each designed for a specific combination of identity type, risk profile, and operational context. Problems arise when these flows are treated as interchangeable or selected based purely on convenience. This article reframes OAuth flow selection as a capability- and channel-driven architectural decision.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Context ==&lt;br /&gt;
&lt;br /&gt;
OAuth 2.0 is often introduced by answering a narrow question:&lt;br /&gt;
&lt;br /&gt;
:&amp;#039;&amp;#039;“How do we get an access token?”&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The more important question is:&lt;br /&gt;
&lt;br /&gt;
:&amp;#039;&amp;#039;“What kind of identity is making this request, and under what conditions?”&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
OAuth flows encode assumptions about:&lt;br /&gt;
&lt;br /&gt;
* Human vs machine identity&lt;br /&gt;
* Interactive vs non-interactive use&lt;br /&gt;
* Token exposure risk&lt;br /&gt;
* Credential handling capability&lt;br /&gt;
&lt;br /&gt;
Choosing the wrong flow weakens a system even when every token is technically valid.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== OAuth Flows Are Not Variants ==&lt;br /&gt;
&lt;br /&gt;
A common misconception is that OAuth flows are simply different ways to reach the same outcome. In reality, each flow represents a distinct capability boundary.&lt;br /&gt;
&lt;br /&gt;
Choosing a flow implicitly answers:&lt;br /&gt;
&lt;br /&gt;
* Who is authenticating?&lt;br /&gt;
* Is a human present?&lt;br /&gt;
* Can secrets be stored securely?&lt;br /&gt;
* Can the user be redirected?&lt;br /&gt;
* Is long-lived access acceptable?&lt;br /&gt;
&lt;br /&gt;
Once issued, tokens inherit these assumptions.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Core OAuth Flows (Modern Reality) ==&lt;br /&gt;
&lt;br /&gt;
=== Authorization Code Flow ===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Best suited for&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* Server-side web applications&lt;br /&gt;
* Confidential clients&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Characteristics&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* User authenticates interactively&lt;br /&gt;
* Authorization code exchanged server-side&lt;br /&gt;
* Tokens never exposed to the browser&lt;br /&gt;
* Supports refresh tokens&lt;br /&gt;
&lt;br /&gt;
This flow maps cleanly to interactive user channels.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Authorization Code Flow with PKCE ===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Best suited for&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* Single-page applications (SPAs)&lt;br /&gt;
* Mobile applications&lt;br /&gt;
* Desktop applications&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;What PKCE adds&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* Cryptographic proof binding&lt;br /&gt;
* Protection against code interception&lt;br /&gt;
* No reliance on a client secret&lt;br /&gt;
&lt;br /&gt;
This is the modern default for public clients and replaces the Implicit Flow.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Client Credentials Flow ===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Best suited for&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* Service-to-service communication&lt;br /&gt;
* Background jobs&lt;br /&gt;
* Automation&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Characteristics&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* No user context&lt;br /&gt;
* Client authenticates directly&lt;br /&gt;
* Tokens represent a service identity&lt;br /&gt;
&lt;br /&gt;
Tokens issued via this flow must never authenticate user interfaces.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Device Authorization Flow ===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Best suited for&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* CLI tools&lt;br /&gt;
* Smart TVs&lt;br /&gt;
* IoT and constrained devices&lt;br /&gt;
&lt;br /&gt;
This flow enables human authentication without requiring a browser on the device itself.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Deprecated and Transitional Flows ==&lt;br /&gt;
&lt;br /&gt;
=== Resource Owner Password Credentials ===&lt;br /&gt;
&lt;br /&gt;
This flow exists only for legacy systems.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Risks&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* Client handles user passwords&lt;br /&gt;
* MFA is bypassed&lt;br /&gt;
* Zero-trust boundaries collapse&lt;br /&gt;
&lt;br /&gt;
If present, it must be tightly restricted and clearly marked as transitional.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Implicit Flow ===&lt;br /&gt;
&lt;br /&gt;
The Implicit Flow is deprecated.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Why&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* Tokens exposed in URLs and logs&lt;br /&gt;
* No refresh tokens&lt;br /&gt;
* No effective mitigations&lt;br /&gt;
&lt;br /&gt;
There is no modern justification for using it.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Flow Selection by Authentication Channel ==&lt;br /&gt;
&lt;br /&gt;
Rather than choosing flows per application, choose them per authentication channel.&lt;br /&gt;
&lt;br /&gt;
=== Interactive User Channel ===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Allowed&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* Authorization Code&lt;br /&gt;
* Authorization Code with PKCE&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Disallowed&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* Client Credentials&lt;br /&gt;
* Password Grant&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== First-Party API Client ===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Allowed&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* Client Credentials&lt;br /&gt;
* Authorization Code (on behalf of user)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Controls&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* Strict audience enforcement&lt;br /&gt;
* Static scope allow-lists&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Third-Party API Client ===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Allowed&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* Authorization Code with PKCE&lt;br /&gt;
* Client Credentials (approval-based)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Disallowed&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* Broad refresh tokens&lt;br /&gt;
* Wildcard scopes&lt;br /&gt;
&lt;br /&gt;
Scopes here should be treated like firewall rules.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Machine / Background Service ===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Allowed&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* Client Credentials only&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Disallowed&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* Any user-involved flows&lt;br /&gt;
* Refresh tokens&lt;br /&gt;
&lt;br /&gt;
These tokens must never authenticate human surfaces.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Legacy / Transitional Channel ===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Allowed&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* Explicitly whitelisted flows only&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Required safeguards&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* Reduced scope ceilings&lt;br /&gt;
* Short token lifetimes&lt;br /&gt;
* No refresh tokens&lt;br /&gt;
* Clear deprecation plan&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Common Failure Patterns ==&lt;br /&gt;
&lt;br /&gt;
* Using interactive flows for automation&lt;br /&gt;
* Accepting machine tokens on admin UIs&lt;br /&gt;
* Enabling password grants indefinitely&lt;br /&gt;
* Treating flows as client configuration rather than policy&lt;br /&gt;
&lt;br /&gt;
These are flow-selection failures, not cryptographic ones.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Conclusion ==&lt;br /&gt;
&lt;br /&gt;
OAuth 2.0 flows encode trust assumptions, identity models, and risk tolerance.&lt;br /&gt;
&lt;br /&gt;
Choose flows based on:&lt;br /&gt;
* Who is authenticating&lt;br /&gt;
* How interactive the channel is&lt;br /&gt;
* Where tokens will travel&lt;br /&gt;
* What assurance level is required&lt;br /&gt;
&lt;br /&gt;
When flows are selected deliberately, OAuth becomes a system of bounded capabilities rather than a loose token-minting service.&lt;/div&gt;</summary>
		<author><name>Dex</name></author>
	</entry>
</feed>