<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ oauth - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ oauth - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Wed, 29 Jul 2026 16:52:43 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/oauth/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How OAuth 2.0 Works: A Practical Guide for Backend Developers ]]>
                </title>
                <description>
                    <![CDATA[ If you ask ten junior developers how OAuth 2.0 works, nine of them will start reciting terminology like "Authorization Server", "Bearer Tokens", "PKCE", and "Implicit Grant". They might also draw a se ]]>
                </description>
                <link>https://www.freecodecamp.org/news/oauth-2-0-guide-for-backend-developers/</link>
                <guid isPermaLink="false">6a69c4a5ad8b0e89e727f8a5</guid>
                
                    <category>
                        <![CDATA[ oauth ]]>
                    </category>
                
                    <category>
                        <![CDATA[ backend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ authorization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ authentication ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ashutosh Krishna ]]>
                </dc:creator>
                <pubDate>Wed, 29 Jul 2026 09:15:17 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5fc16e412cae9c5b190b6cdd/a789ad3d-c2a7-43d6-9c14-ae13705072a4.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you ask ten junior developers how OAuth 2.0 works, nine of them will start reciting terminology like "Authorization Server", "Bearer Tokens", "PKCE", and "Implicit Grant". They might also draw a sequence diagram with six arrows crossing back and forth.</p>
