Security Basics Lesson 6 – Authentication vs Authorization | Dataplexa
Section I · Lesson 6

Authentication vs Authorization

This lesson covers

Authentication vs authorization — the difference that matters → The three authentication factors → MFA and why it changed everything → Authorization models in practice → Broken access control, the most common web vulnerability → Reading auth failures in logs

In 2019, a security researcher typed a valid email address into a major healthcare portal, skipped the password field entirely, and got in. The application was checking the right identity — authentication passed — but the authorization logic had a flaw that let any authenticated session access any account. The researcher could view medical records belonging to complete strangers. Two different controls. One worked. One didn't. That gap is the entire lesson.

Two questions every system asks

Every time someone interacts with a secured system, two separate questions are being asked — usually so fast it feels like one.

Authentication asks: are you who you claim to be? It's identity verification. A username and password, a fingerprint scan, a hardware token — all of these are authentication mechanisms. The system doesn't yet care what you want to do. It just needs to confirm you are who you say you are.

Authorization asks: now that we know who you are, what are you allowed to do? It's permission enforcement. A verified employee might be authenticated to enter the building but not authorized to access the server room. A logged-in user might be authenticated on a banking app but not authorized to transfer more than £10,000 in a single transaction.

Authentication confirms identity. Authorization enforces what that identity can do. They are sequential — authorization can't happen without authentication — but they are completely independent controls that can fail independently.

Authentication

Proving identity. Login page, biometric scan, token. Answers: "Who are you?"

Fails when → credentials are stolen, weak passwords, no MFA

Authorization

Enforcing permissions. Role checks, access control lists, policy rules. Answers: "What can you do?"

Fails when → logic flaws, missing checks, over-privileged accounts

The three authentication factors

Authentication methods fall into three categories, and the distinction between them matters when you're designing a system that needs to resist attack.

Something you know — a password, PIN, or security question answer. The cheapest factor to implement and the easiest to steal. Phishing, credential stuffing, keyloggers — all of these attacks exist because passwords are purely informational. Anyone who obtains the information can use it.

Something you have — a physical device. A hardware token generating time-based codes, a smart card, a mobile phone receiving an SMS, a FIDO2 security key. The attacker needs to physically possess the device, or compromise it remotely, to use it. Significantly harder to steal than a password alone.

Something you are — biometrics. Fingerprint, face scan, voice pattern, retina. Convenient and hard to replicate in person, but comes with its own risks: biometric data can't be changed if it's compromised. You can reset a password. You can't reset your fingerprints.

SMS is the weakest "something you have"

SMS-based 2FA is better than nothing, but it's the weakest form of the second factor. SIM-swapping attacks — where an attacker convinces a mobile carrier to transfer your number to their SIM — let them intercept any SMS codes sent to you. In 2019, Twitter CEO Jack Dorsey's account was taken over this way. For anything sensitive, app-based TOTP codes (Google Authenticator, Authy) or hardware keys (YubiKey) are significantly more resistant.

MFA — the single control with the highest return

Multi-factor authentication combines two or more of those three categories. A password alone is single-factor. A password plus a TOTP code from an authenticator app is two-factor. A smart card plus a PIN plus a fingerprint is three-factor — overkill for most environments but standard in high-security ones.

Microsoft's own data puts the impact bluntly: enabling MFA blocks over 99.9% of automated credential attacks. An attacker who has your password still can't log in without your second factor. The entire ecosystem of credential stuffing — where billions of leaked username/password pairs get fired at every major platform — stops working the moment MFA is in place.

MFA isn't perfect. Attackers have developed MFA fatigue attacks — bombarding a target with push notification approval requests until they accidentally approve one out of frustration. They've built real-time phishing proxies that capture and replay MFA codes before they expire. But even accounting for these attacks, MFA remains the highest-return single control an organisation can deploy for the effort it requires.

Authorization models — three approaches

Once identity is confirmed, the system needs a model for deciding what that identity can access. Three models dominate real-world systems.

Role-Based Access Control (RBAC) assigns permissions to roles, then assigns users to roles. A "junior analyst" role can read security alerts. A "senior analyst" role can read and close them. A "manager" role can read, close, and configure alerting rules. Individual users don't have permissions directly — they inherit them from their role. RBAC is clean, auditable, and the most common model in enterprise environments.

Attribute-Based Access Control (ABAC) makes decisions based on attributes — properties of the user, the resource, and the environment. Access might be granted only if the user's department is "finance," the document classification is "internal," and the request is coming from a company IP address. More flexible than RBAC, but significantly more complex to implement and audit.

Discretionary Access Control (DAC) lets resource owners control who can access their own resources. A file owner on a Linux system can set read/write/execute permissions for themselves, their group, and everyone else. Flexible, but permission sprawl is a constant risk — owners grant access liberally and rarely revoke it.

Principle of Least Privilege

Regardless of the model in use, one principle runs through all good authorization design: give every user, process, and system the minimum permissions needed to do their job — nothing more. A marketing analyst doesn't need database admin rights. A web server process doesn't need to read /etc/shadow. Least privilege limits the blast radius when any account is compromised. The attacker gets what that account could access — not everything.

