<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hecer Mehdiyeva</title>
    <description>The latest articles on DEV Community by Hecer Mehdiyeva (@hecer_mehdiyeva_ffd9cf57f).</description>
    <link>https://dev.to/hecer_mehdiyeva_ffd9cf57f</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3854044%2F923d4893-fd86-40c8-bb13-e1280dff579a.jpg</url>
      <title>DEV Community: Hecer Mehdiyeva</title>
      <link>https://dev.to/hecer_mehdiyeva_ffd9cf57f</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hecer_mehdiyeva_ffd9cf57f"/>
    <language>en</language>
    <item>
      <title>Authentication vs Authorization</title>
      <dc:creator>Hecer Mehdiyeva</dc:creator>
      <pubDate>Mon, 06 Apr 2026 14:26:25 +0000</pubDate>
      <link>https://dev.to/hecer_mehdiyeva_ffd9cf57f/authentication-vs-authorization-4nfe</link>
      <guid>https://dev.to/hecer_mehdiyeva_ffd9cf57f/authentication-vs-authorization-4nfe</guid>
      <description>&lt;p&gt;You've probably seen these two words a hundred times. You might even use them interchangeably. Don't worry — almost everyone does at first. Let's fix that, once and for all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Picture a nightclub
&lt;/h2&gt;

&lt;p&gt;It's Friday night. There's a line outside a club. Two things happen before you get in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The bouncer checks your ID — &lt;em&gt;"Are you who you say you are? Are you old enough?"&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Once inside, staff check your wristband — &lt;em&gt;"VIP? You get the private lounge. Regular ticket? Bar and dance floor only."&lt;/em&gt;
That's it. That's the whole concept.
&lt;strong&gt;Authentication&lt;/strong&gt; = the bouncer checking your ID.
&lt;strong&gt;Authorization&lt;/strong&gt; = the wristband deciding where you can go.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Now let's get a little more technical
&lt;/h2&gt;

&lt;p&gt;In software, every time a user logs into an app, these two processes are quietly running behind the scenes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication — "Who are you?"
&lt;/h3&gt;

&lt;p&gt;When you type your email and password into an app, the system checks: does this password match what we have stored for this email? If yes — you're &lt;strong&gt;authenticated&lt;/strong&gt;. You've proven your identity.&lt;br&gt;
Common authentication methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Password + username (classic)&lt;/li&gt;
&lt;li&gt;OAuth ("Sign in with Google")&lt;/li&gt;
&lt;li&gt;Biometrics — fingerprint, Face ID&lt;/li&gt;
&lt;li&gt;One-time passwords (OTP) sent by SMS or email&lt;/li&gt;
&lt;li&gt;Magic links
### Authorization — "What can you do?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you're logged in, authorization determines which parts of the app you can access. An admin can delete users. A regular user cannot. A free-tier customer can't use premium features. A moderator can remove posts but can't change billing settings.&lt;/p&gt;

&lt;p&gt;Common authorization models:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Role-Based Access Control (RBAC)&lt;/strong&gt; — "You're an admin, so you can do X"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permission-Based&lt;/strong&gt; — granular flags like &lt;code&gt;can_edit&lt;/code&gt;, &lt;code&gt;can_delete&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attribute-Based (ABAC)&lt;/strong&gt; — rules based on user attributes, time, location&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ownership checks&lt;/strong&gt; — "You can only edit your own posts"&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  The HTTP error codes give it away
&lt;/h2&gt;

&lt;p&gt;Here's a neat trick to remember which is which — look at the HTTP status codes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;401 Unauthorized&lt;/code&gt;&lt;/strong&gt; — Despite the confusing name, this means &lt;em&gt;authentication&lt;/em&gt; failed. "I don't know who you are. Please log in."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;403 Forbidden&lt;/code&gt;&lt;/strong&gt; — This means &lt;em&gt;authorization&lt;/em&gt; failed. "I know exactly who you are, but you're not allowed here."&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Think of it this way: 401 is the bouncer turning you away at the door. 403 is the bouncer saying "I recognize you, but you're not on the VIP list."&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  Why does the order matter?
&lt;/h2&gt;

