{"id":3416,"date":"2026-05-11T04:59:51","date_gmt":"2026-05-11T02:59:51","guid":{"rendered":"https:\/\/deepdocs.dev\/?p=3416"},"modified":"2026-05-18T05:11:22","modified_gmt":"2026-05-18T03:11:22","slug":"what-is-oauth-2","status":"publish","type":"post","link":"https:\/\/deepdocs.dev\/what-is-oauth-2\/","title":{"rendered":"What is OAuth2? A Practical Guide for Developers"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Most developers first meet OAuth 2.0 during a GitHub integration. You install a tool, click <strong>Authorize<\/strong>, and GitHub asks whether that app can read or write specific things in your account. That moment answers the practical version of <strong>what is oauth2<\/strong> better than most specs do.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A few points matter more than the rest:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>OAuth 2.0 is about delegated authorization<\/strong>, not handing your password to another app.<\/li>\n\n\n\n<li><strong>The safest common pattern is Authorization Code with PKCE<\/strong>, especially for apps with a user interface.<\/li>\n\n\n\n<li><strong>The dangerous mistakes are usually implementation mistakes<\/strong>, not protocol mistakes. Missing <code>state<\/code>, loose <code>redirect_uri<\/code> handling, and broad scopes cause real trouble.<\/li>\n\n\n\n<li><strong>OAuth 2.0 is not authentication.<\/strong> If you need identity, that\u2019s where OpenID Connect comes in.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Why Modern Apps Ask for Permissions Not Passwords<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You\u2019re wiring up a GitHub app for a CI job, docs bot, analytics tool, or internal platform utility. If that app asks for your GitHub password, the conversation should end there.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Modern apps redirect you to GitHub because the right pattern is <strong>permission delegation<\/strong>. GitHub handles the login and consent screen. Your app gets limited access after the user approves it. That\u2019s OAuth 2.0 doing its job.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/cdnimg.co\/c5154994-a2fe-43c0-a286-28e433de4fd1\/91837a41-55fc-42e3-a4f5-22751d010134\/what-is-oauth2-app-authorization.jpg?ssl=1\" alt=\"A hand pressing an Allow Access button on an App Authorization screen with GitHub icon and security badge.\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That model won because it scales across products and ecosystems. <a href=\"https:\/\/www.arcade.dev\/blog\/authenticated-integration-metrics\/\">Arcade notes that OAuth 2.0 has reached 15,989 companies across 105 countries<\/a>, which lines up with what most engineering teams already see in practice. If an API platform supports third-party access, OAuth 2.0 is usually somewhere in the picture.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Why passwords are the wrong tool<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Passwords create an ugly trust boundary:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>The app can overreach:<\/strong> once it has credentials, it often has more access than it needs.<\/li>\n\n\n\n<li><strong>Rotation gets painful:<\/strong> changing a password can break multiple integrations at once.<\/li>\n\n\n\n<li><strong>Security review gets harder:<\/strong> auditors and platform teams now have to reason about credential storage, reuse, and exposure.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">API keys are better for some server-to-server cases, but they still require careful handling. If you work with transactional email or service integrations, this <a href=\"https:\/\/buildemotion.com\/blog\/sendgrid-api-key\">SendGrid API key guide from Build Emotion<\/a> is a useful comparison point because it shows the operational side of managing scoped secrets versus sharing broad credentials.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Practical rule:<\/strong> If a tool is acting on behalf of a user in GitHub, Google, or Microsoft, password sharing is the wrong shape of solution.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Understanding the Core Concepts of OAuth 2.0<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The spec can feel abstract until you map the moving parts to something familiar. The hotel key card analogy still works because it explains both the security model and the developer ergonomics.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/cdnimg.co\/c5154994-a2fe-43c0-a286-28e433de4fd1\/c07c1acb-0b36-40c5-a774-283541574e11\/what-is-oauth2-oauth-process.jpg?ssl=1\" alt=\"A diagram illustrating the OAuth 2.0 flow, detailing the key roles of Resource Owner, Client, Authorization Server, and Resource Server.\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The four roles<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In <a href=\"https:\/\/oauth.net\/2\/\">RFC 6749 as summarized by oauth.net<\/a>, OAuth 2.0 defines four core roles:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><th>Role<\/th><th>Plain-English meaning<\/th><th>GitHub example<\/th><\/tr><tr><td><strong>Resource Owner<\/strong><\/td><td>The person who controls the data<\/td><td>The GitHub user<\/td><\/tr><tr><td><strong>Client<\/strong><\/td><td>The app requesting access<\/td><td>Your SaaS app or internal tool<\/td><\/tr><tr><td><strong>Authorization Server<\/strong><\/td><td>The system issuing tokens after approval<\/td><td>GitHub\u2019s authorization service<\/td><\/tr><tr><td><strong>Resource Server<\/strong><\/td><td>The API holding protected data<\/td><td>GitHub API endpoints<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The hotel version is simple. The <strong>resource owner<\/strong> is the guest. The <strong>client<\/strong> is the delivery app asking for access. The <strong>authorization server<\/strong> is the front desk issuing a temporary card. The <strong>resource server<\/strong> is the door lock that accepts or rejects that card.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You never hand the delivery app your room key. You let the hotel issue a restricted card.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If your team likes sharper terminology writeups before touching auth code, this overview of <a href=\"https:\/\/omophub.com\/blog\/api-terminology\">essential API vocabulary for OMOP<\/a> is useful because it reinforces the difference between identity, authorization, resources, and clients.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The objects you deal with in code<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Teams often spend less time thinking about the roles and more time handling the artifacts:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><p><strong>Access token<\/strong><br>The credential your client presents to the API. It represents granted permission.<\/p><\/li>\n\n\n\n<li><p><strong>Refresh token<\/strong><br>A way to obtain a new access token without asking the user to approve the app again.<\/p><\/li>\n\n\n\n<li><p><strong>Scopes<\/strong><br>The boundaries of allowed actions. In practice, scopes answer \u201caccess to what, exactly?\u201d<\/p><br><\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">OAuth works best when scopes are small, boring, and explicit.<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">That last part matters. When an integration asks for broad repo access just because it\u2019s easier, you\u2019re borrowing trouble. Good OAuth implementations ask for the smallest scope set that still lets the product work.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A Developer&#8217;s Guide to OAuth 2.0 Grant Flows<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">OAuth 2.0 is a framework, not one single request pattern. The first engineering decision is choosing the flow that matches the client you\u2019re building.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/cdnimg.co\/c5154994-a2fe-43c0-a286-28e433de4fd1\/03dee82f-7f8d-4fb5-8ebd-4771a18ae665\/what-is-oauth2-authorization-flows.jpg?ssl=1\" alt=\"A hand-drawn diagram illustrating various OAuth 2.0 authorization flows for web, mobile, and server applications.\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Authorization Code flow<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This is the one teams should generally reach for when a user is involved.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The rough sequence looks like this:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Your app redirects the user to the authorization server.<\/li>\n\n\n\n<li>The user logs in and approves scopes.<\/li>\n\n\n\n<li>The authorization server redirects back with an authorization code.<\/li>\n\n\n\n<li>Your backend exchanges that code for tokens.<\/li>\n\n\n\n<li>Your app calls the resource server with the access token.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">This is a good fit for:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Web apps with a backend<\/strong><\/li>\n\n\n\n<li><strong>GitHub integrations that act for a signed-in user<\/strong><\/li>\n\n\n\n<li><strong>Developer tools that need explicit consent before reading or writing resources<\/strong><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">A simplified request often looks like this:<\/p>\n\n\n<div class=\"wp-block-code\">\n\t<div class=\"cm-editor\">\n\t\t<div class=\"cm-scroller\">\n\t\t\t\n<pre>\n<code class=\"language-http\"><div class=\"cm-line\"><span class=\"tok-keyword\">GET<\/span> <span class=\"tok-string2\">\/authorize?<\/span><\/div><div class=\"cm-line\">  <span class=\"tok-invalid\">response_type=code&amp;<\/span><\/div><div class=\"cm-line\"><span class=\"tok-string\">  client_id=YOUR_CLIENT_ID&amp;<\/span><\/div><div class=\"cm-line\"><span class=\"tok-string\">  redirect_uri=https:\/\/app.example.com\/callback&amp;<\/span><\/div><div class=\"cm-line\"><span class=\"tok-string\">  scope=repo&amp;<\/span><\/div><div class=\"cm-line\"><span class=\"tok-string\">  state=RANDOM_SESSION_VALUE<\/span><\/div><div class=\"cm-line\"><\/div><\/code><\/pre>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">And the token exchange:<\/p>\n\n\n<div class=\"wp-block-code\">\n\t<div class=\"cm-editor\">\n\t\t<div class=\"cm-scroller\">\n\t\t\t\n<pre>\n<code class=\"language-http\"><div class=\"cm-line\"><span class=\"tok-keyword\">POST<\/span> <span class=\"tok-string2\">\/token<\/span><\/div><div class=\"cm-line\"><span class=\"tok-invalid\">Content-Type: application\/x-www-form-urlencoded<\/span><\/div><div class=\"cm-line\"><\/div><div class=\"cm-line\">grant_type=authorization_code&amp;<\/div><div class=\"cm-line\">code=AUTH_CODE&amp;<\/div><div class=\"cm-line\">redirect_uri=https:\/\/app.example.com\/callback&amp;<\/div><div class=\"cm-line\">client_id=YOUR_CLIENT_ID&amp;<\/div><div class=\"cm-line\">client_secret=YOUR_CLIENT_SECRET<\/div><div class=\"cm-line\"><\/div><\/code><\/pre>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">The design choice that matters is this: <strong>the token exchange happens off the front end<\/strong>. That reduces exposure and gives you a better place to enforce policy, logging, and token handling.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Client Credentials flow<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This flow is for machine-to-machine access. No user approval screen. No user session. The client is acting as itself.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Typical examples:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>a background worker<\/li>\n\n\n\n<li>a CI\/CD service<\/li>\n\n\n\n<li>an internal daemon calling a protected API<\/li>\n\n\n\n<li>a scheduled sync job<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The client authenticates directly with the authorization server and receives an access token tied to the app\u2019s own identity and scopes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That distinction matters operationally. If a nightly job updates metadata or triggers internal automation, you usually want <strong>application identity<\/strong>, not user identity.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Device-style approval patterns<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Some apps can\u2019t easily show a full browser login experience where the action starts. CLIs, TVs, and constrained devices often send the user to approve access somewhere else, then poll or wait for completion.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The same delegated authorization idea applies. The difference is user experience, not the underlying trust model.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For teams building API-first products, auth and API design collide. Deep API shape still matters after auth is in place. This walkthrough on <a href=\"https:\/\/deepdocs.dev\/how-to-make-an-api\/\">how to make an API<\/a> is a good companion because a secure token is only half the story. The resource endpoints still need sensible permissions, naming, and lifecycle handling.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A short explainer is worth watching before implementing your own flow decisions:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><iframe width=\"100%\" style=\"aspect-ratio: 16 \/ 9;\" src=\"https:\/\/www.youtube.com\/embed\/tpIXmmV4ib4\" frameborder=\"0\" allow=\"autoplay; encrypted-media\" allowfullscreen=\"\"><\/iframe><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Which one should you pick<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Here\u2019s the decision rule I give teams:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>There is a user approving access<\/strong>. Use Authorization Code.<\/li>\n\n\n\n<li><strong>There is no user and the app is acting on its own behalf<\/strong>. Use Client Credentials.<\/li>\n\n\n\n<li><strong>The user can\u2019t conveniently complete auth on that device<\/strong>. Use a device-oriented approval flow.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">What doesn\u2019t work well is forcing one flow into every use case. That\u2019s how teams end up with fragile front-end token handling or service jobs pretending to be users.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Why PKCE is Now Essential for Secure Apps<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">PKCE is no longer an optional hardening trick. It\u2019s table stakes for modern OAuth.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The current guidance is direct. <a href=\"https:\/\/oauth.net\/2.1\/\">OAuth 2.1 says PKCE is required for clients using the authorization code flow<\/a>. The client creates a high-entropy <code>code_verifier<\/code> with <strong>43-128 characters<\/strong>, sends the SHA256 hash as the <code>code_challenge<\/code>, and later proves possession by sending the original verifier to the token endpoint.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/cdnimg.co\/c5154994-a2fe-43c0-a286-28e433de4fd1\/dd1391a7-4960-4b59-8652-8f9eb63cfc0e\/what-is-oauth2-pkce-security.jpg?ssl=1\" alt=\"A hand-drawn illustration showing a secure shield and padlock protecting both a native app and SPA.\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What problem PKCE solves<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Without PKCE, an attacker who intercepts the authorization code may be able to exchange it for tokens. That\u2019s the core failure mode.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">With PKCE:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>the client generates a secret per auth request<\/li>\n\n\n\n<li>the server only sees the hash up front<\/li>\n\n\n\n<li>the token endpoint requires the original secret later<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">If someone steals the code but doesn\u2019t have the verifier, the exchange fails.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Use PKCE even when a library makes it feel optional. Good defaults beat remembered advice.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">What implementation looks like<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The pattern is straightforward:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Generate a random <code>code_verifier<\/code>.<\/li>\n\n\n\n<li>Derive a <code>code_challenge<\/code> from it, typically with SHA256.<\/li>\n\n\n\n<li>Send the challenge during the authorization request.<\/li>\n\n\n\n<li>Send the original verifier during the token exchange.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">A skeletal example:<\/p>\n\n\n<div class=\"wp-block-code\">\n\t<div class=\"cm-editor\">\n\t\t<div class=\"cm-scroller\">\n\t\t\t\n<pre>\n<code><div class=\"cm-line\">code_verifier = random-high-entropy-string<\/div><div class=\"cm-line\">code_challenge = BASE64URL(SHA256(code_verifier))<\/div><div class=\"cm-line\">code_challenge_method = S256<\/div><div class=\"cm-line\"><\/div><\/code><\/pre>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">Then:<\/p>\n\n\n<div class=\"wp-block-code\">\n\t<div class=\"cm-editor\">\n\t\t<div class=\"cm-scroller\">\n\t\t\t\n<pre>\n<code class=\"language-http\"><div class=\"cm-line\"><span class=\"tok-keyword\">GET<\/span> <span class=\"tok-string2\">\/authorize?...&amp;code_challenge=...&amp;code_challenge_method=S256<\/span><\/div><div class=\"cm-line\"><\/div><\/code><\/pre>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">Later:<\/p>\n\n\n<div class=\"wp-block-code\">\n\t<div class=\"cm-editor\">\n\t\t<div class=\"cm-scroller\">\n\t\t\t\n<pre>\n<code class=\"language-http\"><div class=\"cm-line\"><span class=\"tok-keyword\">POST<\/span> <span class=\"tok-string2\">\/token<\/span><\/div><div class=\"cm-line\"><span class=\"tok-invalid\">...<\/span><\/div><div class=\"cm-line\"><span class=\"tok-invalid\">code_verifier=ORIGINAL_VALUE<\/span><\/div><div class=\"cm-line\"><\/div><\/code><\/pre>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">For native apps, browser-based apps, and developer tools with user login, PKCE closes an attack path that\u2019s too easy to leave open if you rely on old examples or weak defaults.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Common OAuth 2.0 Security Pitfalls to Avoid<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Most OAuth incidents don\u2019t come from misunderstanding the headline concept. They come from small implementation shortcuts.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Missing state validation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A <code>state<\/code> value binds the authorization request to the client session. The OAuth threat model guidance is clear that this is a key defense against CSRF in OAuth flows.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If your app sends <code>state<\/code>, then ignores it on return, you haven\u2019t protected anything.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">What good looks like:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>generate a fresh, unpredictable <code>state<\/code> value<\/li>\n\n\n\n<li>store it server-side or bind it to a signed session<\/li>\n\n\n\n<li>reject the callback if it doesn\u2019t match exactly<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Loose redirect handling<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The same threat model guidance says the <code>redirect_uri<\/code> should exactly match a pre-registered value. \u201cClose enough\u201d matching is where open redirect problems start.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bad patterns include:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>wildcard-like behavior<\/li>\n\n\n\n<li>substring matching<\/li>\n\n\n\n<li>accepting environment-driven callback values without validation<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Good patterns are stricter:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Pre-register every callback URI<\/strong><\/li>\n\n\n\n<li><strong>Require exact string matching<\/strong><\/li>\n\n\n\n<li><strong>Fail closed when the callback isn\u2019t recognized<\/strong><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Teams that operate across multiple app surfaces often underestimate this. If you\u2019re also managing certificates across subdomains, this guide to <a href=\"https:\/\/uptimewebhosting.com.au\/security\/wildcard-ssl-certificate\/\">protecting multiple subdomains<\/a> is useful background because transport security and callback discipline usually need to be reviewed together.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Token leakage and overbroad access<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Tokens leak when teams put them in the wrong places or ask for too much power.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A few habits prevent a lot of pain:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Keep tokens out of URLs:<\/strong> URLs end up in logs, browser history, and referrer chains.<\/li>\n\n\n\n<li><strong>Store tokens carefully:<\/strong> front-end accessible storage is convenient, but convenience and security usually conflict.<\/li>\n\n\n\n<li><strong>Ask for narrow scopes:<\/strong> if an app only needs repo metadata, don\u2019t ask for broad write access.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">There\u2019s a good connection here to general API design discipline. This guide on <a href=\"https:\/\/deepdocs.dev\/rest-api-best-practices\/\">REST API best practices<\/a> pairs well with OAuth work because permission boundaries only hold up when your endpoints and resource model are also well-designed.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">The safest OAuth implementation is usually the one that says \u201cno\u201d by default and adds capability one scope at a time.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">OAuth 2.0 vs OAuth 1.0 and OpenID Connect<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Two comparisons cause the most confusion in reviews and architecture docs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">OAuth 2.0 versus OAuth 1.0<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">OAuth 2.0 replaced a more cumbersome model. <a href=\"https:\/\/fusionauth.io\/articles\/oauth\/differences-between-oauth-2-oauth-2-1\">FusionAuth\u2019s summary of the evolution from OAuth 1.0 to OAuth 2.0<\/a> points to the key reason teams embraced it: OAuth 2.0 removed the client-side signature complexity that made OAuth 1.0 harder to implement.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That change mattered in practice. OAuth 2.0, released in <strong>October 2012<\/strong> as <strong>RFC 6749 and RFC 6750<\/strong>, defined the now-familiar roles and grant types and became the standard framework for delegated web authorization.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The trade-off is familiar to any engineer who has worked on auth. Simpler developer experience improves adoption, but flexibility also creates room for misconfiguration. That\u2019s why later extensions and best practices became so important.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">OAuth 2.0 versus OpenID Connect<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This is the distinction teams get wrong most often.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>OAuth 2.0 answers<\/strong>: what is this app allowed to do?<br><strong>OpenID Connect answers<\/strong>: who is this user?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That sounds obvious until you look at real integrations. <a href=\"https:\/\/www.onelogin.com\/learn\/what-is-oauth-2\">OneLogin notes that Stack Overflow has over 15,000 OAuth-related questions tagged with \u201csecurity\u201d or \u201cauthentication\u201d and that a common point of failure is treating OAuth 2.0 as direct authentication<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you need login, identity claims, and a reliable answer to \u201cwhich user is this,\u201d OAuth alone is incomplete. OpenID Connect adds the identity layer on top.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A simple rule helps:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Use OAuth 2.0<\/strong> when you need delegated API access.<\/li>\n\n\n\n<li><strong>Use OpenID Connect<\/strong> when you need user sign-in and identity.<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">If your product says \u201cSign in with X,\u201d you\u2019re usually in OpenID Connect territory, even though OAuth is still underneath.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Your OAuth 2.0 Implementation Checklist<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Most auth bugs come from skipping one of the basics during implementation review. A short checklist catches a lot.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The checklist<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Pick the correct flow:<\/strong> user-facing apps should generally use Authorization Code with PKCE. Background jobs should use a machine-oriented flow.<\/li>\n\n\n\n<li><strong>Validate <code>state<\/code> every time:<\/strong> generate it, bind it to the session, and reject mismatches.<\/li>\n\n\n\n<li><strong>Lock down <code>redirect_uri<\/code>:<\/strong> require exact matches against pre-registered values.<\/li>\n\n\n\n<li><strong>Request small scopes:<\/strong> start with the least privilege the feature can function with.<\/li>\n\n\n\n<li><strong>Handle token lifecycle deliberately:<\/strong> plan for expiry, refresh, revocation, and error states.<\/li>\n\n\n\n<li><strong>Keep tokens out of easy-to-leak locations:<\/strong> don\u2019t choose storage based only on convenience.<\/li>\n\n\n\n<li><strong>Separate auth from identity needs:<\/strong> if the feature needs login, model that with OpenID Connect.<\/li>\n\n\n\n<li><strong>Review your API surface too:<\/strong> auth can\u2019t rescue a messy resource model or overpowered endpoints. This guide to <a href=\"https:\/\/deepdocs.dev\/open-api-documentation\/\">OpenAPI documentation<\/a> is a practical follow-up if you\u2019re documenting protected APIs for internal and external consumers.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">A good OAuth implementation feels uneventful. The user approves the right permissions, the app receives the minimum access it needs, and the failure cases are explicit instead of surprising.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If your team is building GitHub-native tooling, <a href=\"https:\/\/deepdocs.dev\">DeepDocs<\/a> is worth a look. It keeps documentation in sync with code changes through your GitHub workflow, which is especially useful for teams maintaining protected APIs, SDK docs, onboarding guides, and fast-moving repos where auth-related behavior tends to drift out of date.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Most developers first meet OAuth 2.0 during a GitHub integration. You install a tool, click Authorize, and GitHub asks whether that app can read or write specific things in your account. That moment answers the practical version of what is oauth2 better than most specs do. A few points matter more than the rest: Why&#8230;<\/p>\n","protected":false},"author":259061979,"featured_media":3417,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_wpcom_ai_launchpad_first_post":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"_wpas_customize_per_network":false,"jetpack_post_was_ever_published":false},"categories":[1],"tags":[],"class_list":["post-3416","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.0 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>What is OAuth2? A Practical Guide for Developers | DeepDocs<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/deepdocs.dev\/what-is-oauth-2\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"What is OAuth2? A Practical Guide for Developers | DeepDocs\" \/>\n<meta property=\"og:description\" content=\"Most developers first meet OAuth 2.0 during a GitHub integration. You install a tool, click Authorize, and GitHub asks whether that app can read or write specific things in your account. That moment answers the practical version of what is oauth2 better than most specs do. A few points matter more than the rest: Why...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/deepdocs.dev\/what-is-oauth-2\/\" \/>\n<meta property=\"og:site_name\" content=\"DeepDocs\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/profile.php?id=61560455754198\" \/>\n<meta property=\"article:published_time\" content=\"2026-05-11T02:59:51+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-05-18T03:11:22+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/deepdocs.dev\/wp-content\/uploads\/2026\/05\/what-is-oauth2-developer-guide-1.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1312\" \/>\n\t<meta property=\"og:image:height\" content=\"736\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Neel Das\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@Nilzkool\" \/>\n<meta name=\"twitter:site\" content=\"@Nilzkool\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Neel Das\" \/>\n\t<meta name=\"twitter:label2\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/deepdocs.dev\\\/what-is-oauth-2\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/deepdocs.dev\\\/what-is-oauth-2\\\/\"},\"author\":{\"name\":\"Neel Das\",\"@id\":\"https:\\\/\\\/deepdocs.dev\\\/#\\\/schema\\\/person\\\/cf2ace6ae4dae8b34ab48a3e833ceede\"},\"headline\":\"What is OAuth2? A Practical Guide for Developers\",\"datePublished\":\"2026-05-11T02:59:51+00:00\",\"dateModified\":\"2026-05-18T03:11:22+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/deepdocs.dev\\\/what-is-oauth-2\\\/\"},\"wordCount\":2180,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/deepdocs.dev\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/deepdocs.dev\\\/what-is-oauth-2\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/deepdocs.dev\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/what-is-oauth2-developer-guide-1.jpg?fit=1312%2C736&ssl=1\",\"articleSection\":[\"Uncategorized\"],\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/deepdocs.dev\\\/what-is-oauth-2\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/deepdocs.dev\\\/what-is-oauth-2\\\/\",\"url\":\"https:\\\/\\\/deepdocs.dev\\\/what-is-oauth-2\\\/\",\"name\":\"What is OAuth2? A Practical Guide for Developers | DeepDocs\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/deepdocs.dev\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/deepdocs.dev\\\/what-is-oauth-2\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/deepdocs.dev\\\/what-is-oauth-2\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/deepdocs.dev\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/what-is-oauth2-developer-guide-1.jpg?fit=1312%2C736&ssl=1\",\"datePublished\":\"2026-05-11T02:59:51+00:00\",\"dateModified\":\"2026-05-18T03:11:22+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/deepdocs.dev\\\/what-is-oauth-2\\\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/deepdocs.dev\\\/what-is-oauth-2\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/deepdocs.dev\\\/what-is-oauth-2\\\/#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/deepdocs.dev\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/what-is-oauth2-developer-guide-1.jpg?fit=1312%2C736&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/deepdocs.dev\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/what-is-oauth2-developer-guide-1.jpg?fit=1312%2C736&ssl=1\",\"width\":1312,\"height\":736},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/deepdocs.dev\\\/what-is-oauth-2\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/deepdocs.dev\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"What is OAuth2? A Practical Guide for Developers\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/deepdocs.dev\\\/#website\",\"url\":\"https:\\\/\\\/deepdocs.dev\\\/\",\"name\":\"DeepDocs\",\"description\":\"Fix Your Outdated GitHub Docs on Autopilot\",\"publisher\":{\"@id\":\"https:\\\/\\\/deepdocs.dev\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/deepdocs.dev\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/deepdocs.dev\\\/#organization\",\"name\":\"DeepDocs\",\"url\":\"https:\\\/\\\/deepdocs.dev\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/deepdocs.dev\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/deepdocs.dev\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/6.jpg?fit=408%2C400&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/deepdocs.dev\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/6.jpg?fit=408%2C400&ssl=1\",\"width\":408,\"height\":400,\"caption\":\"DeepDocs\"},\"image\":{\"@id\":\"https:\\\/\\\/deepdocs.dev\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/profile.php?id=61560455754198\",\"https:\\\/\\\/x.com\\\/Nilzkool\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/deepdocs-dev\",\"https:\\\/\\\/www.youtube.com\\\/@DrNeelDas\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/deepdocs.dev\\\/#\\\/schema\\\/person\\\/cf2ace6ae4dae8b34ab48a3e833ceede\",\"name\":\"Neel Das\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/227924e7431a87895450dcd654b650e5011891dcba027fd9c782941985cbbb2d?s=96&d=identicon&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/227924e7431a87895450dcd654b650e5011891dcba027fd9c782941985cbbb2d?s=96&d=identicon&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/227924e7431a87895450dcd654b650e5011891dcba027fd9c782941985cbbb2d?s=96&d=identicon&r=g\",\"caption\":\"Neel Das\"},\"sameAs\":[\"http:\\\/\\\/neeldasf2ac55feaf.wordpress.com\"],\"url\":\"https:\\\/\\\/deepdocs.dev\\\/author\\\/neeldasf2ac55feaf\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"What is OAuth2? A Practical Guide for Developers | DeepDocs","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/deepdocs.dev\/what-is-oauth-2\/","og_locale":"en_GB","og_type":"article","og_title":"What is OAuth2? A Practical Guide for Developers | DeepDocs","og_description":"Most developers first meet OAuth 2.0 during a GitHub integration. You install a tool, click Authorize, and GitHub asks whether that app can read or write specific things in your account. That moment answers the practical version of what is oauth2 better than most specs do. A few points matter more than the rest: Why...","og_url":"https:\/\/deepdocs.dev\/what-is-oauth-2\/","og_site_name":"DeepDocs","article_publisher":"https:\/\/www.facebook.com\/profile.php?id=61560455754198","article_published_time":"2026-05-11T02:59:51+00:00","article_modified_time":"2026-05-18T03:11:22+00:00","og_image":[{"width":1312,"height":736,"url":"https:\/\/deepdocs.dev\/wp-content\/uploads\/2026\/05\/what-is-oauth2-developer-guide-1.jpg","type":"image\/jpeg"}],"author":"Neel Das","twitter_card":"summary_large_image","twitter_creator":"@Nilzkool","twitter_site":"@Nilzkool","twitter_misc":{"Written by":"Neel Das","Estimated reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/deepdocs.dev\/what-is-oauth-2\/#article","isPartOf":{"@id":"https:\/\/deepdocs.dev\/what-is-oauth-2\/"},"author":{"name":"Neel Das","@id":"https:\/\/deepdocs.dev\/#\/schema\/person\/cf2ace6ae4dae8b34ab48a3e833ceede"},"headline":"What is OAuth2? A Practical Guide for Developers","datePublished":"2026-05-11T02:59:51+00:00","dateModified":"2026-05-18T03:11:22+00:00","mainEntityOfPage":{"@id":"https:\/\/deepdocs.dev\/what-is-oauth-2\/"},"wordCount":2180,"commentCount":0,"publisher":{"@id":"https:\/\/deepdocs.dev\/#organization"},"image":{"@id":"https:\/\/deepdocs.dev\/what-is-oauth-2\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/05\/what-is-oauth2-developer-guide-1.jpg?fit=1312%2C736&ssl=1","articleSection":["Uncategorized"],"inLanguage":"en-GB","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/deepdocs.dev\/what-is-oauth-2\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/deepdocs.dev\/what-is-oauth-2\/","url":"https:\/\/deepdocs.dev\/what-is-oauth-2\/","name":"What is OAuth2? A Practical Guide for Developers | DeepDocs","isPartOf":{"@id":"https:\/\/deepdocs.dev\/#website"},"primaryImageOfPage":{"@id":"https:\/\/deepdocs.dev\/what-is-oauth-2\/#primaryimage"},"image":{"@id":"https:\/\/deepdocs.dev\/what-is-oauth-2\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/05\/what-is-oauth2-developer-guide-1.jpg?fit=1312%2C736&ssl=1","datePublished":"2026-05-11T02:59:51+00:00","dateModified":"2026-05-18T03:11:22+00:00","breadcrumb":{"@id":"https:\/\/deepdocs.dev\/what-is-oauth-2\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/deepdocs.dev\/what-is-oauth-2\/"]}]},{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/deepdocs.dev\/what-is-oauth-2\/#primaryimage","url":"https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/05\/what-is-oauth2-developer-guide-1.jpg?fit=1312%2C736&ssl=1","contentUrl":"https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/05\/what-is-oauth2-developer-guide-1.jpg?fit=1312%2C736&ssl=1","width":1312,"height":736},{"@type":"BreadcrumbList","@id":"https:\/\/deepdocs.dev\/what-is-oauth-2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/deepdocs.dev\/"},{"@type":"ListItem","position":2,"name":"What is OAuth2? A Practical Guide for Developers"}]},{"@type":"WebSite","@id":"https:\/\/deepdocs.dev\/#website","url":"https:\/\/deepdocs.dev\/","name":"DeepDocs","description":"Fix Your Outdated GitHub Docs on Autopilot","publisher":{"@id":"https:\/\/deepdocs.dev\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/deepdocs.dev\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":"Organization","@id":"https:\/\/deepdocs.dev\/#organization","name":"DeepDocs","url":"https:\/\/deepdocs.dev\/","logo":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/deepdocs.dev\/#\/schema\/logo\/image\/","url":"https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2025\/06\/6.jpg?fit=408%2C400&ssl=1","contentUrl":"https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2025\/06\/6.jpg?fit=408%2C400&ssl=1","width":408,"height":400,"caption":"DeepDocs"},"image":{"@id":"https:\/\/deepdocs.dev\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/profile.php?id=61560455754198","https:\/\/x.com\/Nilzkool","https:\/\/www.linkedin.com\/company\/deepdocs-dev","https:\/\/www.youtube.com\/@DrNeelDas"]},{"@type":"Person","@id":"https:\/\/deepdocs.dev\/#\/schema\/person\/cf2ace6ae4dae8b34ab48a3e833ceede","name":"Neel Das","image":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/secure.gravatar.com\/avatar\/227924e7431a87895450dcd654b650e5011891dcba027fd9c782941985cbbb2d?s=96&d=identicon&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/227924e7431a87895450dcd654b650e5011891dcba027fd9c782941985cbbb2d?s=96&d=identicon&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/227924e7431a87895450dcd654b650e5011891dcba027fd9c782941985cbbb2d?s=96&d=identicon&r=g","caption":"Neel Das"},"sameAs":["http:\/\/neeldasf2ac55feaf.wordpress.com"],"url":"https:\/\/deepdocs.dev\/author\/neeldasf2ac55feaf\/"}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/05\/what-is-oauth2-developer-guide-1.jpg?fit=1312%2C736&ssl=1","jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pgAtwt-T6","jetpack-related-posts":[{"id":3670,"url":"https:\/\/deepdocs.dev\/user-is-unauthorized\/","url_meta":{"origin":3416,"position":0},"title":"Fixing User Is Unauthorized: A Developer&#8217;s Guide","author":"Neel Das","date":"10 June 2026","format":false,"excerpt":"A request fails, the UI throws User Is Unauthorized, and the instinct is to blame auth middleware. Sometimes that's right. Often it isn't. The tricky part is that this message sits at the intersection of authentication, authorization, session state, and plain old product logic. In practice, I've seen the same\u2026","rel":"","context":"In &quot;Docs&quot;","block_context":{"text":"Docs","link":"https:\/\/deepdocs.dev\/category\/docs\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/06\/user-is-unauthorized-developer-guide-1.jpg?fit=1200%2C675&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/06\/user-is-unauthorized-developer-guide-1.jpg?fit=1200%2C675&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/06\/user-is-unauthorized-developer-guide-1.jpg?fit=1200%2C675&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/06\/user-is-unauthorized-developer-guide-1.jpg?fit=1200%2C675&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/06\/user-is-unauthorized-developer-guide-1.jpg?fit=1200%2C675&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":3471,"url":"https:\/\/deepdocs.dev\/http-header-authorization\/","url_meta":{"origin":3416,"position":1},"title":"Master HTTP Header Authorization Guide","author":"Neel Das","date":"19 May 2026","format":false,"excerpt":"You send a request that worked yesterday. Today it comes back with 401 Unauthorized. The token looks fine, the endpoint hasn't changed, and curl works while the browser client fails. That's the kind of bug that burns an afternoon because http header authorization sits at the boundary between protocol rules,\u2026","rel":"","context":"In &quot;Docs&quot;","block_context":{"text":"Docs","link":"https:\/\/deepdocs.dev\/category\/docs\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/05\/http-header-authorization-education-1.jpg?fit=1200%2C673&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/05\/http-header-authorization-education-1.jpg?fit=1200%2C673&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/05\/http-header-authorization-education-1.jpg?fit=1200%2C673&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/05\/http-header-authorization-education-1.jpg?fit=1200%2C673&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/05\/http-header-authorization-education-1.jpg?fit=1200%2C673&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":1908,"url":"https:\/\/deepdocs.dev\/open-api-example\/","url_meta":{"origin":3416,"position":2},"title":"8 Essential Open API Example Patterns for 2025","author":"Emmanuel Mumba","date":"6 December 2025","format":false,"excerpt":"TL;DR: Key OpenAPI Patterns CRUD Operations: Master the basics of resource management with POST, GET, PUT\/PATCH, and DELETE. API Authentication: Define security schemes like API Keys, OAuth 2.0, or JWTs to protect your endpoints. File Uploads: Use multipart\/form-data to handle binary data like images or documents alongside metadata. Pagination &\u2026","rel":"","context":"In &quot;Docs&quot;","block_context":{"text":"Docs","link":"https:\/\/deepdocs.dev\/category\/docs\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2025\/11\/Blue-Gradient-Modern-Sport-Presentation-2-1.jpg?fit=1200%2C675&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2025\/11\/Blue-Gradient-Modern-Sport-Presentation-2-1.jpg?fit=1200%2C675&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2025\/11\/Blue-Gradient-Modern-Sport-Presentation-2-1.jpg?fit=1200%2C675&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2025\/11\/Blue-Gradient-Modern-Sport-Presentation-2-1.jpg?fit=1200%2C675&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2025\/11\/Blue-Gradient-Modern-Sport-Presentation-2-1.jpg?fit=1200%2C675&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":3526,"url":"https:\/\/deepdocs.dev\/rest-api-insomnia\/","url_meta":{"origin":3416,"position":3},"title":"REST API Insomnia: Master Your Workflow in 2026","author":"Neel Das","date":"17 May 2026","format":false,"excerpt":"Teams often open Insomnia when something is already broken. A request fails, auth looks suspicious, or a response body doesn't match what the docs promise. That's useful, but it leaves a lot of value on the table. A better rest api insomnia workflow treats the tool as part of API\u2026","rel":"","context":"In &quot;Docs&quot;","block_context":{"text":"Docs","link":"https:\/\/deepdocs.dev\/category\/docs\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/05\/rest-api-insomnia-workflow-design-1.jpg?fit=1152%2C640&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/05\/rest-api-insomnia-workflow-design-1.jpg?fit=1152%2C640&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/05\/rest-api-insomnia-workflow-design-1.jpg?fit=1152%2C640&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/05\/rest-api-insomnia-workflow-design-1.jpg?fit=1152%2C640&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/05\/rest-api-insomnia-workflow-design-1.jpg?fit=1152%2C640&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":1232,"url":"https:\/\/deepdocs.dev\/api-documentation-best-practices\/","url_meta":{"origin":3416,"position":4},"title":"8 API Documentation Best Practices for 2025","author":"Emmanuel Mumba","date":"7 October 2025","format":false,"excerpt":"TL;DR: Top API Documentation Practices Provide Practical Code Examples: Offer clear, multi-language code snippets for both successful requests and common errors. Make them copy-paste ready with realistic data. Include an Interactive API Explorer: Let developers make live API calls directly from your docs using a sandboxed environment. This speeds up\u2026","rel":"","context":"In &quot;Docs&quot;","block_context":{"text":"Docs","link":"https:\/\/deepdocs.dev\/category\/docs\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2025\/10\/Blue-Gradient-Modern-Sport-Presentation-1-1.jpg?fit=1200%2C675&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2025\/10\/Blue-Gradient-Modern-Sport-Presentation-1-1.jpg?fit=1200%2C675&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2025\/10\/Blue-Gradient-Modern-Sport-Presentation-1-1.jpg?fit=1200%2C675&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2025\/10\/Blue-Gradient-Modern-Sport-Presentation-1-1.jpg?fit=1200%2C675&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2025\/10\/Blue-Gradient-Modern-Sport-Presentation-1-1.jpg?fit=1200%2C675&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":2948,"url":"https:\/\/deepdocs.dev\/best-practices-for-api-design\/","url_meta":{"origin":3416,"position":5},"title":"10 Best Practices for API Design That Actually Work","author":"Neel Das","date":"18 March 2026","format":false,"excerpt":"Summary Focus on RESTful principles: Design your API around resources (nouns, not verbs) and use standard HTTP methods (GET, POST, PUT, DELETE) for predictable interactions. Prioritize stability and clarity: Use semantic versioning (MAJOR.MINOR.PATCH) to signal changes and maintain a clear deprecation policy to build trust with developers. Provide robust error\u2026","rel":"","context":"In &quot;Docs&quot;","block_context":{"text":"Docs","link":"https:\/\/deepdocs.dev\/category\/docs\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/03\/best-practices-for-api-design-digital-interaction-1.jpg?fit=1200%2C673&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/03\/best-practices-for-api-design-digital-interaction-1.jpg?fit=1200%2C673&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/03\/best-practices-for-api-design-digital-interaction-1.jpg?fit=1200%2C673&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/03\/best-practices-for-api-design-digital-interaction-1.jpg?fit=1200%2C673&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/deepdocs.dev\/wp-content\/uploads\/2026\/03\/best-practices-for-api-design-digital-interaction-1.jpg?fit=1200%2C673&ssl=1&resize=1050%2C600 3x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/deepdocs.dev\/wp-json\/wp\/v2\/posts\/3416","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/deepdocs.dev\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/deepdocs.dev\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/deepdocs.dev\/wp-json\/wp\/v2\/users\/259061979"}],"replies":[{"embeddable":true,"href":"https:\/\/deepdocs.dev\/wp-json\/wp\/v2\/comments?post=3416"}],"version-history":[{"count":2,"href":"https:\/\/deepdocs.dev\/wp-json\/wp\/v2\/posts\/3416\/revisions"}],"predecessor-version":[{"id":3524,"href":"https:\/\/deepdocs.dev\/wp-json\/wp\/v2\/posts\/3416\/revisions\/3524"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/deepdocs.dev\/wp-json\/wp\/v2\/media\/3417"}],"wp:attachment":[{"href":"https:\/\/deepdocs.dev\/wp-json\/wp\/v2\/media?parent=3416"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/deepdocs.dev\/wp-json\/wp\/v2\/categories?post=3416"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/deepdocs.dev\/wp-json\/wp\/v2\/tags?post=3416"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}