Broken access control — the most exploited flaw on the web

OWASP's Top 10 list — the industry's most referenced ranking of web application vulnerabilities — has listed broken access control at number one since 2021. It's the most widespread finding in web application penetration tests, and it's almost always an authorization failure, not an authentication one.

The classic pattern is an Insecure Direct Object Reference — IDOR. A user logs in, views their invoice at example.com/invoice?id=1042, then changes the URL to invoice?id=1041 and views someone else's invoice. The application authenticated them correctly. It just never checked whether invoice 1041 belonged to them.

# VULNERABLE: No authorization check — any logged-in user
# can retrieve any invoice by changing the ID
@app.route('/invoice')
def get_invoice():
    invoice_id = request.args.get('id')
    invoice = db.query("SELECT * FROM invoices WHERE id = ?", invoice_id)
    return render_template('invoice.html', invoice=invoice)


# SECURE: Authorization check added — user can only access
# invoices that belong to their own account
@app.route('/invoice')
@login_required
def get_invoice():
    invoice_id = request.args.get('id')
    invoice = db.query(
        "SELECT * FROM invoices WHERE id = ? AND user_id = ?",
        invoice_id, current_user.id
    )
    if not invoice:
        abort(403)  # Forbidden — not their invoice
    return render_template('invoice.html', invoice=invoice)

What just happened

The only difference between the vulnerable and secure versions is AND user_id = ? in the database query. Without it, the application is authenticated but not authorizing — it confirms who you are and then gives you whatever you ask for. This exact pattern has been responsible for some of the largest accidental data exposures in web application history.

Auth failures in logs — reading the signals

Authentication and authorization failures leave distinct traces. Here's what each looks like in a typical web application log:

# Filter authentication and authorization failures from an access log
grep -E " 401 | 403 " /var/log/nginx/access.log | tail -20
203.0.113.42 - - [14/Jun/2024:09:12:03] "POST /login HTTP/1.1" 401 185
203.0.113.42 - - [14/Jun/2024:09:12:05] "POST /login HTTP/1.1" 401 185
203.0.113.42 - - [14/Jun/2024:09:12:07] "POST /login HTTP/1.1" 401 185
203.0.113.42 - - [14/Jun/2024:09:12:09] "POST /login HTTP/1.1" 401 185
203.0.113.42 - - [14/Jun/2024:09:12:11] "POST /login HTTP/1.1" 200 942
192.168.1.55  - jsmith [14/Jun/2024:09:45:17] "GET /invoice?id=1041 HTTP/1.1" 200 3847
192.168.1.55  - jsmith [14/Jun/2024:09:45:19] "GET /invoice?id=1040 HTTP/1.1" 200 3712
192.168.1.55  - jsmith [14/Jun/2024:09:45:21] "GET /invoice?id=1039 HTTP/1.1" 200 3901
192.168.1.55  - jsmith [14/Jun/2024:09:45:23] "GET /invoice?id=1038 HTTP/1.1" 200 4012
10.0.0.91     - guest [14/Jun/2024:10:02:44] "GET /admin/users HTTP/1.1" 403 512
10.0.0.91     - guest [14/Jun/2024:10:02:46] "GET /admin/config HTTP/1.1" 403 512
10.0.0.91     - guest [14/Jun/2024:10:02:48] "GET /admin/logs HTTP/1.1" 403 512

What just happened

The first block is a brute-force authentication attack — four 401s in rapid succession from the same IP, then a 200. Someone eventually got the password right. The middle block is an IDOR probe — an authenticated user (jsmith) walking backwards through sequential invoice IDs they didn't request legitimately. The bottom block is authorization probing — a guest account testing admin endpoints and getting 403 Forbidden each time. 401 means authentication failed. 403 means authentication passed but authorization didn't. That single digit difference tells you exactly which control was hit.

Instructor's Note

In code reviews and penetration tests, I see authentication get fixed and authorization get forgotten constantly. Teams add login pages, implement MFA, hash passwords correctly — and then build the entire application assuming that if you're logged in, you're allowed to do whatever you're asking for. Broken access control is number one on the OWASP list because the industry still hasn't fixed this habit. Every endpoint, every action, every resource needs its own authorization check. Being logged in is not permission.


Practice Questions

A logged-in user changes a URL parameter from user_id=501 to user_id=502 and successfully views another user's profile. Authentication worked correctly. Which control failed?




A user enters their password and then approves a push notification on their phone to complete login. The phone notification belongs to which authentication factor category?




A web server process is given only the file system permissions it needs to serve web content — nothing more. Which authorization principle does this demonstrate?



Quiz

According to Microsoft's data, why is MFA considered the highest-return single authentication control?



A company gives every employee in the "finance" department access to billing reports by updating a single role definition. Which authorization model is this, and why does it scale cleanly?



A security analyst sees HTTP 401 responses on the login endpoint and HTTP 403 responses on the admin panel from the same IP. What does each status code indicate about which control was triggered?


Up Next · Lesson 7

Security Policies & Procedures

The documents nobody reads until something goes wrong — and why getting them right before that moment matters more than most teams think.