<p>But if you ask them why a specific HTTP request exists or what breaks if you remove it, they often can't give a good explanation.</p>
<p>That's because OAuth is usually taught backward, in my opinion. Most tutorials start with definitions and sequence diagrams before establishing why the protocol was designed that way in the first place.</p>
<p>In this guide, we're going to fix that. We'll build up OAuth 2.0 concept by concept, starting from a real engineering problem and arriving at the protocol solutions naturally. By the time we write the code in Spring Boot, every parameter, redirect, and token will make total sense.</p>
<h3 id="heading-heres-what-well-cover">Here's What We'll Cover:</h3>
<ul>
<li><p><a href="#heading-the-problem-before-oauth">The Problem Before OAuth</a></p>
</li>
<li><p><a href="#heading-what-oauth-20-actually-is-and-isnt">What OAuth 2.0 Actually Is (And Isn't)</a></p>
</li>
<li><p><a href="#heading-application-registration-where-credentials-come-from">Application Registration: Where Credentials Come From</a></p>
</li>
<li><p><a href="#heading-the-four-roles-in-oauth-20">The Four Roles in OAuth 2.0</a></p>
</li>
<li><p><a href="#heading-access-tokens-and-scopes">Access Tokens and Scopes</a></p>
</li>
<li><p><a href="#heading-the-authorization-code-flow">The Authorization Code Flow</a></p>
</li>
<li><p><a href="#heading-why-the-two-step-redirect-exists">Why The Two-Step Redirect Exists</a></p>
</li>
<li><p><a href="#heading-token-expiration-and-refresh-tokens">Token Expiration and Refresh Tokens</a></p>
</li>
<li><p><a href="#heading-pkce-protecting-public-clients">PKCE: Protecting Public Clients</a></p>
</li>
<li><p><a href="#heading-state-vs-pkce-stopping-different-attacks">state vs. PKCE: Stopping Different Attacks</a></p>
</li>
<li><p><a href="#heading-oauth-20-vs-openid-connect-oidc-amp-jwts">OAuth 2.0 vs. OpenID Connect (OIDC) &amp; JWTs</a></p>
</li>
<li><p><a href="#heading-what-is-oauth-21">What is OAuth 2.1?</a></p>
</li>
<li><p><a href="#heading-production-security-pitfalls-to-avoid">Production Security Pitfalls to Avoid</a></p>
</li>
<li><p><a href="#heading-final-thoughts">Final Thoughts</a></p>
</li>
</ul>
<h2 id="heading-the-problem-before-oauth">The Problem Before OAuth</h2>
<p>Imagine we're building <strong>TravelBuddy</strong>, a Spring Boot application that helps users plan trips.</p>
<p>TravelBuddy has a feature that automatically detects scheduling conflicts and inserts trip itineraries directly into the user's Google Calendar.</p>
<p>To do this, TravelBuddy needs access to Google Calendar's API. Specifically, it needs to read existing events and write new ones on behalf of the user, Alice.</p>
<p>How would we have solved this back in 2005 before OAuth existed?</p>
<h3 id="heading-the-password-sharing-anti-pattern">The Password Sharing Anti-Pattern</h3>
<p>Without a protocol like OAuth, TravelBuddy would've to ask Alice for her Google username and password.</p>
<img src="https://cdn.hashnode.com/uploads/covers/61c1acb4a90dea775da8262b/71470751-1c68-45b9-8ab1-14b229124670.png" alt="A linear flow showing Alice sending her full account credentials directly to TravelBuddy, which then forwards those credentials to the Google Calendar API. This pattern forces users to hand over total account control to third-party applications." style="display:block;margin:0 auto" width="1469" height="140" loading="lazy">

<p>Alice would type her Google password directly into TravelBuddy's UI. TravelBuddy would store her password in its database and use those credentials to log into Google whenever it needed to fetch or create calendar events.</p>
<p>This approach works, but it creates massive security and operational problems:</p>
<ol>
<li><p><strong>Over-privileged access:</strong> TravelBuddy only needs to manage calendar events. But because it has Alice's actual Google password, it can also read her Gmail, look at her Google Drive files, delete her photos, or change her account password. There's no way to give TravelBuddy <em>limited</em> access.</p>
</li>
<li><p><strong>No revocation granular control:</strong> If Alice wants to stop TravelBuddy from accessing her calendar, her only option is to change her Google password. Doing so breaks every other application she previously authorized.</p>
</li>
<li><p><strong>Storage liability for TravelBuddy:</strong> TravelBuddy is now storing plaintext or decryptable passwords for thousands of Google accounts. A single SQL injection or database leak on TravelBuddy's side compromises the master keys to its users' entire digital lives on Google.</p>
</li>
<li><p><strong>Phishing normalization:</strong> Training users to enter their primary Google credentials into third-party apps teaches them terrible security habits.</p>
</li>
</ol>
<p>We need a way for Alice to give TravelBuddy permission to perform specific actions on Google Calendar <em>without ever giving TravelBuddy her Google password</em>.</p>
<p>That capability is called <strong>delegated authorization</strong>, and that's precisely what OAuth 2.0 provides.</p>
<h2 id="heading-what-oauth-20-actually-is-and-isnt">What OAuth 2.0 Actually Is (And Isn't)</h2>
<p>OAuth 2.0 is an open standard for <strong>delegated authorization</strong>.</p>
<p>It provides a framework that allows a user to grant a third-party application limited access to their resources on another service without sharing their credentials.</p>
<p>Before moving forward, we must address the single most common misconception in web development.</p>
<h3 id="heading-authentication-vs-authorization">Authentication vs. Authorization</h3>
<p>Developers swap these terms constantly, but they answer two fundamentally different questions:</p>
<ul>
<li><p><strong>Authentication (AuthN):</strong> <em>Who are you?</em> (Identity)</p>
</li>
<li><p><strong>Authorization (AuthZ):</strong> <em>What are you allowed to do?</em> (Permissions)</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/61c1acb4a90dea775da8262b/f03b89c7-79e8-489e-9607-f5b2f5a65a5e.png" alt="A flowchart illustrating how Authentication precedes Authorization. The first box establishes identity (&quot;You are Alice&quot;), which feeds into the second box establishing permissions (&quot;Alice can read/write events, but cannot delete the calendar&quot;)." style="display:block;margin:0 auto" width="702" height="916" loading="lazy">

<p>OAuth 2.0 is <strong>strictly an authorization framework.</strong> It doesn't specify how to authenticate a user, how to issue identity details, or how to store user accounts. It only cares about issuing permission keys (tokens) so one service can talk to another on a user's behalf.</p>
<p>When you click "Log in with Google" on a website, that interaction uses an extension built <em>on top</em> of OAuth called OpenID Connect (OIDC), which we'll cover later. But core OAuth 2.0 is entirely about authorization.</p>
<h2 id="heading-application-registration-where-credentials-come-from">Application Registration: Where Credentials Come From</h2>
<p>Before TravelBuddy can initiate an OAuth flow, we must register TravelBuddy in the <strong>Google Cloud Console</strong>.</p>
<p>During registration, Google prompts TravelBuddy for two key details:</p>
<ol>
<li><p><strong>Application Name &amp; Logo:</strong> Presented on the user consent screen.</p>
</li>
<li><p><strong>Redirect URIs:</strong> The exact callback URLs (for example, <code>https://travelbuddy.com/login/oauth2/code/google</code>) where Google is permitted to send authorization codes.</p>
</li>
</ol>
<p>Once registered, Google issues two credentials to TravelBuddy:</p>
<ul>
<li><p><code>client_id</code><strong>:</strong> A public identifier (like a username) that identifies TravelBuddy. It;s safe to embed in public links or frontend code.</p>
</li>
<li><p><code>client_secret</code><strong>:</strong> A confidential key (like a password) used by TravelBuddy's backend server to authenticate itself when exchanging authorization codes for tokens.</p>
</li>
</ul>
<h2 id="heading-the-four-roles-in-oauth-20">The Four Roles in OAuth 2.0</h2>
<p>OAuth 2.0 defines four roles. Let's map them directly to our TravelBuddy example so these terms stop being abstract definitions.</p>
<img src="https://cdn.hashnode.com/uploads/covers/61c1acb4a90dea775da8262b/615ddf00-a380-45c7-a49b-2b613a7b36ff.png" alt="A diagram connecting the four entities: Alice (Resource Owner) grants permission to TravelBuddy (Client). Alice authenticates with Google's Authorization Server, which issues a token to TravelBuddy. TravelBuddy uses that token to request data from Google Calendar (Resource Server), which validates the token with the Authorization Server." style="display:block;margin:0 auto" width="2816" height="1536" loading="lazy">

<ul>
<li><p><strong>Resource Owner:</strong> The user who owns the data. In our example, this is <strong>Alice</strong>. She owns her Google Calendar.</p>
</li>
<li><p><strong>Client:</strong> The third-party application trying to access the user's data. In our example, this is <strong>TravelBuddy</strong> (our Spring Boot backend). It's called a "client" because it acts as a client to the API.</p>
</li>
<li><p><strong>Authorization Server:</strong> The server that authenticates the user, obtains their consent, and issues access tokens. In our example, this is <strong>Google's OAuth server</strong> (<code>accounts.google.com</code>).</p>
</li>
<li><p><strong>Resource Server:</strong> The server hosting the protected user data. In our example, this is the <strong>Google Calendar API</strong> (<code>www.googleapis.com/calendar</code>).</p>
</li>
</ul>
<p>Notice how Google's responsibilities are split into two separate roles: the Authorization Server (which issues tokens) and the Resource Server (which hosts the API). In large organizations, these are frequently separate services maintained by different teams.</p>
<h2 id="heading-access-tokens-and-scopes">Access Tokens and Scopes</h2>
<p>Instead of handing TravelBuddy her password, Alice approves the issuance of an <strong>Access Token</strong>.</p>
<p>An access token is a string of characters that acts like a temporary keycard. When TravelBuddy makes an HTTP request to Google Calendar, it presents this token in the headers.</p>
<p>An access token has three critical properties that passwords lack:</p>
<ol>
<li><p><strong>Limited Scope:</strong> It can only be used for specific permissions.</p>
</li>
<li><p><strong>Limited Lifetime:</strong> It expires automatically after a short period (typically minutes or hours).</p>
</li>
<li><p><strong>Revocable:</strong> Alice or Google can revoke the token at any point without impacting Alice's account password.</p>
</li>
</ol>
<h3 id="heading-what-is-a-scope">What is a Scope?</h3>
<p>A scope is a string that defines the exact permission being requested. Instead of asking for "Google account access", TravelBuddy asks for specific scopes.</p>
<p>When TravelBuddy redirects Alice to Google, it specifies the requested scopes:</p>
<ul>
<li><p>Read calendar events: <a href="https://www.googleapis.com/auth/calendar.events.readonly">https://www.googleapis.com/auth/calendar.events.readonly</a></p>
</li>
<li><p>Create/Edit calendar events: <a href="https://www.googleapis.com/auth/calendar.events">https://www.googleapis.com/auth/calendar.events</a></p>
</li>
</ul>
<p>When TravelBuddy redirects Alice to Google, it specifies the requested scopes. Google displays these exact permissions to Alice:</p>
<p>"TravelBuddy would like permission to view and edit your Google Calendar events."</p>
<p>If Alice agrees, the access token Google issues will be bound strictly to those requested scopes. If TravelBuddy tries to use that same token to read Alice's emails, Google's Resource Server will reject the request with a <code>403 Forbidden</code> status code.</p>
<h2 id="heading-the-authorization-code-flow">The Authorization Code Flow</h2>
<p>Now that we know the roles and tokens, how does TravelBuddy actually get an access token?</p>
<p>The standard, most secure flow for server-side applications (like our Spring Boot app) is the <strong>Authorization Code Flow</strong>.</p>
<p>Here's the sequence of events. We'll walk through every step in detail immediately after the diagram.</p>
<img src="https://cdn.hashnode.com/uploads/covers/61c1acb4a90dea775da8262b/1d792e3f-3d4b-4596-852b-b917e63c4c2d.png" alt="A nine-step sequence diagram detailing the authorization process. The user initiates the sync, gets redirected to Google to log in and consent, and receives a temporary Auth Code via browser redirect. TravelBuddy's backend exchanges that code and its Client Secret for an Access Token directly with Google, then calls the Calendar API using the Bearer token." style="display:block;margin:0 auto" width="2372" height="1278" loading="lazy">

<p>Let's break this down step-by-step.</p>
<h3 id="heading-step-1-user-initiates-action">Step 1: User Initiates Action</h3>
<p>Alice is using TravelBuddy's UI and clicks "Connect Google Calendar."</p>
<h3 id="heading-step-2-travelbuddy-constructs-redirect-url">Step 2: TravelBuddy Constructs Redirect URL</h3>
<p>TravelBuddy's backend doesn't prompt for credentials. Instead, it generates a URL pointing to Google's Authorization Server and instructs Alice's browser to redirect there.</p>
<p>This URL looks like this:</p>
<pre><code class="language-shell">GET https://accounts.google.com/o/oauth2/v2/auth?response_type=code&amp;client_id=TRAVELBUDDY_CLIENT_ID&amp;redirect_uri=https://travelbuddy.com/login/oauth2/code/google&amp;scope=https://www.googleapis.com/auth/calendar.events&amp;state=xyz123
</code></pre>
<p>Let's analyze what each parameter does:</p>
<ul>
<li><p><code>response_type=code</code>: Tells Google we're using the Authorization Code flow.</p>
</li>
<li><p><code>client_id</code>: A public identifier Google gave to TravelBuddy when TravelBuddy registered as a developer app.</p>
</li>
<li><p><code>redirect_uri</code>: The URL where Google should send Alice back once she completes consent.</p>
</li>
<li><p><code>scope</code>: The permissions TravelBuddy is asking for.</p>
</li>
<li><p><code>state</code>: A random string generated by TravelBuddy to prevent Cross-Site Request Forgery (CSRF) attacks.</p>
</li>
</ul>
<h3 id="heading-step-3-alice-authenticates-and-consents">Step 3: Alice Authenticates and Consents</h3>
<p>Alice's browser lands on Google's domain (<a href="http://accounts.google.com"><code>accounts.google.com</code></a>).</p>
<p>Google verifies whether Alice is logged in. If not, Google asks her to log in. <strong>TravelBuddy never sees this interaction.</strong></p>
<p>Once authenticated, Google displays the consent screen listing TravelBuddy's name and the requested scopes.</p>
<h3 id="heading-step-4-amp-5-google-issues-an-authorization-code">Step 4 &amp; 5: Google Issues an Authorization Code</h3>
<p>Alice clicks "Approve." Google's authorization server redirects Alice's browser back to TravelBuddy's registered <code>redirect_uri</code>, attaching a short-lived <strong>Authorization Code</strong> and the <code>state</code> parameter in the query string:</p>
<pre><code class="language-shell">GET https://travelbuddy.com/login/oauth2/code/google?code=4/0AX4XfWh...&amp;state=xyz123
</code></pre>
<p>TravelBuddy's backend verifies that the returned <code>state</code> matches what it originally sent. If it matches, TravelBuddy takes the <code>code</code>.</p>
<h3 id="heading-step-6-amp-7-travelbuddy-exchanges-the-code-for-a-token">Step 6 &amp; 7: TravelBuddy Exchanges the Code for a Token</h3>
<p>Now TravelBuddy's <strong>backend server</strong> makes a direct, server-to-server POST request to Google's token endpoint (<code>https://oauth2.googleapis.com/token</code>):</p>
<pre><code class="language-shell">POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&amp;
code=4/0AX4XfWh...&amp;
redirect_uri=https://travelbuddy.com/login/oauth2/code/google&amp;
client_id=TRAVELBUDDY_CLIENT_ID&amp;
client_secret=TRAVELBUDDY_CLIENT_SECRET
</code></pre>
<p>Google validates the authorization code and TravelBuddy's <code>client_secret</code>. If valid, Google responds with a JSON payload containing the access token:</p>
<pre><code class="language-json">{
  "access_token": "ya29.a0ARrdaM...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "1//04rG...",
  "scope": "https://www.googleapis.com/auth/calendar.events"
}
</code></pre>
<h3 id="heading-step-8-amp-9-calling-the-api">Step 8 &amp; 9: Calling the API</h3>
<p>TravelBuddy now stores this access token securely and uses it to call the Google Calendar API on Alice's behalf:</p>
<pre><code class="language-shell">GET /calendar/v3/users/me/calendarList HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer ya29.a0ARrdaM...
</code></pre>
<p>Google Calendar receives the request, extracts the Bearer token, checks with Google's auth infrastructure to verify it is valid and scoped correctly, and returns Alice's calendar data.</p>
<h2 id="heading-why-the-two-step-redirect-exists">Why The Two-Step Redirect Exists</h2>
<p>At this point, a junior developer almost always asks a great question:</p>
<blockquote>
<p><em>"Why do we have Step 4 and 6? Why doesn't Google just return the access token directly in the redirect back to the browser in Step 4?"</em></p>
</blockquote>
<p>Why bother returning a temporary <code>authorization_code</code> to the browser, only to immediately make another backend call to exchange it for the actual <code>access_token</code>?</p>
<p>The answer boils down to <strong>Front-Channel vs. Back-Channel security</strong>.</p>
<ul>
<li><p><strong>The Front-Channel (the browser):</strong> The browser is an untrusted, highly exposed environment. Redirect URIs pass through browser histories, system logs, referrer headers, and browser extensions. If Google returned an access token directly in the browser's URL, that high-privilege token could easily leak or be intercepted by malicious extensions.</p>
</li>
<li><p><strong>The Back-Channel (server-to-server):</strong> The direct HTTPS network call between TravelBuddy's backend server and Google's auth server is private and encrypted. It bypasses the browser completely.</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/61c1acb4a90dea775da8262b/3771a305-01b5-4e0f-8732-5c74fbe2a01b.png" alt="A structural diagram separating the two network channels. The top box shows the Front-Channel, where the browser passes the exposed Authorization Code through URL redirects. The bottom box shows the secure Back-Channel, where TravelBuddy's server directly exchanges the Auth Code and Client Secret for tokens over encrypted server-to-server HTTPS." style="display:block;margin:0 auto" width="1563" height="1044" loading="lazy">

<p>The Authorization Code acts as a temporary, single-use ticket (usually expiring in under 60 seconds). Even if an attacker steals the authorization code from the browser's URL history, <strong>they can't exchange it for an access token because they don't possess TravelBuddy's</strong> <code>client_secret</code><strong>.</strong></p>
<h2 id="heading-token-expiration-and-refresh-tokens">Token Expiration and Refresh Tokens</h2>
<p>Access tokens are intentionally designed to be short-lived, typically expiring after one hour (<code>expires_in: 3600</code>).</p>
<p>Why? Because if an access token leaks, the window of opportunity for an attacker is strictly limited to whatever time remains before expiration.</p>
<p>But having Alice re-authenticate and click "Approve" every hour would offer a terrible user experience. TravelBuddy needs to sync calendars in the background while Alice is asleep.</p>
<p>To solve this, OAuth 2.0 introduces <strong>Refresh Tokens</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/61c1acb4a90dea775da8262b/0f235e3b-59ff-4973-8a3b-adc3517caec8.png" alt="A sequence diagram showing error recovery. TravelBuddy attempts an API call with an expired token and gets a 401 response. TravelBuddy sends a POST request with its Refresh Token to the Auth Server, receives a fresh Access Token, and retries the original API request successfully." style="display:block;margin:0 auto" width="1868" height="966" loading="lazy">

<h3 id="heading-how-refresh-tokens-work">How Refresh Tokens Work</h3>
<p>Depending on provider configuration (for example, passing <code>access_type=offline</code> and <code>prompt=consent</code> for Google), Google returns both an <code>access_token</code> and a long-lived <code>refresh_token</code> during the initial code exchange.</p>
<p>Then TravelBuddy encrypts and stores the <code>refresh_token</code> securely in its database.</p>
<p>When the <code>access_token</code> expires, TravelBuddy makes a background request directly to Google's token endpoint, presenting the <code>refresh_token</code> and <code>client_secret</code>.</p>
<p>Finally, Google validates the refresh token and issues a brand-new <code>access_token</code> without involving Alice at all.</p>
<table style="min-width:75px"><colgroup><col style="min-width:25px"><col style="min-width:25px"><col style="min-width:25px"></colgroup><tbody><tr><td><p><strong>Feature</strong></p></td><td><p><strong>Access Token</strong></p></td><td><p><strong>Refresh Token</strong></p></td></tr><tr><td><p><strong>Primary Purpose</strong></p></td><td><p>Used to access protected APIs</p></td><td><p>Used to obtain new access tokens</p></td></tr><tr><td><p><strong>Lifetime</strong></p></td><td><p>Very short (15 mins to 1 hour)</p></td><td><p>Long-lived (days, months, or until revoked)</p></td></tr><tr><td><p><strong>Sent Where?</strong></p></td><td><p>Sent with every API call to Resource Server</p></td><td><p>Sent ONLY to Authorization Server token endpoint</p></td></tr><tr><td><p><strong>Storage Security</strong></p></td><td><p>Can be kept in temporary server memory</p></td><td><p>Must be stored encrypted in secure storage</p></td></tr></tbody></table>

<h2 id="heading-pkce-protecting-public-clients">PKCE: Protecting Public Clients</h2>
<p>The Authorization Code flow we just discussed relies on TravelBuddy keeping its <code>client_secret</code> confidential. That is why TravelBuddy is classified as a <strong>Confidential Client</strong>. It runs on a server where developers can safely store environment variables and secrets.</p>
<p>But what if TravelBuddy is a Single Page Application (React/Vue running directly in the browser) or a Native Mobile App (iOS/Android)?</p>
<p>These are <strong>Public Clients</strong>. Anyone can open browser developer tools or decompile an Android <code>.apk</code> file to extract any embedded <code>client_secret</code>.</p>
<p>Without a secret, how can public clients safely use the Authorization Code flow? If a malicious app on a mobile device intercepts the authorization code, it could exchange that code for tokens because there is no <code>client_secret</code> stopping it.</p>
<p>To solve this, OAuth 2.0 introduced <strong>PKCE</strong> (Proof Key for Code Exchange, pronounced "pixie").</p>
<img src="https://cdn.hashnode.com/uploads/covers/61c1acb4a90dea775da8262b/05e945d7-a9a8-4de2-8ff3-20c955f704a5.png" alt="A sequence diagram illustrating PKCE. The client generates a secret code_verifier and hashes it into a code_challenge. It sends the challenge during authorization. When exchanging the Auth Code for tokens, it reveals the original code_verifier. The Auth Server hashes the verifier and compares it against the challenge to verify client identity without requiring a client secret." style="display:block;margin:0 auto" width="2156" height="1108" loading="lazy">

<h3 id="heading-how-pkce-works">How PKCE Works</h3>
<p>Before starting the flow, the client generates a cryptographic, random string called the <code>code_verifier</code>. The client hashes this string (typically using SHA-256) to produce the <code>code_challenge</code>.</p>
<p>In Step 2 of the Auth flow, the client sends the <code>code_challenge</code> and hash method <code>code_challenge_method=S256</code>) to the Authorization Server. The Authorization Server stores the <code>code_challenge</code> and returns the authorization code as usual.</p>
<p>In Step 6, when exchanging the code for tokens, the client sends the original <code>unhashed code_verifier</code>.</p>
<p>The Authorization Server hashes the provided <code>code_verifier</code> using SHA-256 and checks if it matches the stored <code>code_challenge</code>. If it matches, it proves that the app requesting the token is the exact same app that initiated the request.</p>
<p><strong>Note</strong>: Modern OAuth security guidelines recommend using PKCE for all applications, including confidential backend applications like Spring Boot.</p>
<h2 id="heading-state-vs-pkce-stopping-different-attacks"><code>state</code> vs. PKCE: Stopping Different Attacks</h2>
<p>Developers often confuse <code>state</code> and <code>PKCE</code> because both involve random strings sent during the OAuth flow. But they protect against completely different attack vectors:</p>
<table style="min-width:75px"><colgroup><col style="min-width:25px"><col style="min-width:25px"><col style="min-width:25px"></colgroup><tbody><tr><td><p><strong>Property</strong></p></td><td><p><code>state</code><strong> Parameter</strong></p></td><td><p><code>PKCE</code><strong> (code_verifier)</strong></p></td></tr><tr><td><p><strong>Primary Threat</strong></p></td><td><p><strong>Login CSRF:</strong> An attacker tricks a victim into completing an OAuth flow using the <em>attacker's</em> authorization code.</p></td><td><p><strong>Code Interception:</strong> An attacker steals a victim's authorization code and exchanges it for a token.</p></td></tr><tr><td><p><strong>How It Protects</strong></p></td><td><p>Binds the authorization callback to the user's specific browser session.</p></td><td><p>Proves that the entity exchanging the code is the same entity that requested it.</p></td></tr><tr><td><p><strong>Validation Point</strong></p></td><td><p>Checked by the <strong>Client Application Backend</strong> upon callback.</p></td><td><p>Checked by the <strong>Authorization Server</strong> at the <code>/token</code> endpoint.</p></td></tr></tbody></table>

<h2 id="heading-oauth-20-vs-openid-connect-oidc-amp-jwts">OAuth 2.0 vs. OpenID Connect (OIDC) &amp; JWTs</h2>
<p>Earlier, I emphasized that OAuth 2.0 is purely for <strong>authorization</strong> (permissions), not <strong>authentication</strong> (identity).</p>
<p>Yet, almost every app you use has a "Sign in with Google" button. How does that work?</p>
<h3 id="heading-enter-openid-connect-oidc">Enter OpenID Connect (OIDC)</h3>
<p>OpenID Connect is an identity layer built directly on top of OAuth 2.0.</p>
<p>While core OAuth issues an <code>access_token</code> meant for an API, requesting the <code>openid</code> scope instructs the Authorization Server to issue an <strong>ID Token</strong> alongside the access token:</p>
<img src="https://cdn.hashnode.com/uploads/covers/61c1acb4a90dea775da8262b/0089d542-a859-45c0-874e-19f54d85e431.png" alt="A nested architecture diagram showing OpenID Connect as an outer identity layer wrapping core OAuth 2.0. OAuth 2.0 handles Access Tokens for API permissions, while OIDC adds the ID Token (JWT) to convey user identity information." style="display:block;margin:0 auto" width="940" height="688" loading="lazy">

<p>When TravelBuddy requests the <code>openid</code> scope alongside calendar permissions:</p>
<pre><code class="language-shell">scope=openid profile email https://www.googleapis.com/auth/calendar.events
</code></pre>
<p>Google's token endpoint responds with both an <code>access_token</code> AND an <code>id_token</code>.</p>
<ul>
<li><p><strong>Access Token:</strong> Intended for the Resource Server (Google Calendar). TravelBuddy doesn't need to read its contents. It just passes it along in headers.</p>
</li>
<li><p><strong>ID Token:</strong> Intended specifically for TravelBuddy. It contains cryptographically signed information about Alice (for example, her Google User ID, full name, email, and profile picture URL).</p>
</li>
</ul>
<h3 id="heading-what-is-a-jwt">What is a JWT?</h3>
<p>An ID Token is almost always formatted as a <strong>JWT</strong> (JSON Web Token, pronounced "jot").</p>
<p>A JWT is a compact, URL-safe string containing three parts separated by dots: <code>Header.Payload.Signature</code></p>
<pre><code class="language-shell">eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
</code></pre>
<p>Decoding the middle section (Payload) reveals plain JSON:</p>
<pre><code class="language-json">{
  "sub": "google-user-id-98765",
  "iss": "https://accounts.google.com",
  "aud": "TRAVELBUDDY_CLIENT_ID",
  "email": "alice@gmail.com",
  "exp": 1711900000
}
</code></pre>
<p>Base64URL encoding is <strong>not encryption</strong>. Anyone who holds a JWT can read its contents. But because the token is signed using Google's private key, TravelBuddy's backend can verify Google's public signature locally without needing to call Google's servers to confirm Alice's identity on every request.</p>
<h3 id="heading-is-an-access-token-always-a-jwt">Is an Access Token always a JWT?</h3>
<p><strong>No.</strong> OAuth 2.0 intentionally doesn't mandate any specific format for access tokens.</p>
<p>An access token can be:</p>
<ol>
<li><p><strong>An Opaque Token:</strong> A completely random string (for example, <code>ya29.a0ARrdaM...</code>). The client and resource server must look up its meaning by querying the authorization server.</p>
</li>
<li><p><strong>A Structured Token (like a JWT):</strong> Contains embedded claims so the resource server can validate it self-sufficiently.</p>
</li>
</ol>
<h2 id="heading-what-is-oauth-21">What is OAuth 2.1?</h2>
<p>If you work with modern security guidelines, you'll hear about <strong>OAuth 2.1</strong>.</p>
<p>OAuth 2.1 is not an overhaul of OAuth 2.0. It's a consolidation draft that incorporates years of security best practices into a single specification:</p>
<ol>
<li><p><strong>Mandatory PKCE:</strong> PKCE is required for <em>all</em> Authorization Code flows, including confidential server-side apps like Spring Boot.</p>
</li>
<li><p><strong>Deprecation of Legacy Grants:</strong> The Implicit Grant (which returned tokens directly in browser URLs) and the Resource Owner Password Credentials Grant (which collected passwords directly) are removed entirely.</p>
</li>
<li><p><strong>Exact Redirect URI Matching:</strong> Wildcards in redirect URIs are prohibited to prevent open-redirect exploits.</p>
</li>
</ol>
<h2 id="heading-production-security-pitfalls-to-avoid">Production Security Pitfalls to Avoid</h2>
<p>Building OAuth integrations in production requires careful attention to detail. Here are five of the most common security mistakes backend engineers make and how to avoid them:</p>
<h3 id="heading-1-storing-tokens-in-browser-localstorage">1. Storing Tokens in Browser <code>localStorage</code></h3>
<p>If you're building a SPA client that receives access or refresh tokens, never store tokens in <code>localStorage</code> or <code>sessionStorage</code>.</p>
<p>Any script running on your page, including third-party analytics, chat widgets, or compromised npm dependencies, can read <code>localStorage</code> through a Cross-Site Scripting (XSS) vulnerability.</p>
<p><strong>Fix:</strong> Store tokens inside HTTP-Only, Secure, SameSite cookies managed by your backend, or use a backend-for-frontend (BFF) architecture where tokens never reach the browser at all.</p>
<h3 id="heading-2-leaking-the-client-secret">2. Leaking the Client Secret</h3>
<p>It sounds obvious, but <code>client_secret</code> strings end up in public GitHub repositories constantly. Remember: any secret included in Android/iOS apps, React single-page apps, or frontend code is public.</p>
<p><strong>Fix:</strong> Keep client secrets inside environment variables on server-side environments. Use PKCE for public clients where secrets can't be protected.</p>
<h3 id="heading-3-requesting-unnecessary-scopes-scope-creep">3. Requesting Unnecessary Scopes (Scope Creep)</h3>
<p>Asking for full account access when you only need read permission makes users suspicious and increases your liability if a token leaks.</p>
<p><strong>Fix:</strong> Follow the principle of least privilege. Request only the specific scopes your app needs immediately. If TravelBuddy later adds a feature to analyze emails, request the Gmail scope dynamically when the user activates that feature.</p>
<h3 id="heading-4-assuming-an-oauth-token-proves-identity">4. Assuming an OAuth Token Proves Identity</h3>
<p>Just because an app receives an <code>access_token</code> from an API doesn't mean it can treat that token as proof of who logged in.</p>
<p>If an attacker passes a valid access token obtained from a different application (a confused deputy attack), your system might accept it if it only checks token validity without checking who the token was issued to <code>aud</code> / audience claim).</p>
<p>Fix: Use OpenID Connect (and validate the <code>id_token</code> claims including <code>aud</code> and <code>iss</code>) when authenticating users.</p>
<h3 id="heading-5-skipping-state-or-pkce-validation">5. Skipping <code>state</code> or <code>PKCE</code> Validation</h3>
<p>If you manually build OAuth flows without checking the <code>state</code> parameter, your application is vulnerable to Login Cross-Site Request Forgery (CSRF). An attacker could trick a user's browser into completing an OAuth flow using the attacker's authorization code, linking the victim's session to the attacker's account data.</p>
<p>Fix: Always generate a cryptographically strong, non-guessable <code>state</code> parameter bound to the user's session, or rely on established security frameworks like Spring Security that enforce this automatically.</p>
<h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>OAuth 2.0 can feel overwhelming when viewed entirely as a web of specs, RFCs, and terminology.</p>
<p>When you strip away the jargon, OAuth solves one core problem: allowing a user to give an application permission to access their data without handing over their password.</p>
<p>Every moving part in the protocol exists to support that core mission safely:</p>
<ul>
<li><p><strong>Scopes</strong> restrict permissions.</p>
</li>
<li><p><strong>Access Tokens</strong> provide temporary, revocable access.</p>
</li>
<li><p><strong>Authorization Codes</strong> keep tokens out of vulnerable browser URLs.</p>
</li>
<li><p><strong>Refresh Tokens</strong> maintain long-term access without harassing the user.</p>
</li>
<li><p><strong>PKCE</strong> protects public applications that can't keep secrets.</p>
</li>
<li><p><strong>OpenID Connect</strong> adds a standardized identity layer on top.</p>
</li>
</ul>
<p>The next time you integrate an OAuth provider in Spring Boot or debug a token error in production, don't focus on memorizing the diagrams. Look at the HTTP request, ask which specific boundary it is crossing, and the design choices will make immediate sense.</p>
<details>
<summary>Summary Glossary</summary>
<ul><li><p><strong>Authorization Code:</strong> A short-lived, single-use ticket returned via browser redirect, exchanged server-side for access tokens.</p></li><li><p><strong>Access Token:</strong> A temporary keycard used in HTTP headers to access protected resources.</p></li><li><p><strong>Refresh Token:</strong> A long-lived credential used strictly at the token endpoint to obtain new access tokens.</p></li><li><p><strong>Scope:</strong> A string specifying granular permissions requested by the client.</p></li><li><p><strong>PKCE:</strong> Proof Key for Code Exchange. A cryptographic technique binding token exchange to the initiating client instance.</p></li><li><p><strong>OpenID Connect (OIDC):</strong> An identity layer built on top of OAuth 2.0 that issues an <code>id_token</code> containing user profile details.</p></li><li><p><strong>JWT:</strong> JSON Web Token, a compact, digitally signed format commonly used for ID tokens.</p></li></ul>
</details> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Set Up GitHub OAuth in a Django App for User Authentication ]]>
                </title>
                <description>
                    <![CDATA[ Maintaining safe and frictionless user authentication is paramount in today's fast-changing web application landscape.  Among the many authentication methods available, GitHub OAuth has emerged as a useful tool for improving user login experience whi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/set-up-github-oauth-on-django-for-user-authentication/</link>
                <guid isPermaLink="false">66c4c64d1b22d2d8d9040ec6</guid>
                
                    <category>
                        <![CDATA[ authentication ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Django ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GitHub ]]>
                    </category>
                
                    <category>
                        <![CDATA[ oauth ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sophia Iroegbu ]]>
                </dc:creator>
                <pubDate>Tue, 05 Dec 2023 21:19:14 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/11/Blog-Banner---Template.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Maintaining safe and frictionless user authentication is paramount in today's fast-changing web application landscape. </p>
<p>Among the many authentication methods available, GitHub OAuth has emerged as a useful tool for improving user login experience while strengthening security measures. </p>
<p><a target="_blank" href="https://docs.djangoproject.com/en/4.2/">Django</a>, a Python web framework, has recently gained popularity in web development due to its efficiency and versatility. Adding GitHub OAuth to your Django projects helps improve the authentication process. </p>
<p>Django developers can use GitHub OAuth to access a user's GitHub profile and (with permission) their repositories to personalize the user experience and tailor application services.</p>
<p>This article will walk you through how to implement GitHub OAuth. You'll see the benefits to your Django projects as we go. By embracing this technology, you can give users a seamless login experience while adhering to strict security standards.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>If you wish to follow this guide, you need to have a basic understanding of these tools or have them installed on your PC: </p>
<ul>
<li><a target="_blank" href="https://github.com/">GitHub</a></li>
<li><a target="_blank" href="https://docs.djangoproject.com/en/4.2/">Django</a></li>
<li><a target="_blank" href="https://www.django-rest-framework.org/">Django Rest Framework</a></li>
</ul>
<h2 id="heading-how-to-create-a-github-oauth-application">How to Create a GitHub OAuth Application</h2>
<p>You must sign into your GitHub account to create a GitHub OAuth application. </p>
<p>First, login to your GitHub account, click on your GitHub profile picture, and select Settings.</p>
<p><img src="https://lh7-us.googleusercontent.com/tLIRoSttp2_c3XAlLPzt_TbxCrGT70wcAubnY3ilywK9kxiGJ-z_5pzX3rDECRpTxKpXx61esK_NL5t1Jkg0kQNfMnvU6hhvfa7TRr9wVX0WyhQWhcvWivDbEQOqtehc87MPXzinHvY_da3IkORxFy8" alt="Image" width="532" height="1223" loading="lazy">
<em>Login to GitHub and select "Settings" from the sidebar menu</em></p>
<p>Then, once the new page comes up, scroll to the bottom and select Developer Settings.</p>
<p><img src="https://lh7-us.googleusercontent.com/jmWCI4fxgLc34a7tZhqXA1hvD6QnBTF1_ERfsq7VwleIuv21frXVxFyoeuIVPz-0SwAD3fJK8hTqIc8pTGaijVQrFUAUptYfGcUmljisdqjAlhQgElkXRb8iO4OeW9YyZ_DOYal-6bkDhL-5RYcvifY" alt="Image" width="1600" height="1149" loading="lazy">
<em>Scroll to the bottom and select "Develop Settings"</em></p>
<p>Select OAuth Apps and click on New OAuth App.</p>
<p><img src="https://lh7-us.googleusercontent.com/2loAs8jJILhusyITEk6v2XUher8kP5jBZWEWuUszfD0_C1vD56L6hlIsAwXL7gMV_8gR28T1Mthv_VrSZwqWo2MuIVKdH0SfGsFWBZcK1M3FbMD6JTdszf1v56sKQHcpDYDsu7VSbfg0DFeQCPI6Af8" alt="Image" width="1600" height="317" loading="lazy">
<em>Creating a new OAuth app</em></p>
<p>Define your OAuth application by naming it.</p>
<ul>
<li>The Homepage URL should be the URL that leads to the homepage of your website.</li>
<li>The Authorization callback URL should be a site, or a page users view after their GitHub account has been authenticated. </li>
</ul>
<p>Once you are done defining it, click Register application.</p>
<p><img src="https://lh7-us.googleusercontent.com/2jEfTNBil-Z5qCakfh8HkptyMm4Z8WOxsUfoN6T9nclv9soRmR4akgJJxuc52Xqzo2f3uBPZ6a_UMGJR8eukFdZk6HxSwPSdrPLG5m2n5NLRJXroCvr8_56DwWvHjtmi7KqZvga48RFbpry--FJq9zg" alt="Image" width="992" height="1101" loading="lazy">
<em>Register your application once all the info has been filled in</em></p>
<p>Next, you'll need a client secret and a client ID key to access your GitHub OAuth app on your Django project.</p>
<p>The Client ID is already defined once you create an application. Click Generate a new client secret to create a client secret key.</p>
<p><img src="https://lh7-us.googleusercontent.com/Fl2B2iqfYUejqWlb04TRUgN6XNP3m4IswS2JptoS-cVkQ4ft3SElu8xV0cF04buhrLdl3zRo6OEtvpg7rGnJ0Yj22KbmONEz0HWbjRRRk6R0H-XIN-hoaBQUjyQl_XPzcCAPCBFPEhcet7WcDwTrBoU" alt="Image" width="1600" height="819" loading="lazy">
<em>Creating a client secret key</em></p>
<p>You might be prompted to sign in. Do so to continue. </p>
<p><img src="https://lh7-us.googleusercontent.com/ceMI0FXuKACvZeA_S-RWYs2qjlCgkPzK9DbJtA6vIH6Nh5GvVHA66_rb9bHmtdxrM5VIzA3S6rpWbsCXURbrRjPrs4yHCLPttCC_9g1vNfQV5qeUN-eKAueE4EqKAmcvSThhJcav-53Jz1PsC7z4JMI" alt="Image" width="677" height="835" loading="lazy">
<em>Sign in to continue</em></p>
<p>Once you log in, your client's secret key will be generated. Copy and save it on your .env file.</p>
<p><img src="https://lh7-us.googleusercontent.com/Y0trI-EIYeKVBT_s3TSA7A-5FEkONt4fNfdUKqHXdBqsfxyxfnl5E9_DL02eynpj87i-cBworbxusUIRdNaH_qU_2TaKRDM1afpuBjVZBsaq-2GZyf4dz4sE43hjx24hknJwkHwkaiZOTDLBZvjxbHk" alt="Image" width="1477" height="818" loading="lazy">
<em>Copy your secret key to your .env file</em></p>
<p>Now that you’ve set up your GitHub OAuth application, let’s connect it to your Django project.</p>
<h2 id="heading-how-to-integrate-github-oauth-with-django">How to Integrate GitHub OAuth with Django</h2>
<p>This part will link your Django project's GitHub OAuth application to it using the social-auth app package. </p>
<p>First, install the <a target="_blank" href="https://dj-rest-auth.readthedocs.io/en/latest/">dj-rest-auth</a> package and define it on your settings.py.</p>
<pre><code class="lang-python">pip install dj-rest-auth
</code></pre>
<p>Then configure dj-rest-auth package on your settings.py.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Application definition</span>
INSTALLED_APPS = [
    <span class="hljs-string">"django.contrib.admin"</span>,
    <span class="hljs-string">"django.contrib.auth"</span>,
    <span class="hljs-string">"django.contrib.contenttypes"</span>,
    <span class="hljs-string">"django.contrib.sessions"</span>,
    <span class="hljs-string">"django.contrib.messages"</span>,
    <span class="hljs-string">"django.contrib.staticfiles"</span>,
    <span class="hljs-string">"django.contrib.sites"</span>,
    <span class="hljs-string">"rest_framework"</span>,
    <span class="hljs-string">"rest_framework.authtoken"</span>,
    <span class="hljs-string">"dj_rest_auth"</span>,
    <span class="hljs-string">"allauth"</span>,
    <span class="hljs-string">"allauth.account"</span>,
    <span class="hljs-string">"allauth.socialaccount"</span>,
    <span class="hljs-string">"allauth.socialaccount.providers.github"</span>,
    <span class="hljs-string">"oauth2_provider"</span>,
    <span class="hljs-string">"users"</span>,
]
</code></pre>
<p>You'll need to enable the authentication classes for dj-rest-auth by updating REST_FRAMEWORK and AUTHENTICATION_BACKENDS on your settings.py.</p>
<p>Optionally, you can configure <code>allauth</code> if you intend to use templates. Do this on your settings.py file. </p>
<pre><code class="lang-python">AUTHENTICATION_BACKENDS = (<span class="hljs-string">"allauth.account.auth_backends.AuthenticationBackend"</span>,)

REST_USE_JWT = <span class="hljs-literal">True</span>  <span class="hljs-comment"># Use JWT for authentication with dj-rest-auth</span>
SITE_ID = <span class="hljs-number">1</span> <span class="hljs-comment">#Set site ID</span>

SITE_ID = <span class="hljs-number">1</span>  <span class="hljs-comment"># Set the site ID</span>

<span class="hljs-comment"># Disable email verification for simplicity</span>
ACCOUNT_EMAIL_VERIFICATION = <span class="hljs-string">"none"</span>
LOGIN_REDIRECT_URL = <span class="hljs-string">"/"</span>  <span class="hljs-comment"># Redirect URL after successful login</span>
LOGOUT_REDIRECT_URL = <span class="hljs-string">"/"</span>  <span class="hljs-comment"># Redirect URL after logout</span>

SOCIALACCOUNT_PROVIDERS = {
    <span class="hljs-string">"github"</span>: {
        <span class="hljs-string">"APP"</span>: {
            <span class="hljs-string">"client_id"</span>: <span class="hljs-string">"YOUR_GITHUB_CLIENT_ID"</span>,
            <span class="hljs-string">"secret"</span>: <span class="hljs-string">"YOUR_GITHUB_SECRET_KEY"</span>,
            <span class="hljs-string">"key"</span>: <span class="hljs-string">""</span>,
            <span class="hljs-string">"redirect_uri"</span>: <span class="hljs-string">"http://localhost:8000/accounts/github/login/callback/"</span>,
        }
    }
}
</code></pre>
<p>A Django app is required for this guide. Let's call it users. Head over to the views of the Django app and define the following code:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> allauth.socialaccount.providers.github.views <span class="hljs-keyword">import</span> GitHubOAuth2Adapter
<span class="hljs-keyword">from</span> allauth.socialaccount.providers.oauth2.client <span class="hljs-keyword">import</span> OAuth2Client
<span class="hljs-keyword">from</span> dj_rest_auth.registration.views <span class="hljs-keyword">import</span> SocialLoginView

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GitHubLogin</span>(<span class="hljs-params">SocialLoginView</span>):</span>
    adapter_class = GitHubOAuth2Adapter
    callback_url = CALLBACK_URL_YOU_SET_ON_GITHUB
    client_class = OAuth2Client

<span class="hljs-comment"># Define the urls.py on the Django app</span>
urlpatterns += [
    path(<span class="hljs-string">'github/'</span>, GitHubLogin.as_view(), name=<span class="hljs-string">'github_login'</span>)
    ]
</code></pre>
<h2 id="heading-how-to-set-up-a-new-application">How to Set Up a New Application</h2>
<p>To specify the GitHub OAuth credentials, you'll need to log into the Django social application model. This will provide your Django project with an additional degree of protection. Because of this, changing the OAuth credentials will be simple and won't damage your existing code.</p>
<p>Start by logging into your Django admin, clicking Social Applications, and selecting Add Application. This will prompt you to create a new application.</p>
<p><img src="https://lh7-us.googleusercontent.com/9XQcRYZfLG8NOw-2ODor7Zgn-6x5Voq9F4ToVdp0eVLdnLnbWVkbB4PUEh68p3DJk9yjkKQf592_kDjipQQqHnpn7jeneWfu2X7Z4I2_n0wsltX5rGvbFSmyQteuDaXLUjWnNTBzDDJic6XQ8goBSd8" alt="Image" width="1600" height="812" loading="lazy">
<em>On Django admin, select "Social applications"</em></p>
<p>You will be prompted to enter information on the new page.</p>
<ul>
<li>Select GitHub as the provider.</li>
<li>Give your social app a name.</li>
<li>Enter the Client Secret and Client ID created from your GitHub OAuth app.</li>
<li>Select the site on Available sites and move it to Chosen sites. Once done, click Save. This will create a new application.</li>
</ul>
<p><img src="https://lh7-us.googleusercontent.com/pStq_1opKb7rkVNCqO2ouCfd2ZBLHFEwoxfWuHabFG12nT5v35NkXYSOH6Su2d_fISvwmO7LpCTfPsDK0EmmLUUvNYynoAgjuvsogP4Ee0xNBfIU_ai4TtXzzHZPFq2U0C3eFQfNCfXSuIoWup6PeCo" alt="Image" width="1600" height="1028" loading="lazy">
<em>Create/Add a Social application</em></p>
<p>Change your site domain to localhost since this is still the development phase.</p>
<p><img src="https://lh7-us.googleusercontent.com/pRKpPs06V2j5ciPCLZRCd5weyc3X5HOGgWXhen_GS9-DhItBkkVJFYe6jBd3QmWMRwfBPagYxh6r1PRXHVeM_M3X6xWeq0lRKYM0GbVKDMlZS7hIVz4oAF6M6lMxYUGF5ZuuPwQyUF-1lfidzJPw79E" alt="Image" width="1600" height="968" loading="lazy">
<em>Select, "Site" to change the existing the site domain</em></p>
<p>Select example.com and change it to http://127.0.0.1:8000/ then Save.</p>
<p><img src="https://lh7-us.googleusercontent.com/ikQ9_lhABi-avsKcoIqH98znI3aJKN4RkZqGfYQwio8nujR0M1kEewfBYdekhVkQMqYQi5APqsqxqpEkbX78wFS8dw76tGH11eEQ2qqTzCuabzgx5qD85SPBgkVtyJVEUui4RAKR_y2Dr65dEiyh7P4" alt="Image" width="1600" height="551" loading="lazy">
<em>Change your site domain from example.com to http://127.0.0.1:8000/</em></p>
<h2 id="heading-how-to-test-the-defined-social-app">How to Test the Defined Social App</h2>
<p>Once you are done defining and setting up the social Django app on your project, you will need to test it and make sure that it works. </p>
<p>If you open the route http://127.0.0.1:8000/auth/github/, you'll need to enter some information such as Access token, ID token, and code. </p>
<p>We'll manually get this information, as the front end is meant to get and parse this information.</p>
<p><img src="https://lh7-us.googleusercontent.com/eLkjj3nueZUf26fcORK9iJSvSyKNiO_ZgvfD9vFbF2momnDka6dVxngCQSKY9VwWcHJDduKDhGXhYsbimtSGZL5uzjrherU6bDXUFDfu5Bys1wylda6WZCOZsotH7ENkZAsHEYbhbImbx9JmbRKCtYM" alt="Image" width="1600" height="791" loading="lazy">
<em>Go to the GitHub registration page to test the defined social app</em></p>
<p>To do this, head over to https://github.com/settings/apps and select Personal access tokens then select Generate new token. Use the second option, Generate new token (classic), since this guide is focused on authenticating users just to get their GitHub user info.</p>
<p><img src="https://lh7-us.googleusercontent.com/E8bb0KrJ0IwoTqCf2f2WVMoycUNad3YuqQZnG6heWwpNh3euYesNjx_ipRAOxYZyGfT-DShM1OyIOznVByQCWqsFrllTXO-FQEUIYPKLbjcbCBrp6vsN_XLlZJhaB3ZaxyBmWGiTMfWD5vjq0VWEq5g" alt="Image" width="1600" height="434" loading="lazy">
<em>On GitHub settings, select "Personal access tokens" then select "Generate new token".</em></p>
<p>Give the token a name and select scopes. Ensure you check all the user scopes.  Then generate a new token.</p>
<p><img src="https://lh7-us.googleusercontent.com/ZLkgWxuIQ1y-jZ3Pere1I-cmDIlwS032kQ0i5bvYufflVfnjhezcgNRqY-UpnJMPbJZY1RcdKApbTz579_DqR-Cs2M6ba3gTcaS6H2utA9JVkW2KVVXqsDjGwItruyBKpktd8TvlIDzVvlgQqh-RqUE" alt="Image" width="1600" height="942" loading="lazy">
<em>Define your new token</em></p>
<p>Your new token should look like this. Ensure you store it somewhere safe. </p>
<p><img src="https://lh7-us.googleusercontent.com/ywiFWxHFRJQwVZpGS-ePV7qR6YNIVi7gh3OoL9HgJvHc7TWHiSevr_Hmc8TRXbNxv0VAwwdt71O3PVchsLuRIlM9nbvhzj8X4IWBtgAjx17M8yYGApqxgBlU1lKeQYg8xwdwCg1PchuqiLuyj8YRCAg" alt="Image" width="1484" height="723" loading="lazy">
<em>Copy the generated personal access token generated by GitHub.</em></p>
<p>Head over to http://127.0.0.1:8000/auth/github/. Enter the access token generated and voilà!  Your user access token and GitHub username will be sent as a response on the body. </p>
<p><img src="https://lh7-us.googleusercontent.com/jd736d5yvsSPhvXCNX21CGHEzTdMhUerN4HVst57iOVqisAejH_T35D7AwKGGHgkJCtkzfkn4ut0YP2vxpYZgSa7ITEqaR2Wqw0J4qxWeIug0ciCEFM4GnDK-DjfooYRzg1sbU1z8cyFMtwRmgMG_bs" alt="Image" width="1600" height="855" loading="lazy">
<em>Using your token and GitHub username ensure the backend system works</em></p>
<h2 id="heading-how-to-implement-oauth-authentication-flow">How to Implement OAuth Authentication Flow</h2>
<p>You have successfully installed and tested the dj-rest-auth package. Next, you will learn how to test the OAuth flow and how it obtains user data from GitHub.</p>
<p>To test the GitHub OAuth authentication flow, you'll need to send a request to https://github.com/login/oauth/authorize.</p>
<p>You can do so by either using curl:</p>
<pre><code class="lang-python"><span class="hljs-string">"https://github.com/login/oauth/authorize?client_id=YOUR_CLIENT_ID&amp;amp;redirect_uri=http://127.0.0.1:8000/auth/callback/&amp;amp;scope=user"</span>
</code></pre>
<p>(and making sure you use the same redirect URI defined in your GitHub OAuth application) or opening https://github.com/login/oauth/authorize?client_id=YOUR_CLIENT_ID&amp;redirect_uri=http://127.0.0.1:8000/auth/callback/&amp;scope=user on your browser. It will redirect you to an authorization page. </p>
<p><img src="https://lh7-us.googleusercontent.com/rJbNTlLFz8h-dMJNgeeMCX-kT-Y_Ofv-1Po0wNp2qZQVH_e6syyabIasdrjWzDDdtF6NQ-2o2oDxv_KX2wYmoUb7OiYcZGz66sbzNjfpfB0P3asAFh4oPV7OvybcQ4OYtiGKAUNYYvqAUt7H1-sn7mM" alt="Image" width="919" height="1164" loading="lazy">
<em>Send a request to GitHub OAuth authentication flow</em></p>
<p>Click Authorize YOUR USERNAME to authorize the user.</p>
<p><img src="https://lh7-us.googleusercontent.com/8GaW8izjQgcqd-9IbCeyDZcdnajXKBDETOIiZ5P2s3iziZQMUvROKmJQuJBDvmPdpAEEhSCCB_xdy1NSkgEEqU2o18lmwsbo8Eay8IYzKL-HJCKoB40ySLE9-vl3g5CLtMyuzmSwQy9u_fyI2iqfuwg" alt="Image" width="991" height="307" loading="lazy">
<em>Click "Authorize" to authorize your GitHub user</em></p>
<p>You will be redirected to a URL showing the code. With the code, you can generate the access token needed to authenticate the user.</p>
<p><img src="https://lh7-us.googleusercontent.com/_RO4IqpLY0-zg8SiW7SXKk1gTCkJq_bVqIrDzH4_tzqWSzHUArqsQlDYSqzFHiGfxdyPpSXW5psYKnZVyHPgnDbETBncgpIrWxZAWc1RjQvcGmi5QRN5XpOyOxuy5n5DqiJkSJO8c0VizOFh3h-tqy4" alt="Image" width="1523" height="159" loading="lazy">
<em>Use the code from GitHub to generate an access token for your auth</em></p>
<p>To get the access token, send a request to this URL: https://github.com/login/oauth/access_token?client_id=YOUR_CLIENT_ID&amp;client_secret=YOUR_CLIENT_SECRET&amp;code=CODE </p>
<p>Or you can choose to use curl to send the request. </p>
<pre><code class="lang-curl">"https://github.com/login/oauth/access_token?client_id=YOUR_CLIENT_ID&amp;amp;client_secret=YOUR_CLIENT_SECRET&amp;amp;code=CODE"
</code></pre>
<p>This should either download the access token for you or return it as a response body depending on how you defined it. The response should look like this:</p>
<p><img src="https://lh7-us.googleusercontent.com/ZIn4u5kqdW3P7o27ReEsAyc-X9R2O28Bm2qfjDh0saywx7vpso41OLoOldHzii4AbnQe-jfqT__4aELgchdXUSQPIR6I86-KdOyZL4hrcFI38YBOjX27IbH2NNtS7SWS7hAFNTroZfVF17s8xoI0lBk" alt="Image" width="1336" height="213" loading="lazy">
<em>Your response from your backend authentication system</em></p>
<p>Now, with this token, you can authenticate your user when they make any request. </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, setting up GitHub OAuth on Django is a helpful way to enable users to log in to your web applications using their GitHub credentials. </p>
<p>By following this guide, you can enhance your application's security and access your users' data which improves the user experience of your Django app.   </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Set Up a GitHub OAuth Application ]]>
                </title>
                <description>
                    <![CDATA[ GitHub is an incredibly useful OAuth provider, especially if you are building an application targeted toward developers.  In this article, we will give you a quick rundown of how to set up a GitHub OAuth application. Create Your Application Begin by ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-set-up-a-github-oauth-application/</link>
                <guid isPermaLink="false">66ac7f3d23cc28a03a55e088</guid>
                
                    <category>
                        <![CDATA[ freeCodeCamp.org ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GitHub ]]>
                    </category>
                
                    <category>
                        <![CDATA[ oauth ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Naomi Carrigan ]]>
                </dc:creator>
                <pubDate>Thu, 27 Oct 2022 21:31:36 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/10/pexels-george-becker-333837--1-.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>GitHub is an incredibly useful OAuth provider, especially if you are building an application targeted toward developers. </p>
<p>In this article, we will give you a quick rundown of how to set up a GitHub OAuth application.</p>
<h2 id="heading-create-your-application">Create Your Application</h2>
<p>Begin by navigating to your GitHub settings (make sure you are logged in!). Scroll down to the bottom of the sidebar and click "Developer Settings".</p>
<p>This will take you to the application page:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-230.png" alt="GitHub OAuth Apps view, showing a hacktoberfest and mattermost application that have been previously authorised." width="600" height="400" loading="lazy">
<em>You may see some applications you've previously authorised.</em></p>
<p>Click the "New OAuth App" button to create a new application.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-232.png" alt="The new OAuth application page, showing form fields for Application name, homepage URL, application description, and authorisation callback URL." width="600" height="400" loading="lazy"></p>
<p>Fill in the form and click "Register application". This will create your application and take you to the settings page.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-233.png" alt="The Application settings page, which shows the same form fields as the previous form, with additional options to transfer ownership, revoke user tokens, generate client secrets, and upload a logo." width="600" height="400" loading="lazy"></p>
<p>For OAuth applications, you will need the Client ID. You will also need to generate a client secret. Click the "Generate a new client secret" to do so.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-234.png" alt="The new client secret (obfuscated for security in this image)" width="600" height="400" loading="lazy"></p>
<p>Make sure to save this secret in a secure location as you will not be able to view it again.</p>
<h2 id="heading-using-your-new-application">Using Your New Application</h2>
<p>Now that you have a client ID and secret, you can use your OAuth application in your project. </p>
<p>If you want to learn how to do so, <a target="_blank" href="https://www.freecodecamp.org/learn/quality-assurance/#advanced-node-and-express">freeCodeCamp's curriculum can teach you</a>. </p>
<p>Happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Social Login with OAuth to Make Your Apps More Secure ]]>
                </title>
                <description>
                    <![CDATA[ Many developers have written a demo login application at some point in time. We all start with the simple user defined ID and password. We then try to implement something like a social login with, say, Google or Twitter. There is, of course, a more c... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-social-login-with-oauth-for-more-secure-apps/</link>
                <guid isPermaLink="false">66bb458361078de848a7e0e4</guid>
                
                    <category>
                        <![CDATA[ Application Security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ oauth ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Rohit Jacob Mathew ]]>
                </dc:creator>
                <pubDate>Fri, 29 Oct 2021 14:50:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/10/MzBKTcnJA.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Many developers have written a demo login application at some point in time. We all start with the simple user defined ID and password. We then try to implement something like a social login with, say, Google or Twitter.</p>
<p>There is, of course, a more complex process involved in setting up social login, but for a user it's as simple as clicking a button to log in. </p>
<p>The ease of not having to remember an ID/password and just being able to signup/login through the click of a button is extremely beneficial to the user.</p>
<h2 id="heading-what-if-i-told-you-this-was-way-more-secure">What if I Told You This Was Way More Secure? 😉</h2>
<p>Social logins really help us achieve a few things:</p>
<ul>
<li>Support for multiple devices</li>
<li>Single Sign On</li>
<li>Simple to implement</li>
<li>The ability to share data for users without having to release personal information</li>
<li>Ability revoke an active session i.e not allow a third party access to the login and data</li>
<li>There are no long-lasting credentials being exchanged</li>
</ul>
<h2 id="heading-so-what-technology-drives-social-login">So What Technology Drives Social Login? 🤔</h2>
<p>The underlying protocol used is something called <a target="_blank" href="https://oauth.net/">OAuth</a>. It is defined as:</p>
<blockquote>
<p>An open protocol to allow secure authorization in a simple and standard method from web, mobile, and desktop applications.</p>
</blockquote>
<p>Now with a basic understanding of social login and the above definition you probably have some idea of how this works – but let me use a simple example to explain how to use OAuth.</p>
<p>I remember my friend <a target="_blank" href="https://twitter.com/lunatic_monk">Sumedh</a> describing it as an interaction between a Mother, Father, and their Son. Imagine that the mother wants some groceries from the market and she wants the son to buy them for her.</p>
<p>Before I go into the conversation let me set some context.</p>
<blockquote>
<p><strong>Mother:</strong> The user of the application</p>
<p><strong>Son:</strong> Third party client or in technical terms the OAuth Client</p>
<p><strong>Father:</strong> The Social Account or in technical terms the OAuth Provider</p>
</blockquote>
<p>The conversation could possibly go like this:</p>
<blockquote>
<p><strong>Mother:</strong> Hey son, go to the market and bring me some coffee powder. Take the required money from your father.</p>
<p><strong>Son:</strong> Okay.</p>
<p><em>Son (OAuth client) goes to father (OAuth provider)</em></p>
<p><strong>Son:</strong> Hey dad, mom told me to take money from you since she wants some things from the market.</p>
<p><em>Father (OAuth provider) asks mother (User) about the permission to give money to their son (OAuth client)</em></p>
<p><strong>Father:</strong> Hey, shall I give him the money and how much?</p>
<p><em>Authorization of your application takes place here.</em></p>
<p><strong>Mother:</strong> Yes, please give it to him.</p>
<p><em>Permission grant by mother (User)</em></p>
<p><em>Son (OAuth client) gets the required things from the market and returns them to mother (User). Here returning things to mother (User) can be thought of redirecting the user (or logging them) into the third party site.</em></p>
</blockquote>
<p>For a more technical understanding of how this works in code, <a target="_blank" href="https://twitter.com/schneems">Richard Schneeman</a> has this amazing video below:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/tFYrq3d54Dc" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-now-lets-put-all-of-this-in-context">Now Lets Put All of This in Context</h2>
<p>Let's take as an example <a target="_blank" href="https://dev.to/">the DEV Community</a>. If you wanted to create an account on the DEV Community using Twitter, what would happen?</p>
<p>Basically, if the "Sign up with Twitter" button exists, then the initial setup between the OAuth Client (Dev.to) and the OAuth Provider (Twitter) is already done.</p>
<p>The Client triggers a permission granting page for the OAuth Provider based on the credentials it receives from the initial setup. This looks something like below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1622980489496/IrLawupb6.png" alt="Permission Grant Page" width="1398" height="1106" loading="lazy"></p>
<p>Once you login and grant permission, the OAuth Provider redirects you back to the client and the client gets a token to access your information from the OAuth Provider. This access token enables the client to get specific data from the provider</p>
<p>Based on that data the client then creates an account and logs you in</p>
<h3 id="heading-what-happens-on-successive-login">What Happens on Successive Login?</h3>
<p>Thats a good question. Now OAuth has multiple grant types, and based on that we have different ways to get an access token from the OAuth Provider. </p>
<p>For all subsequent logins, the OAuth Client will hit the provider and generate a new access token to get access to the data and do the login.</p>
<p>Thus this enables us to achieve Single Sign On, the ability to share data for users without having to release personal information, the ability to revoke access, and the ability to not have long lasting credentials exchanged.</p>
<p>This all leads to a more secure experience.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I hope this short blog post helps you understand why social logins are more secure than the traditional username/password option. I will be writing about the different OAuth Grant types in the future and will be providing code examples as well.</p>
<p>Thanks for reading! I really hope that you find this article useful. I'm always interested to know your thoughts and happy to answer any questions you might have in your mind. If you think this post was useful, please share it to help promote this piece to others.</p>
<p>Thanks for reading! :)</p>
<p>P.S Do feel free to connect with me on <a target="_blank" href="https://www.linkedin.com/in/rohitjmathew">LinkedIn</a> or <a target="_blank" href="https://twitter.com/iamrohitjmathew">Twitter</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Brilliant Add-on For Static Sites That Will Make You Dance ]]>
                </title>
                <description>
                    <![CDATA[ By Jared Wolff This post is originally from www.jaredwolff.com Privacy. Performance. Brilliant looks. Can you have all three? (Of course!) Having a statically generated blog is great. Many folks use services like Disqus and Google Analytics to make t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-setup-worry-free-blog-comments-in-20-simple-steps/</link>
                <guid isPermaLink="false">66d8505639c4dccc43d4d4a7</guid>
                
                    <category>
                        <![CDATA[ blog ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Docker compose ]]>
                    </category>
                
                    <category>
                        <![CDATA[ nginx ]]>
                    </category>
                
                    <category>
                        <![CDATA[ oauth ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Static Site Generators ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 08 Jul 2019 12:30:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/07/Copy-of-Static-Site-Docker-Recipes-2.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Jared Wolff</p>
<p><strong>This post is originally from <a target="_blank" href="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/">www.jaredwolff.com</a></strong></p>
<p>Privacy.</p>
<p>Performance.</p>
<p>Brilliant looks.</p>
<p>Can you have all three?</p>
<p>(Of course!)</p>
<p>Having a statically generated blog is great. Many folks use services like Disqus and Google Analytics to make them even better. Not surprising if you were one of them!  Privacy concerns are are the forefront of everyone’s attention. So, rather than keeping the status quo, it’s time to do something about it!</p>
<p><strong>If you've been looking to protect your site visitor's privacy and improve performance this blog post is for you.</strong></p>
<p>In this article we'll be using DigitalOcean’s Docker droplet. It allows you to host several different applications/services on one (virtual) machine. By the end of it you'll know how to run your own comments server using Commento. Plus i’ll share a few tricks i’ve learned along the way to make it much easier for you.</p>
<p>Leeeets go!</p>
<h2 id="heading-reverse-proxy">Reverse Proxy</h2>
<p>One of the most important aspects of this setup is the reverse proxy. A reverse proxy acts like a router. Requests come in for a certain domain.  That request is then routed to the service associated with that domain.</p>
<p>Here’s a diagram from the Nginx Reverse Proxy + Let’s Encrypt Helper documentation. It'll help illustrate the idea.</p>
<p><img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/webproxy-1f1c7540-4b86-4478-bb3e-f05043d671a5.jpg" alt="Nginx Reverse Proxy with Let's Encrypt" width="730" height="334" loading="lazy"></p>
<p>Another benefit is that there’s an extra layer of protection to the outside world. Your websites run in a private network and the only access is through the Nginx reverse proxy. Point your DNS to the server and Nginx handles all the magic.</p>
<p>Here's how to get it setup:</p>
<ol>
<li>Go ahead and set up your Digital Ocean Droplet. <a target="_blank" href="https://marketplace.digitalocean.com/apps/docker">All the info you need is right here</a>. The $5 version is more than sufficient.</li>
<li><p><a target="_blank" href="https://github.com/evertramos/docker-compose-letsencrypt-nginx-proxy-companion">Go here to clone the repository.</a> You can also run this in your terminal. Make sure you SSH into your Digital Ocean droplet first!</p>
<p>     git clone git@github.com:evertramos/docker-compose-letsencrypt-nginx-proxy-companion.git</p>
</li>
<li><p>Change directories to the cloned repository.</p>
</li>
<li>Copy <code>.env.sample</code> to <code>.env</code> and update the values inside. I had to change the <code>IP</code> value to the IP of my Digital Ocean Droplet. I left all the other ones alone.</li>
<li>Run <code>docker-compose up -d</code> to start everything. (you can run without the <code>-d</code> option to make sure everything starts ok. Or you can attach the log output using <code>docker container logs -f &lt;container name</code></li>
</ol>
<p>When pointing your sub-domains to this server, make sure you use an A record. Here's an example of mine:</p>
<p><img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-05_at_6-9c0432cd-4d40-4c89-88f3-24037d915eaf.52.32_PM.png" alt="NS1 A Record Configuration" width="730" height="581" loading="lazy"></p>
<p>Depending on your DNS provider, you'll have to figure out how to set an A record. That is beyond the purpose of this article though!</p>
<h2 id="heading-setting-up-commento-with-docker-compose">Setting Up Commento with Docker Compose</h2>
<p><img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Compose-1c868832-6819-43e2-8696-ab698a10dbee.jpg" alt="Commento Logo with Docker Logo" width="730" height="486" loading="lazy"></p>
<p>Here is the current docker compose file i'm using for Commento. It includes a few more environment variables for configuring Github, Gitlab and Google. It also includes the environment variables for setting the SMTP settings. These parameters are important. Otherwise you can't receive password reset or moderation emails!</p>
<p>    version: '3'</p>
<p>    services:
      commento:
        image: registry.gitlab.com/commento/commento
        container_name: commento
        restart: always
        environment:
          COMMENTO_ORIGIN: https://${COMMENTS_URL}
          COMMENTO_PORT: 8080
          COMMENTO_POSTGRES: postgres://postgres:postgres@postgres:5432/commento?sslmode=disable
          COMMENTO_SMTP_HOST: ${SMTP_HOST}
          COMMENTO_SMTP_PORT: ${SMTP_PORT}
          COMMENTO_SMTP_USERNAME: ${SMTP_USERNAME}
          COMMENTO_SMTP_PASSWORD: ${SMTP_PASSWORD}
          COMMENTO_SMTP_FROM_ADDRESS: ${SMTP_FROM_ADDRESS}
          COMMENTO_GITHUB_KEY: ${COMMENTO_GITHUB_KEY}
          COMMENTO_GITHUB_SECRET: ${COMMENTO_GITHUB_SECRET}
          COMMENTO_GITLAB_KEY: ${COMMENTO_GITLAB_KEY}
          COMMENTO_GITLAB_SECRET: ${COMMENTO_GITLAB_SECRET}
          COMMENTO_GOOGLE_KEY: ${COMMENTO_GOOGLE_KEY}
          COMMENTO_GOOGLE_SECRET: ${COMMENTO_GOOGLE_SECRET}
          COMMENTO_TWITTER_KEY: ${COMMENTO_TWITTER_KEY}
          COMMENTO_TWITTER_SECRET: ${COMMENTO_TWITTER_SECRET}
          VIRTUAL_HOST: ${COMMENTS_URL}
          VIRTUAL_PORT: 8080
          LETSENCRYPT_HOST: ${COMMENTS_URL}
          LETSENCRYPT_EMAIL: ${EMAIL}
        depends_on:</p>
<ul>
<li>postgres
networks:</li>
<li>db_network</li>
<li><p>webproxy</p>
<p>postgres:
image: postgres
container_name: postgres
environment:
POSTGRES_DB: commento
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
networks:</p>
</li>
<li>db_network
volumes:</li>
<li><p>postgres_data_volume:/var/lib/postgresql/data</p>
<p>networks:
db_network:
webproxy:
external: true</p>
<p>volumes:
postgres_data_volume:</p>
</li>
</ul>
<p>To set the environment variables, put them inside an <code>.env</code> file. Make sure the <code>.env</code> file is in the same directory as <code>docker-compose.yml</code>. When you run <code>docker-compose up</code> it will apply the variables set in the <code>.env</code> file. Nothing gets set if they're left blank.</p>
<p>Set the required <code>COMMENTS_URL</code> and <code>EMAIL</code> or you may run into problems. The best way to set these is by pacing them in the <code>.env</code> file. Here is an example:</p>
<p>    COMMENTS_URL=comments.your.url
    EMAIL=you@your.url</p>
<h2 id="heading-getting-oauth-key-amp-secret">Getting OAuth Key &amp; Secret</h2>
<p>Commento works with most popular OAuth providers. Thus visitors can leave comments without making an account.</p>
<p>The instructions are similar for each. I've outlined the steps for all of them below.</p>
<h3 id="heading-twitter">Twitter</h3>
<ol>
<li><p>Login to <a target="_blank" href="http://twitter.com">Twitter.com</a> and apply for a developer account: <a target="_blank" href="https://developer.twitter.com/en/application/use-case">https://developer.twitter.com/en/application/use-case</a></p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-05_at_6-4171cdf7-6c2b-408b-bb64-57822ede91cb.26.08_PM.png" alt="Twitter API Access" width="730" height="581" loading="lazy"></p>
</li>
<li><p>Describe how you'll use the API. You can use what I wrote.</p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-05_at_6-4c0aecf2-c020-4005-bd5f-81e3b4ac6b8f.28.43_PM.png" alt="How will you use the API?" width="730" height="581" loading="lazy"></p>
</li>
<li><p>Double check your entry and click <strong>Looks Good!</strong></p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-05_at_6-ade63510-86d3-48a4-a121-221f6e14cd96.28.50_PM.png" alt="Is everything correct?" width="730" height="581" loading="lazy"></p>
</li>
<li><p>Agree to the terms of service.</p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-05_at_6-2e8e3089-bd51-4d27-8573-6987aafc663e.28.59_PM.png" alt="Agree to Developer Agreement" width="730" height="581" loading="lazy"></p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-05_at_6-145b1bfd-9fc7-4ea6-ba5f-032e59d7fe8d.41.47_PM.png" alt="You did it!" width="730" height="581" loading="lazy"></p>
</li>
<li><p>They'll tell you to check your email for a confirmation. Confirm your email and you should be able to create your first app!</p>
</li>
<li><p>Once approved to to <strong>Get started</strong> click <strong>Create an app</strong>.</p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-05_at_6-640686b8-15c6-4af0-b9df-65ce15ae0fe7.29.22_PM.png" alt="Create an app" width="730" height="581" loading="lazy"></p>
</li>
<li><p>Next screen, again click <strong>Create an app</strong></p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-05_at_6-de2b85d5-8bb7-428f-bfd1-2a23d0b7d4e0.29.26_PM.png" alt="Create an app" width="730" height="581" loading="lazy"></p>
</li>
<li><p>Enter all the appropriate details. For the callback URL, use <a target="_blank" href="https://comments.jaredwolff.com/api/oauth/google/callback"><code>https://&lt;your URL&gt;/api/oauth/github/callback</code></a> where <a target="_blank" href="https://comments.jaredwolff.com/api/oauth/google/callback"><code>&lt;your URL&gt;</code></a> is your Commento subdomain.</p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-05_at_6-91acb343-9dee-4917-be77-9704fe439722.32.44_PM.png" alt="App details" width="730" height="581" loading="lazy"></p>
</li>
<li><p>Finally, once you're done filling out the information to go the <strong>Keys and Token</strong>s area. Save both the key and token. Enter them into the <code>.env</code> file. You can use <code>COMMENTO_TWITTER_KEY</code> and <code>COMMENTO_TWITTER_SECRET</code></p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-05_at_6-b910e9ff-dc34-45e8-94df-affb06702617.33.07_PM.png" alt="Get oauth key and secret" width="730" height="581" loading="lazy"></p>
</li>
</ol>
<h3 id="heading-gitlab">Gitlab</h3>
<ol>
<li>Login to <a target="_blank" href="http://gitlab.com">Gitlab.com</a> and go to to top right and click <strong>Settings</strong></li>
<li><p>Then click on <strong>Applications</strong></p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-05_at_12-c6da9d02-2052-4fa4-89de-d5212b8f49ca.56.47_PM.png" alt="Gitlab profile" width="730" height="445" loading="lazy"></p>
</li>
<li><p>Enter a name for your app. I put <strong>Commento</strong>.</p>
</li>
<li>Set the Redirect URI to <a target="_blank" href="https://comments.jaredwolff.com/api/oauth/google/callback"><code>https://&lt;your URL&gt;/api/oauth/gitlab/callback</code></a></li>
<li><p>Select the <strong>read_user</strong> scope.</p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-05_at_12-e616c338-6144-4704-93c6-914db6fad5f6.59.15_PM.png" alt="Gitlab add application" width="730" height="500" loading="lazy"></p>
</li>
<li><p>Click the green <strong>Save Application</strong> button</p>
</li>
<li><p>Copy the <strong>Application ID</strong> and <strong>Secret</strong> and place them in your <code>.env</code> file using <code>COMMENTO_GITLAB_KEY</code> and <code>COMMENTO_GITLAB_SECRET</code></p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-05_at_1-a4f4ab4a-9fd6-423f-821c-6ff2f174e589.04.10_PM.png" alt="Application key and secret" width="730" height="689" loading="lazy"></p>
</li>
</ol>
<h3 id="heading-github">Github</h3>
<ol>
<li>To get your OAuth key and secret, you'll need to go to this URL: <a target="_blank" href="https://github.com/settings/developers">https://github.com/settings/developers</a></li>
<li><p>Once there, click on <strong>New OAuth App</strong></p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-04_at_9-18bf8f23-916f-476b-8c25-3377de931fe3.15.33_AM.png" alt="Add OAuth application" width="730" height="562" loading="lazy"></p>
</li>
<li><p>Enter your details. For the callback URL, use <a target="_blank" href="https://comments.jaredwolff.com/api/oauth/google/callback"><code>https://&lt;your URL&gt;/api/oauth/github/callback</code></a> where <a target="_blank" href="https://comments.jaredwolff.com/api/oauth/google/callback"><code>&lt;your URL&gt;</code></a> is your Commento subdomain.</p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-04_at_9-6e616334-7123-4de4-a4fd-f2fe319b1971.28.24_AM.png" alt="Register new OAuth application" width="730" height="585" loading="lazy"></p>
<p> <em>Note: Make sure you include <code>https</code> in your URLs.</em></p>
</li>
<li><p>Grab the <strong>Client ID</strong> and <strong>Client secret</strong> and put that into your <code>.env</code> file using <code>COMMENTO_GITHUB_KEY</code> and <code>COMMENTO_GITHUB_SECRET</code></p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-04_at_9-7505a3ef-386a-4b75-a7dc-1dd3e22d0baf.29.28_AM.png" alt="Application created successfully" width="730" height="585" loading="lazy"></p>
</li>
</ol>
<h3 id="heading-google">Google</h3>
<p>Setting up Google is just about as tedious to set up as Twitter. Despite how scary I just made it out to be, it's completely doable. Here are the steps.</p>
<ol>
<li>Go to this URL: <a target="_blank" href="https://console.developers.google.com/cloud-resource-manager?previousPage=%2Fapi">Google Developer Console</a></li>
<li><p>Create a new project</p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-04_at_8-f3793926-cc54-4345-b81c-5ec0f4631a35.42.48_AM.png" alt="Create a new project" width="730" height="588" loading="lazy"></p>
</li>
<li><p>Click the <strong>GoogleAPIs logo</strong> in the top left corner to go back once you have a project. (Make sure the dropdown next to the <strong>GoogleAPIs logo</strong> is the same as your new project!)</p>
</li>
<li>Then, click <strong>Credentials</strong> on the left side.</li>
<li><p>Update the <strong>Application Name</strong> and <strong>Authorized Domains</strong> in the <strong>OAuth consent screen</strong></p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-04_at_8-d839a5c9-3368-4f18-b674-73b6e4e7c17c.47.15_AM.png" alt="Setup application" width="730" height="499" loading="lazy"></p>
</li>
<li><p>Click <strong>Create credentials</strong> then <strong>OAuth client ID</strong></p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-04_at_8-201545f9-4d47-4e0c-ae9a-b40efdc35a4b.44.36_AM.png" alt="Setup credentials" width="730" height="545" loading="lazy"></p>
</li>
<li><p>On the <strong>Create OAuth client ID</strong> enter the subdomain associated with Commento to <strong>Authorized Javascript origins.</strong> Then, enter the full callback URL. For example <a target="_blank" href="https://comments.jaredwolff.com/api/oauth/google/callback"><code>https://comments.jaredwolff.com/api/oauth/google/callback</code></a>. Make it yours by replacing <code>comments.jaredwolff.com</code> with your URL.</p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-04_at_8-fdba3491-d562-41f3-acff-2857ea816cec.52.15_AM.png" alt="Create OAuth Client ID" width="730" height="706" loading="lazy"></p>
<p> Once entered, click the <strong>create</strong> button.</p>
</li>
<li><p>Grab the <strong>client ID</strong> and <strong>client secret</strong></p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-04_at_8-0c3f2895-0cb9-4b3a-a154-a3d80fd9716a.57.40_AM.png" alt="OAuth Credentials" width="730" height="706" loading="lazy"></p>
</li>
<li><p>Update your <code>.env</code> file using <code>COMMENTO_GOOGLE_KEY</code> and <code>COMMENTO_GOOGLE_SECRET</code></p>
</li>
</ol>
<h2 id="heading-install-your-application">Install your application</h2>
<p>You've entered your OAuth Credentials email, domain and SMTP credentials. It's time to wrap this show up!</p>
<ol>
<li>Once you're done editing your <code>.env</code> file. Run <code>docker-compose up</code> (For files not named <code>docker-compose.yml</code>, use the <code>-f</code> flag. Example: <code>docker-compose -f commento.yml up</code></li>
<li>Watch the output for errors. If it looks good you may want to kill it (<strong>CTRL+C</strong>) and run with the <code>-d</code> flag</li>
<li><p>On first start, Commento will prompt you with a login screen.</p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-05_at_12-d5a1ca53-93b3-49c5-a3a7-e8b728259e2d.11.29_PM.png" alt="Commento Login" width="730" height="545" loading="lazy"></p>
</li>
<li><p>Create a new account by clicking <strong>Don't have an account yet? Sign up.</strong></p>
</li>
<li>Enter your information and click <strong>Sign Up</strong></li>
<li><p>Check your email and click the included link:</p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-05_at_12-e263aa4f-201b-42ac-986c-b28c5f003f38.12.48_PM.png" alt="Validation email with link" width="730" height="733" loading="lazy"></p>
</li>
<li><p>Log in with your freshly made account.</p>
</li>
<li><p>Then, click <strong>Add a New Domain.</strong></p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-05_at_12-46acfe9c-f3f4-4d3e-b8fb-97fbff643a86.10.47_PM.png" alt="Add new domain" width="730" height="598" loading="lazy"></p>
</li>
<li><p>Once created go to <strong>Installation Guide.</strong>  Copy the snippet and place it where ever you want your comments to live. In my case, I put the snippet in an area just after my <code>&lt;article&gt;</code> tag.</p>
<p> <img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-05_at_12-f78f36c5-f3f7-45ec-971d-9bf0bf7b7d1f.36.35_PM.png" alt="Code snippet" width="730" height="589" loading="lazy"></p>
</li>
<li><p>Re-compile your site and check for success!</p>
<p><img src="https://www.jaredwolff.com/how-to-setup-worry-free-blog-comments-in-less-than-20-simple-steps/images/Screen_Shot_2019-07-05_at_12-8f7ffbdc-c49f-49bc-95bb-1f53a926f361.30.27_PM.png" alt="Blog comment section with checkmarks" width="730" height="589" loading="lazy"></p>
<p>Checkmark! Finally, I recommend you try logging in with each individual OAuth configuration. That way you know it working for your website visitors. ?</p>
</li>
</ol>
<h2 id="heading-alternatives">Alternatives</h2>
<p>I spent a good chunk playing around with some of the alternatives. This is by no means a definitive guide on what will work best for your site. Here are some of the top ones as of this writing:</p>
<p><a target="_blank" href="https://utteranc.es/#configuration">https://utteranc.es/#configuration</a></p>
<p><a target="_blank" href="https://github.com/netlify/gotell">https://github.com/netlify/gotell</a></p>
<p><a target="_blank" href="https://github.com/eduardoboucas/staticman">https://github.com/eduardoboucas/staticman</a></p>
<p><a target="_blank" href="https://posativ.org/isso/">https://posativ.org/isso/</a></p>
<p><a target="_blank" href="https://www.remarkbox.com/">https://www.remarkbox.com</a></p>
<p><a target="_blank" href="https://www.vis4.net/blog/2017/10/hello-schnack/">https://www.vis4.net/blog/2017/10/hello-schnack/</a></p>
<p><a target="_blank" href="https://github.com/gka/schnack">https://github.com/gka/schnack</a></p>
<p>There's also a huge thread over at the Hugo blog which has a ton more links and resources as well:</p>
<p><a target="_blank" href="https://discourse.gohugo.io/t/alternative-to-disqus-needed-more-than-ever/5516">https://discourse.gohugo.io/t/alternative-to-disqus-needed-more-than-ever/5516</a></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Congrats! You are now hosting your own comments server! ?</p>
<p>In this article you've learned how to harness the power of Docker and a Nginx Reverse Proxy. As an added bonus, you know how to  set up OAuth credentials! That way future setup will be easy peasy.</p>
<p>By the way, this is only the tip of the iceberg. You can set up the same server for analytics, data collection and more. <a target="_blank" href="https://www.jaredwolff.com/files/host-your-comments/">All the example code including code for other applications can be found here.</a></p>
<p>Finally, if you're looking pay for Commento head to <a target="_blank" href="http://www.commento.io">www.commento.io</a> and sign up for the service. You'll be supporting awesome open source software!</p>
<p>If you have comments and questions let's hear em'. Start the conversation down below. ???</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to dance the OAuth: a step-by-step lesson ]]>
                </title>
                <description>
                    <![CDATA[ By Anabella Spinelli Most of the times I try to learn something new and put it into practice, I quickly start to feel like I’m lost in a myriad of dance moves. I’m desperately trying to find the right way to do things, while not really understanding ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-dance-the-oauth-a-step-by-step-lesson-fd2364d89742/</link>
                <guid isPermaLink="false">66c3515b465d1b2f886ba42e</guid>
                
                    <category>
                        <![CDATA[ data ]]>
                    </category>
                
                    <category>
                        <![CDATA[ oauth ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ user experience ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 03 Jul 2018 19:08:15 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*eTlZtD7s7bWMGaa0P4anvA.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Anabella Spinelli</p>
<p>Most of the times I try to learn something new and put it into practice, I quickly start to feel like I’m lost in a myriad of dance moves. I’m desperately trying to find the right way to do things, while not really understanding what’s going on or how I ended up on the wrong side of the room…</p>
<p>Just trying things out until something works.</p>
<p>Maybe it’s because of the way my learning process works, or maybe guides and tutorials are targeted at more experienced or technical people. But, after I’m done wrapping my head around the subject, I always feel like there should be an easy guide for understanding the key concepts <strong>and</strong> making it easier to apply them in a project.</p>
<p>So this time, I’ve decided to stop wishing for it and make it myself, using the last thing that I learned.</p>
<p>And that thing was OAuth 2.0.</p>
<h3 id="heading-what-is-oauth">What is OAuth?</h3>
<p>Let’s start with the basics: OAuth stands for <strong>Open Authorization</strong>. It’s a process through which an application or website can access private user data from another website.</p>
<p>This other website usually works only as a trusted <strong>identity provider</strong>. It gives the requesting app some basic information about you so that the app can create a profile. This way, you don’t have to fill in a boring sign-up form and deal with yet another password ?</p>
<p>You’ve already used this at least a gazillion times, in fact you used it every time you clicked on “Log in with Facebook / Google / GitHub / …”. Next, you were shown a consent screen that displayed which information from your (let’s say) Facebook profile you’re allowing <strong>that-hot-new-app.com</strong> to read (and sometimes, write). After that, since <strong>that-hot-new-app.com</strong> trusts the identity provided by Facebook, they can create a profile for you on their database using the data that they received.</p>
<p>The communication between <strong>that-hot-new-app.com</strong> and Facebook usually ends here. This is why your profile picture won’t change all across the Internet if you change it on Facebook. They just never go back to Facebook and ask for updated data.</p>
<h3 id="heading-when-marimba-rhythms-start-to-play">When marimba rhythms start to play…</h3>
<p>There’s another purpose for building this kind of mechanism, one with way more potential: using the identity provider as a <strong>service provider</strong> (in an ongoing manner). This means communicating with it regularly to supply enhanced features for your users.</p>
<p>A nice example of this is <a target="_blank" href="https://www.relive.cc/"><strong>Relive</strong></a>, a service that connects with different sports tracking apps to create Earth view videos of your run or ride. Every time you finish an activity, Relive prompts you offering to create a video from it. If you say yes, they’ll process it, and notify you when it’s ready for social media bragging… I mean sharing ?</p>
<p>There’s really no technical difference between these two usages. That’s why <strong>you should be cautious</strong> about where you log in with your social media or Google/Gmail account.</p>
<p>It might sound scary, but there's really nothing to fear. Just bear in mind that you’re authorizing <strong>that-hot-new-app.com</strong> to access that information about you that’s detailed in the consent screen, potentially on a recurrent basis. Be aware of the permissions you grant, and make sure you know how to disable them whenever you don’t feel trusting anymore.</p>
<p>For instance, if you are using your Google account for accessing <strong>that-hot-new-app.com</strong> but don’t want to allow that anymore, just go to your <a target="_blank" href="https://myaccount.google.com/security#connectedapps">Google account settings</a> and disable their access.</p>
<p>All the main identity providers offer control over this.</p>
<h3 id="heading-all-right-but-how-do-you-dance-the-oauth">All right, but how do you dance the OAuth?</h3>
<p>Before you land on <strong>that-hot-new-app.com</strong> and even click on “Log in with <code>YourFavoriteIdentityProvider</code><em>”</em>, someone — probably a developer — has to create an application on the provider’s site.</p>
<p>This is a way of registering <strong>that-hot-new-app.com</strong> so that, later, the provider knows who’s asking for private data.</p>
<p>In this step, the developer will set up some information about the application, like the app's name or website and — most importantly — <strong>a redirect URI</strong>. The provider (like Google or Facebook) will use this to contact the requesting app and tell them that the user said <em>yes</em> ?</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/-ZNoydoRCuDXAntqiAdKG9MVmuTjLk7qpOtW" alt="Image" width="800" height="366" loading="lazy">
<em>I promise you won't have to write it by hand, we pride ourselves on our paperlessness.</em></p>
<p>Once the app is registered, the provider will give <strong>that-hot-new-app.com</strong> a <strong>clientId</strong> and a <strong>clientSecret</strong> which will be used in the communications between them. They work sort of like a username and password for the application.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Nc8EUZy8o8w-5QddAogfWj2SifjW9Qh5OZWh" alt="Image" width="800" height="569" loading="lazy">
<em>You'll get the clientID and clientSecret right after you click on Save application</em></p>
<p>It's very important that you keep your clientSecret in a secure location and don't share it with strangers. If someone gets access to it, they could request private user data from the provider on your behalf, and then use it for evil!</p>
<p>We don't want that.</p>
<h4 id="heading-hands-on-waists-or-shoulders">Hands on waists or shoulders</h4>
<p>Apart from setting up all those things, the developer has to find out what kind of data the provider gives access to, and how it’s segmented.</p>
<p>These “segments” are known as <strong>scopes</strong> and they define access rights, usually separated in read/write categories. So, for example, <strong>that-hot-new-app.com</strong> can request for “<strong>profile:read</strong>” and “<strong>contacts:read</strong>” scopes. This means they can read whatever the provider assigns to the “profile” and “contacts” segments. Other things won’t be accessible, for example your posts or what content you like.</p>
<p>Well, just to make things simple for now on, let’s say that <strong>that-hot-new-app.com</strong> is a website that integrates with <a target="_blank" href="https://www.typeform.com/"><strong>Typeform</strong></a>, a service for creating beautiful and smart forms and also the company I work for. You definitely want in on the hottest thing right now, and quick, so on their website you click on “Log in with Typeform” to get right into the action. What’s next?</p>
<p>Here’s a home-made, organic, and cholesterol-free diagram to use as a map for the whole thing. It may look a bit complicated but don’t worry, we’ll examine each step up next.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/EieGAKMEfd4kumthtdBGcXE7rUq4xsvo8i15" alt="Image" width="800" height="1194" loading="lazy">
<em>Colorful notes bring joy to my heart</em></p>
<h3 id="heading-authorize-the-first-step-in-the-oauth-dance">Authorize: the first step in the OAuth dance</h3>
<p>So, you take the initiative and click on “Connect with Typeform”. Here, that-hot-new-app.com (<em>THNA</em> from now on, ’cause I’m getting tired of writing dash-separated words) will send you to Typeform’s authorize endpoint (<code>/oauth/authorize</code>) and provide:</p>
<ul>
<li>their clientId (remember, that’s <strong>THNA</strong>’s username)</li>
<li>their desired scopes (or access rights)</li>
<li>and their redirect URI again (Typeform already knows it from when we set up the whole thing, but we send it again as an extra layer of security)</li>
</ul>
<p>That URL will look something like this:</p>
<pre><code>https:<span class="hljs-comment">//api.typeform.com/oauth/authorize?client_id=yourClientId&amp;scope=accounts:read+forms:read+results:read</span>
</code></pre><p>Typeform will use this information to generate a consent screen where you can review what sort of things you’re authorizing <strong>THNA</strong> to see and do.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/istIyX0juNBgdwBXW2-y-sAzMhnOgkF1sY0R" alt="Image" width="800" height="251" loading="lazy"></p>
<p>Once you have <strong>thoroughly read what you’re consenting</strong> to and happily click on “Allow”, Typeform will send you to the redirect URI with a temporary, like so:</p>
<pre><code>https:<span class="hljs-comment">//that-hot-new-app.com/auth/redirect?code=xxxXXXxxxXXXxxx</span>
</code></pre><h3 id="heading-token-it-takes-2-to-tangoauth">Token: it takes 2 to tangOAuth ?</h3>
<p>All this back and forth feels like someone’s taking you for a tango spin, right?</p>
<p>The second step of the OAuth dance is when <strong>THNA</strong> receives that code, and exchanges it for an <strong>OAuth Token</strong>.</p>
<p>So <strong>THNA</strong> takes that code and sends it back again to Typeform, along with the redirect URI (yes, again!), and the client secret (that’s the app’s password!).</p>
<p>As reward for a dance well danced, <strong>THNA</strong> will get a shiny OAuth Token ✨ which it can use to interact with Typeform on behalf of the user, that is… you!</p>
<h4 id="heading-stay-with-me-sway-with-me">Stay with me, sway with me</h4>
<p>From now on, in every request <em>THNA</em> makes to Typeform on your behalf, they’ll have to include an <strong>Authorization</strong> header with that access token. With it, Typeform (or any other provider) can identify:</p>
<ul>
<li>who’s asking for the data (in this case, <strong>THNA</strong><em>)</em></li>
<li>who’s the data about (you!)</li>
<li>and also make sure they have the correct <strong>authorization</strong> to access that data (only what you consented to).</li>
</ul>
<h3 id="heading-ready-for-the-dance-floor">Ready for the dance floor ?</h3>
<p>So now that you know all the steps and spins of the OAuth dancing technique you should be ready to create your own choreographies, I mean, integrations, and make the Internet an even greater place.</p>
<p>Drawings by yours truly, cover photo by <a target="_blank" href="https://unsplash.com/photos/I_mkJxsx8kA?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Gez Xavier Mansfield</a> on <a target="_blank" href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
