Author: UnboundCompute

  • Authentication vs authorization, explained with examples

    Authentication vs authorization, explained with examples

    People mix these two words all the time, and the mix up causes real bugs. The difference between authentication vs authorization is simple once you see it: authentication proves who you are, and authorization decides what you are allowed to do. This post walks through both with a concrete login example, then shows how confusing them leads to broken access control.

    Authentication vs authorization in one sentence each

    Authentication answers the question “who are you?” You prove your identity, usually with a password, a passkey, or a one time code. When the app is satisfied, it knows it is talking to a specific user.

    Authorization answers a different question: “are you allowed to do this?” Once the app knows who you are, it checks whether that identity may read a record, edit a setting, or delete an account. Same user, different question.

    Authentication is the bouncer checking your ID at the door. Authorization is the staff checking whether your ticket lets you into the VIP room.

    A login is authentication

    You type an email and password into a SaaS app called Acme Notes. The server checks the password hash, sees it matches, and starts a session. That whole exchange is authentication. At the end of it the app is confident you are alice@example.com and nobody else. Nothing here has decided what Alice can touch yet.

    Opening a record is authorization

    Alice is now logged in. She clicks an invoice and the browser requests /invoice/123. The server has to answer a separate question before it returns anything: does invoice 123 belong to Alice? That check is authorization. If invoice 123 belongs to Bob, the correct answer is no, even though Alice is a fully authenticated, real user.

    The example that shows the gap

    Here is the request Alice’s browser sends after she logs in:

    GET /invoice/123 HTTP/1.1
    Host: app.acmenotes.example
    Cookie: session=alicevalidsessiontoken

    The session cookie is valid. Authentication passes. The dangerous question is what the server does next. A correct server loads invoice 123, checks the owner field against the session user, and returns the invoice only if they match. A broken server skips that check and returns the invoice to anyone who is logged in.

    Now Alice edits the URL by hand and asks for /invoice/124, then /invoice/125, walking the numbers up one at a time:

    GET /invoice/124 HTTP/1.1
    Host: app.acmenotes.example
    Cookie: session=alicevalidsessiontoken

    If the server returns Bob’s invoice because Alice’s session is valid, the app has confused authentication with authorization. Alice proved who she is. The app never checked what she is allowed to see. This is the most common shape of broken access control, often called an insecure direct object reference, or IDOR.

    Why the confusion is so easy to ship

    Login code gets careful attention. Teams test it, rate limit it, and add multi factor. So authentication tends to be solid. Authorization is spread across every endpoint that returns or changes data, and it is invisible when you test with a single account, because that account owns everything it can reach. The bug only appears when a second user asks for the first user’s data. Many test suites never try that, so the gap survives to production.

    Authentication vs authorization, side by side

    • Question asked. Authentication: who are you? Authorization: what may you do?
    • When it runs. Authentication runs once at login or per token. Authorization runs on every protected action.
    • What proves it. Authentication uses passwords, passkeys, or codes. Authorization uses ownership rules, roles, and permissions.
    • Typical failure. Authentication failing lets a stranger become a user. Authorization failing lets a real user reach data that is not theirs.
    • Where it lives. Authentication sits at the front door. Authorization sits at every record, field, and button behind it.
    • Status code on denial. Authentication problems return 401 Unauthorized. Authorization problems return 403 Forbidden.

    The status codes are worth a closer look, because their names are backwards from the concepts. The 401 code is literally named “Unauthorized” but it means you are not authenticated, so log in. The 403 code means you are authenticated but not authorized for this thing. If your code uses these interchangeably, that is often the first sign the two ideas are blurred in the codebase too.

    “Authentication and authorization difference” in plain terms

    If you search for the authentication and authorization difference, you will see them paired constantly, sometimes shortened to authn and authz. They run in order. Authn first, because you cannot decide what a user may do until you know who the user is. Authz second, on every single request that touches protected data. Reverse them or skip the second step and you get the invoice bug above.

    How to spot the gap before an attacker does

    You do not need fancy tooling to start. You need two accounts and a habit of suspicion.

    • Create two real users, Alice and Bob, with separate data.
    • Log in as Alice and note an object you own, like /invoice/123.
    • Log in as Bob and request Alice’s object directly by its id.
    • If Bob sees Alice’s data, you found a broken authorization check.
    • Repeat for write actions, not just reads. A POST or DELETE to another user’s object is worse than a read.

    Then push past predictable ids. Swap a numeric id for a UUID and the manual walk gets harder, but the missing check is still missing. The fix is the same in every case: every endpoint must check that the current authenticated user is allowed to act on the specific object, on the server, on every request. Never trust the client to hide a button or skip a URL.

    The vs authorization vs authentication ordering trap

    Some teams write a global middleware that confirms a valid session, then treat every authenticated request as fully allowed. That handles authentication and stops there. Authorization needs object level and field level rules that the middleware cannot know. A user may be allowed to read their own profile but not change their own role to admin. Same identity, different permissions, decided per action.

    If you only remember one thing about authentication vs authorization, make it this: proving who you are is not the same as being allowed, and the gap between them is where access control breaks. For more on this class of bug, see our access control articles. Tracking down a missing ownership check across hundreds of endpoints is exactly the kind of bug an autonomous researcher that tests an app’s assumptions is built to find. You can read how we approach that on our about page.

  • What is automated penetration testing?

    What is automated penetration testing?

    If you run a web app or an API, you have probably heard the phrase tossed around in security pitches. So what is automated penetration testing, and how is it different from the vulnerability scanner you may already run? In short, it is software that pokes at your application the way an attacker would, then tries to confirm what it finds, instead of a person doing every step by hand.

    This guide is for people who are new to the topic. We will define the term, compare it to a manual pentest and to a plain scanner, and be clear about what each tool is good at and where it falls short.

    What is automated penetration testing, in plain terms

    A penetration test, or pentest, is an authorized attempt to break into a system so you can fix the holes before a real attacker finds them. A human tester explores the app, forms a theory about what might break, and tries to exploit it. Automated penetration testing hands much of that loop to software. The tool maps the application, picks targets, sends crafted requests, and reports what got through.

    The word that matters here is exploit. A good automated pentest does not just say “this parameter looks risky.” It tries to actually use the weakness and shows you the result.

    The difference that counts is proof. A flag says maybe. A working exploit says yes, and here is the evidence.

    How it differs from a manual pentest

    A manual pentest is run by a person, often over one or two weeks, against a defined scope. Humans are good at understanding what an app is for. They read the screen, guess at business rules, and chase odd behavior that no rulebook predicted.

    Automation trades some of that judgment for speed and repeatability. Here is the honest trade:

    • Speed. Software can test thousands of requests in the time a person tests a handful.
    • Repeatability. You can run the same checks every night and on every deploy, not once a year.
    • Coverage of known classes. It is steady at the well understood bugs, like reflected injection or a missing access check on a predictable URL.
    • Weaker on context. It struggles with rules that only a human reading the app would know, such as “a trial account must never export the full customer list.”

    The two are not rivals. Many teams run automation often and bring in human testers for deep, scoped work on the parts that matter most.

    How it differs from a plain vulnerability scanner

    This is the comparison most people get wrong, so it is worth slowing down. A vulnerability scanner checks for known issues and reports anything that matches a signature. It might flag an out of date library, an open port, or a parameter that reflects input back to the page. That is useful, but a scanner usually stops at “this looks suspicious.”

    An automated pentest goes one step further and tries to prove the issue is real. Take a classic example. A scanner sees this request and notices the id value is reflected in the response:

    GET /api/invoices?id=1042
    Authorization: Bearer trial-user-token

    The scanner says: possible insecure direct object reference, please review. An automated pentest treats that as a theory to test. It changes the value and watches what comes back:

    GET /api/invoices?id=1043
    Authorization: Bearer trial-user-token
    
    HTTP/1.1 200 OK
    { "id": 1043, "customer": "Acme Notes", "total": 8800, "card_last4": "4242" }

    Now there is evidence. The trial user just read another customer’s invoice. That is no longer a maybe. It is a confirmed access control bug with a request you can replay. If the deeper reading on this distinction is what you are after, the scanners vs research category goes through it in more detail.

    Flagging versus verifying

    Hold this difference in your head, because it shapes everything else:

    • A scanner flags. It hands you a list of candidates ranked by severity, and a human has to check each one.
    • An automated pentest verifies. It tries the attack and keeps only the findings it could actually reproduce.

    The most useful tools sit on the verifying side. A short list of proven bugs is worth more than a long list of maybes, because every false alarm costs someone an hour of triage.

    What automated penetration testing is good at

    Used well, it earns its place. It is strong at:

    • Breadth. Checking every endpoint, every parameter, on a schedule a human could not keep.
    • Regression. A confirmed bug can become a repeatable check that watches for the same hole reappearing after a future deploy.
    • Fast feedback. Running on each release means a new flaw gets caught in days, not at the next annual review.

    Where it falls short

    Honesty matters more than the sales pitch, so here are the real limits.

    Logic bugs

    The bugs that hurt most often live in business logic, and those are the hardest to automate. Consider a checkout flow that applies a discount code. A tool that only sends known payloads will not think to apply the same code twice, or to set the quantity to a negative number so the total drops below zero. Those attacks come from understanding what the app is trying to do, then asking what happens if you bend a rule. A fixed payload list does not reason that way.

    Context and intent

    Software does not know your business rules unless someone teaches it. It cannot tell that a field labeled role should never be editable by the customer, or that an internal admin route was left exposed by accident. Without that context, it tests the requests it can see and misses the ones that only make sense once you understand the product.

    False positives and noise

    Tools that flag without verifying drown teams in noise. After enough false alarms, people stop reading the report, and a real finding gets lost in the pile. This is exactly why the verifying approach matters: proof cuts the noise.

    What good looks like

    If you are choosing a tool, look past the feature list and ask one question: does it prove its findings? The better systems do not just match patterns. They learn how the app is meant to work, form an idea about where that logic could break, design a test, and then confirm the result with concrete evidence before they bother you. Understand, assume, experiment, verify.

    The highest impact bugs come from understanding the app, not from matching a known string. That is the bar worth holding any tool to.

    Closing

    So, to answer the question plainly: automated penetration testing is software that attacks your app like an attacker would and, in its best form, proves what it finds rather than just listing suspects. It is fast and tireless on known issues, and weaker on logic and context, which is where a human or a smarter system earns its keep. This is the gap UnboundCompute is built to close, an autonomous researcher that tests the assumptions your app makes and proves a finding with hard evidence before reporting it. You can read more on the about page.