&lt;p&gt;Authentication always comes first. You can't check what someone is allowed to do until you know who they are. It's a strict sequence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Identify → Verify → Authorize
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A common junior developer mistake is skipping authentication checks and jumping straight to authorization — or worse, trusting client-side data (like a &lt;code&gt;user_role&lt;/code&gt; sent from the frontend) without verifying the user's identity server-side first.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Don't do that.&lt;/strong&gt; Always verify the identity on the server before trusting any claims about what a user can do.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Quick cheat sheet
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Authentication&lt;/th&gt;
&lt;th&gt;Authorization&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Question&lt;/td&gt;
&lt;td&gt;Who are you?&lt;/td&gt;
&lt;td&gt;What can you do?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Purpose&lt;/td&gt;
&lt;td&gt;Prove identity&lt;/td&gt;
&lt;td&gt;Grant access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Examples&lt;/td&gt;
&lt;td&gt;Login, OAuth, biometrics&lt;/td&gt;
&lt;td&gt;Roles, permissions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP error&lt;/td&gt;
&lt;td&gt;401 Unauthorized&lt;/td&gt;
&lt;td&gt;403 Forbidden&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Order&lt;/td&gt;
&lt;td&gt;First&lt;/td&gt;
&lt;td&gt;Second&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;These two concepts are foundational to almost every app you'll ever build. Get them confused and you'll end up writing security bugs that are embarrassing at best and catastrophic at worst. But now that you have the nightclub analogy in your head, you'll never mix them up again.&lt;br&gt;
&lt;strong&gt;Authentication is the bouncer. Authorization is the wristband. Both are necessary. Neither is optional.&lt;/strong&gt;&lt;br&gt;
Happy coding. 🚀&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>learning</category>
    </item>
    <item>
      <title>This Code Will Betray You:</title>
      <dc:creator>Hecer Mehdiyeva</dc:creator>
      <pubDate>Tue, 31 Mar 2026 19:03:29 +0000</pubDate>
      <link>https://dev.to/hecer_mehdiyeva_ffd9cf57f/this-code-will-betray-you-59ai</link>
      <guid>https://dev.to/hecer_mehdiyeva_ffd9cf57f/this-code-will-betray-you-59ai</guid>
      <description>&lt;p&gt;🔐  This Code Will Betray You: The Hidden Flaw in Your Admin Panel&lt;br&gt;
 The Hidden Flaw in Your Admin Panel Imagine you've built a web application. Login system works, passwords are hashed, everything looks solid. You feel confident. Then someone simply types this URL:GET /admin/dashboard and walks right in. No attack tools, no exploit. Just a URL .This is Broken Access Control — ranked #1 on OWASP's list of the most critical web security risks. And it almost always comes from the simplest mistake.&lt;br&gt;
Where Is the Flaw?&lt;br&gt;
Take a look at this Flask code:_&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/admin/dashboard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;admin_dashboard&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;user_&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user _id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;  &lt;span class="nf"&gt;jsonify &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Please log in&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt;

    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; Welcome, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;! This is the admin panel.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code asks only one question: "Is this person logged in?"&lt;br&gt;
What it never asks: "Does this person actually have permission to be here?"&lt;br&gt;
So a regular user logs in, navigates to the URL, and gets this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Welcome, Ali! This is the admin panel."&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Ali is a regular user — but he's inside the admin panel. The code works perfectly. That's exactly why this bug goes unnoticed for so long&lt;/em&gt;.&lt;br&gt;
**&lt;br&gt;
The Fix**&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;admin_&lt;/span&gt; &lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nd"&gt;@wraps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decorated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;user_&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user _id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;user_&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Please log in&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt;

        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Access denied&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;decorated&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/admin/dashboard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@admin_required&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;admin_&lt;/span&gt; &lt;span class="nf"&gt;dashboard&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;@admin_ required&lt;/code&gt; — one line, full protection.&lt;/p&gt;

&lt;p&gt;Write it once, attach it to every protected route. If you forget — it returns &lt;code&gt;403&lt;/code&gt;, not your admin data.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Lesson
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Authentication&lt;/strong&gt; and &lt;strong&gt;authorization&lt;/strong&gt; are not the same thing.&lt;/p&gt;

&lt;p&gt;Authentication asks: &lt;em&gt;"Who are you?"&lt;/em&gt;&lt;br&gt;
Authorization asks: &lt;em&gt;"What are you allowed to do?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Locking the front door while leaving every room inside wide open is only half a security model.&lt;/p&gt;

&lt;p&gt;And hiding the URL doesn't help either. &lt;code&gt;/admin/secret-panel-xyz&lt;/code&gt; is not protection — it's just obscurity. Anyone who finds it gets in.&lt;/p&gt;

&lt;p&gt;Every time you write an endpoint, ask yourself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Am I checking that the user is logged in — or that they're allowed to be here?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One small line of code. One very large difference.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article is part of a series on Broken Access Control. Next up: IDOR — how attackers access anyone's data using nothing but an ID.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🏷️ Dev.to Tags
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#python #security #webdev #flask #beginners
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;`&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
