Skip to content
Authentication Methods Explained — Sessions, JWT, OAuth 2.0 & Passkeys

Authentication Methods Explained — Sessions, JWT, OAuth 2.0 & Passkeys

DodaTech Updated Jun 15, 2026 5 min read

Authentication verifies who a user is — the first line of defense in any web application’s security model.

What You’ll Learn

In this tutorial, you’ll learn session-based authentication, JSON Web Tokens (JWT), OAuth 2.0 authorization flows, Single Sign-On (SSO), multi-factor authentication (MFA), and WebAuthn/passkeys.

Why It Matters

Authentication is the gateway to every protected resource. A broken authentication system can expose user data, allow account takeover, and lead to compliance violations. Understanding authentication methods helps you choose the right approach for your application.

Real-World Use

When you log into Google, it uses OAuth 2.0 to authenticate your Google account, issues an access token (JWT) for API access, and supports MFA for extra security. Doda Browser uses OAuth 2.0 to integrate with third-party identity providers for seamless login.


graph TD
  subgraph "Authentication Methods"
    A[Session-Based] --> B[Server stores session]
    C[Token-Based (JWT)] --> D[Client stores token]
    E[OAuth 2.0] --> F[Delegated authorization]
    G[WebAuthn] --> H[Passkeys / Biometrics]
  end
  A --> I[Traditional web apps]
  C --> J[SPAs / Mobile apps]
  E --> K[Third-party login]
  G --> L[Passwordless auth]

Session-Based Authentication

The server creates a session (stored in memory or database) and sends a session ID cookie to the browser. On each request, the server looks up the session to identify the user.

import secrets
from datetime import datetime, timedelta

class SessionStore:
    def __init__(self):
        self.sessions = {}

    def create_session(self, user_id):
        session_id = secrets.token_hex(32)
        self.sessions[session_id] = {
            "user_id": user_id,
            "created": datetime.now(),
            "expires": datetime.now() + timedelta(hours=24)
        }
        return session_id

    def get_user(self, session_id):
        session = self.sessions.get(session_id)
        if not session:
            return None
        if datetime.now() > session["expires"]:
            del self.sessions[session_id]
            return None
        return session["user_id"]

    def destroy_session(self, session_id):
        self.sessions.pop(session_id, None)

store = SessionStore()
sid = store.create_session(42)
print(f"Session ID: {sid}")
print(f"User: {store.get_user(sid)}")
store.destroy_session(sid)
print(f"After destroy: {store.get_user(sid)}")

Expected output:

Session ID: a1b2c3... (64 hex chars)
User: 42
After destroy: None

Token-Based Authentication (JWT)

JSON Web Tokens encode user identity in a self-contained, signed token. The server doesn’t need to store sessions — the token itself contains the user info (stateless).

import jwt
import datetime

SECRET_KEY = "my-secret-key-change-in-production"

def create_jwt(user_id, role="user"):
    payload = {
        "sub": user_id,
        "role": role,
        "iat": datetime.datetime.now(datetime.timezone.utc),
        "exp": datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(hours=1)
    }
    token = jwt.encode(payload, SECRET_KEY, algorithm="HS256")
    return token

def verify_jwt(token):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
        return payload
    except jwt.ExpiredSignatureError:
        return None
    except jwt.InvalidTokenError:
        return None

token = create_jwt(42, "admin")
print(f"JWT: {token[:50]}...")
decoded = verify_jwt(token)
print(f"Decoded: user_id={decoded['sub']}, role={decoded['role']}")

Expected output:

JWT: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Decoded: user_id=42, role=admin

OAuth 2.0 Flows

OAuth 2.0 is an authorization framework that allows third-party applications to access resources on behalf of a user.

FlowBest ForSecurity
Authorization CodeServer-side appsHighest
PKCEMobile/SPA appsHigh (prevents auth code interception)
Client CredentialsServer-to-serverNo user involvement
Device CodeInput-constrained devicesModerate

Authorization Code Flow (Simplified)

  1. User clicks “Login with Google”
  2. Browser redirects to Google’s auth URL with client ID and redirect URI
  3. Google authenticates user and asks for consent
  4. Google redirects back with an authorization code
  5. Server exchanges the code for an access token (server-to-server, secure)
  6. Server uses the access token to call Google APIs

Multi-Factor Authentication (MFA)

MFA adds layers beyond passwords:

FactorExamples
Something you knowPassword, PIN
Something you havePhone (TOTP), security key
Something you areFingerprint, face, voice

WebAuthn / Passkeys

WebAuthn is a W3C standard for passwordless authentication using public-key cryptography. The user’s device generates a key pair:

  • Private key: stored on the device (never leaves)
  • Public key: sent to the server

To authenticate, the user signs a challenge with their private key (using biometrics or PIN to unlock it).

Common Mistakes

  1. Storing JWT in localStorage: Vulnerable to XSS. Use httpOnly cookies instead.
  2. Not rotating refresh tokens: Access tokens expire quickly, but refresh tokens can be used indefinitely if not rotated after each use.
  3. Using weak secrets for JWT signing: A weak secret can be brute-forced, allowing attackers to forge tokens. Use at least 256-bit random keys.
  4. Setting short session timeouts too aggressively: Logging out users every 5 minutes frustrates UX. Balance security with usability.
  5. Not implementing rate limiting on login: Without rate limiting, attackers can brute-force passwords. Use exponential backoff or CAPTCHA after failed attempts.

Practice Questions

  1. What’s the difference between session and token-based auth? Sessions are stored server-side (stateful). Tokens (JWT) are self-contained (stateless) — the server doesn’t need to look up sessions.

  2. Why should JWT secrets be strong? A weak secret allows attackers to forge valid tokens, impersonating any user. Use a cryptographically random 256-bit key.

  3. What problem does PKCE solve in OAuth 2.0? It prevents authorization code interception attacks in mobile and SPA apps where the client secret can’t be kept confidential.

  4. What is the difference between authentication and authorization? Authentication verifies who you are. Authorization determines what you can do (what resources you can access).

  5. How does WebAuthn prevent phishing? The private key is bound to the origin domain. A phishing site on evil.com can’t use a passkey created for bank.com.

Challenge

Implement a complete authentication flow: user registers (password hashed with bcrypt), logs in (JWT issued), accesses protected route (JWT verified), refreshes token, and logs out (token blacklisted).

Real-World Task

Open your browser’s Application → Storage → Cookies. Find session cookies for sites you’re logged into. What attributes (HttpOnly, Secure, SameSite) are set?

Mini Project: Auth Server

Build a Flask/FastAPI authentication server supporting session-based auth and JWT. Include user registration, login, protected endpoints, and logout. Add rate limiting on login.

Security angle: Authentication is the foundation of application security. Doda Browser’s saved password manager uses encryption (not plaintext storage) and supports biometric unlock.

What’s Next

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

What’s Next

Congratulations on completing this Authentication tutorial! Here’s where to go from here:

  • Practice daily — Consistency is more important than long study sessions
  • Build a project — Apply what you learned by building something real
  • Explore related topics — Check out other tutorials in the same category
  • Join the community — Discuss with other learners and share your progress

Remember: every expert was once a beginner. Keep coding!

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro