What this note is really about

Authentication and authorization are discussed constantly in software, but they are often mixed together so casually that people lose the real distinctions.

You will hear things like:

  • “add auth”
  • “protect the API”
  • “check permissions”
  • “log the user in”

Those may involve related mechanisms, but they are not all the same problem.

This note is about:

  • what authentication actually is
  • what authorization actually is
  • how they differ
  • what kinds of software need them
  • the main implementation patterns used today
  • the tools and frameworks people rely on
  • what it would take to implement them yourself manually

This topic is important because authentication and authorization are not optional details in serious software.

They are part of:

  • security
  • user identity
  • system boundaries
  • data protection
  • operational trust
  • compliance in some domains

So the goal here is not “memorize terms.”

The goal is to be clear-headed about the actual security boundary being designed.


The fundamental distinction

The cleanest starting point is this:

Authentication

Authentication answers:

Who are you?

It is the process of establishing identity.

Examples:

  • proving you are a specific user
  • proving this service is a trusted service
  • proving this device session belongs to a known account

Authorization

Authorization answers:

What are you allowed to do?

It is the process of deciding whether an authenticated identity may access a resource or perform an action.

Examples:

  • can this user read this document?
  • can this admin delete that account?
  • can this service call that internal endpoint?
  • can this customer see only their own orders?

Short rule

Authentication is about identity.

Authorization is about permissions.

That distinction is the foundation for everything else.


Why the distinction matters

A system can authenticate correctly and still authorize badly.

Examples:

  • the user is correctly logged in, but can access another user’s data
  • the API knows which service is calling, but that service has too many privileges
  • the admin role is granted too broadly

Likewise, a system can have authorization rules conceptually, but if authentication is weak, those rules are being applied to an untrusted or spoofable identity.

So strong systems need both:

  • reliable identity establishment
  • correct permission enforcement

If either half is weak, the boundary is weak.


Not all software needs the same level of auth

Different kinds of software need different identity and permission models.

Personal offline tools

Some software has no real user separation and may need little or no formal auth.

Examples:

  • a local single-user utility
  • a private script on your own machine

Consumer applications

These usually need:

  • user accounts
  • login
  • password reset
  • session management
  • account recovery
  • user-specific data protection

Examples:

  • e-commerce
  • social apps
  • productivity apps

Enterprise software

These often need:

  • organization-level identity
  • employee login
  • group and role mapping
  • auditability
  • admin control
  • single sign-on

Examples:

  • HR systems
  • finance tools
  • internal dashboards
  • SaaS products for companies

Public APIs and developer platforms

These often need:

  • API keys
  • OAuth flows
  • scopes
  • service-to-service trust
  • rate limits
  • tenant isolation

Internal microservices

These need:

  • service identity
  • secure communication
  • machine credentials
  • internal authorization boundaries

High-risk software

Banking, healthcare, identity systems, and admin platforms often need stronger controls such as:

  • multi-factor authentication
  • step-up verification
  • stronger audit trails
  • fine-grained authorization
  • shorter token lifetimes
  • anomaly detection

So the right auth model depends heavily on the software context.


Identity is broader than “user with password”

People often think authentication means:

  • username
  • password

That is only one common case.

Identities in software can include:

  • human users
  • admin users
  • service accounts
  • applications
  • devices
  • tenants or organizations
  • external partners

This matters because a secure system often has to authenticate more than one type of actor.

For example:

  • a browser user logs in
  • a mobile app holds tokens
  • a backend service calls another service
  • a scheduled job runs under a service identity

These are different identities with different trust models.


The main authentication factors

Authentication methods are often described in terms of what the subject proves.

Something you know

Examples:

  • password
  • PIN
  • security answer

Something you have

Examples:

  • phone receiving OTP
  • authenticator app
  • hardware key
  • smart card

Something you are

Examples:

  • fingerprint
  • face recognition
  • other biometrics

Modern security often combines multiple factors.

That is multi-factor authentication or MFA.

MFA matters especially when:

  • accounts are valuable targets
  • privileges are high
  • compliance requirements exist
  • phishing risk is high

Passwords: still common, but not enough by themselves

Passwords remain widely used because they are familiar and easy to deploy.

But passwords have major weaknesses:

  • reuse across sites
  • phishing
  • weak user choices
  • leaks from compromised services
  • credential stuffing attacks

So modern best practice is not “never use passwords.”

It is:

  • if passwords exist, handle them correctly
  • often combine them with MFA
  • increasingly support better login methods where possible

How passwords should be stored

This is one of the most important fundamentals.

You should never store plain-text passwords.

You should also not store them using simple fast hashes such as:

  • plain SHA-256
  • plain MD5
  • plain SHA-1

Why?

Because password storage needs protection against offline brute-force attacks if the credential database is leaked.

Modern password storage uses:

  • slow password hashing algorithms
  • salting
  • configurable work factors

Important names include:

  • Argon2
  • bcrypt
  • scrypt
  • PBKDF2

These are designed for password hashing, unlike ordinary fast cryptographic hashes.

The basic model is:

  • generate a unique salt
  • hash the password with a password-hashing algorithm
  • store the salt and resulting hash
  • on login, recompute and compare

That is a minimum baseline for password-based systems.


Sessions: the classic web model

One of the oldest and still very common patterns is:

  1. user logs in
  2. server verifies credentials
  3. server creates a session
  4. client stores a session identifier, often in a cookie
  5. future requests present that session identifier
  6. server looks up session state and recognizes the user

This is the classic session-based authentication model.

Important features:

  • the server keeps session state
  • the client usually stores only a session identifier
  • session invalidation is straightforward on the server side

This remains strong and practical for many web applications.


Cookies and browser-based auth

In browser-oriented systems, cookies remain a major tool.

Why?

Because browsers naturally support them for request continuity.

Security-related cookie attributes matter:

  • HttpOnly
  • Secure
  • SameSite

These help reduce risks such as:

  • script access to session cookies
  • sending cookies over insecure transport
  • certain cross-site request forgery patterns

A lot of practical browser auth is really session management plus safe cookie handling.


Tokens: the stateless-friendly model

Another common modern pattern is token-based authentication.

Instead of the server always looking up a session by ID, the client presents a token proving identity or authorization context.

Common token concepts include:

  • access token
  • refresh token
  • ID token in some identity protocols

A token may contain claims such as:

  • user identifier
  • issuer
  • audience
  • expiration
  • scopes
  • roles

But a token is only useful if:

  • it is issued securely
  • it is validated correctly
  • its lifetime and revocation model are understood

Token-based systems are common in:

  • SPAs
  • mobile apps
  • APIs
  • service-to-service communication

JWTs: common, useful, and often misunderstood

One widely used token format is the JWT:

  • JSON Web Token

A JWT can carry signed claims and be verified by the receiver.

Benefits:

  • portable
  • standardized
  • can work well across services

Common misunderstandings:

  • “JWT means secure by default”
  • “JWT means no server state is ever needed”
  • “JWT is always the best choice”

None of those are automatically true.

Important realities:

  • token contents are not secret just because the token is signed
  • long-lived tokens are risky
  • revocation can be harder than with server sessions
  • audience, issuer, signature, expiry, and algorithm validation must be correct

JWTs are a tool, not a security strategy by themselves.


OAuth 2.0: delegation, not just login

OAuth 2.0 is one of the most important names in modern auth, but many people misunderstand it.

OAuth is fundamentally about:

delegated authorization

That means one application can obtain limited access to resources on behalf of a user or client, without directly sharing the user’s password with every application.

This is why OAuth is central for:

  • third-party integrations
  • APIs
  • delegated access
  • platform ecosystems

OAuth by itself is not mainly “who is the user?” in the identity sense.

It is about delegated access grants.


OpenID Connect: identity on top of OAuth

If OAuth is mainly about delegated authorization, OpenID Connect or OIDC adds identity-layer concepts on top of that foundation.

OIDC is commonly used for:

  • user login through an identity provider
  • single sign-on
  • standard identity claims

So a practical summary is:

  • OAuth 2.0: delegated authorization framework
  • OpenID Connect: authentication/identity layer built on top of OAuth-style flows

This is one of the most important conceptual distinctions in modern software auth.


Single sign-on

In enterprise and platform environments, users often should not manage separate credentials for every system.

That leads to single sign-on or SSO.

With SSO:

  • one identity provider handles primary login
  • multiple applications trust that provider
  • users authenticate once and gain access to multiple systems according to policy

This helps with:

  • usability
  • centralized policy
  • employee lifecycle management
  • MFA enforcement
  • reduced password sprawl

Common enterprise identity providers support:

  • SAML
  • OAuth 2.0
  • OpenID Connect
  • directory integration

API keys

For some use cases, especially machine-to-machine or developer-platform access, APIs use API keys.

An API key is usually:

  • a secret string identifying a client or application
  • presented with requests

This can be useful for:

  • simple platform usage
  • quota enforcement
  • identifying calling applications

But API keys are limited.

They are usually weaker than full delegated identity systems because:

  • they are often long-lived
  • they usually represent the application, not a human user
  • they can be leaked
  • they often provide coarse access control

So API keys are practical, but not sufficient for every security model.


Service-to-service authentication

Modern distributed systems often need services to authenticate each other.

This is not browser login.

This is machine identity.

Common approaches include:

  • mTLS
  • signed tokens
  • workload identity systems
  • cloud IAM-based service identity
  • client certificates

Why this matters:

Inside a network, you still need trust boundaries.

“Internal” does not mean “safe by default.”

Service identity is a major part of modern platform security.


Authorization models

Once identity is established, the system must decide what that identity can do.

There are several important authorization models.

Role-based access control

RBAC assigns permissions through roles such as:

  • user
  • moderator
  • admin
  • billing-manager

This is common because it is simple and understandable.

Good for:

  • many enterprise systems
  • admin panels
  • coarse to medium-grained permissions

Weakness:

  • can become messy if too many exceptions accumulate

Permission-based or capability-based models

Instead of only broad roles, systems may use explicit permissions such as:

  • order.read
  • order.cancel
  • invoice.approve
  • user.delete

This supports finer control.

Attribute-based access control

ABAC makes decisions based on attributes such as:

  • user department
  • resource owner
  • tenant
  • data classification
  • time or location

This can be more expressive, but it is also more complex.

Policy-based authorization

Some systems define reusable policies that evaluate multiple conditions together.

This is common in modern frameworks because it scales better than sprinkling raw role checks everywhere.

Relationship-based authorization

Some systems base authorization on relationships such as:

  • owner
  • manager
  • collaborator
  • member of organization

This matters a lot in document-sharing, SaaS, and collaborative systems.

In practice, real systems often combine multiple models.


Authentication does not imply authorization

This point deserves repetition.

A user being authenticated does not mean they should access everything their account can technically reach through URLs or IDs.

Examples:

  • a user should see only their own invoices
  • a tenant admin should see only data within their tenant
  • a support staff member may read but not modify
  • a service can call billing APIs but not HR APIs

Strong authorization is usually contextual:

  • who is the caller?
  • what resource is involved?
  • what action is being attempted?
  • under what tenant, organization, or ownership rule?

This is why authorization checks must be close to domain meaning, not only route-level decoration.


Multi-tenant software

Many modern systems are multi-tenant:

  • one software platform serves many organizations or customer accounts

That creates a critical authorization concern:

tenant isolation

Even a properly authenticated user must usually be limited to:

  • their tenant
  • their organization’s data
  • their authorized scope within that tenant

Multi-tenant authorization bugs can be severe because they risk cross-customer data exposure.

So auth design in SaaS systems often includes:

  • tenant-scoped identities
  • tenant claims
  • tenant-aware queries
  • tenant-aware authorization rules

Different software types use auth differently

This is worth seeing side by side.

Traditional server-rendered web app

Often uses:

  • session cookies
  • server-side session storage
  • form login
  • CSRF protection

SPA plus backend API

Often uses:

  • token-based auth
  • OAuth/OIDC login via identity provider
  • short-lived access tokens
  • refresh tokens or silent re-auth patterns

Mobile apps

Often uses:

  • token-based auth
  • secure credential or token storage on device
  • OAuth/OIDC flows through browser or system web auth

Internal enterprise systems

Often uses:

  • SSO
  • corporate identity provider
  • MFA
  • role or group-based authorization

Public developer APIs

Often uses:

  • API keys for simple clients
  • OAuth for delegated user access
  • scopes
  • quotas
  • per-client limits

Microservices and platform systems

Often uses:

  • service identity
  • internal tokens or mTLS
  • policy-based authorization between services

So “how auth works” changes significantly depending on the software architecture.


Best practices for authentication today

At a broad modern level, strong practice usually includes:

  • use proven identity standards where appropriate
  • do not build password storage casually
  • hash passwords with proper password-hashing algorithms
  • support MFA where risk justifies it
  • use short-lived tokens where tokens are used
  • secure refresh mechanisms carefully
  • validate all token claims properly
  • use HTTPS everywhere
  • protect cookies properly if cookie-based sessions are used
  • design account recovery carefully
  • log security-relevant events
  • rotate secrets and keys
  • minimize credential exposure

The key pattern is:

prefer well-understood security building blocks over homemade cryptographic invention


Best practices for authorization today

Strong authorization practice usually includes:

  • enforce least privilege
  • keep permissions explicit
  • avoid spreading ad hoc checks randomly through the codebase
  • centralize policy logic where practical
  • authorize at the right level of domain meaning
  • include tenant and ownership rules where relevant
  • make admin privileges narrow and auditable
  • review default access carefully
  • log sensitive actions
  • test negative cases, not only happy paths

Authorization failures are often logic failures more than cryptographic failures.

So discipline and clear policy modeling matter greatly.


Manual implementation: what it means if you do it yourself

If you implemented authentication and authorization manually with your own code and no auth framework, the minimum correct path would look something like this: define a user identity model, build credential registration and login flows, hash passwords with a proper password-hashing algorithm such as Argon2, bcrypt, scrypt, or PBKDF2 using per-password salts, verify credentials during login, issue either a secure server-side session or a signed token with strict expiration and claim validation rules, protect transport with HTTPS, implement logout and credential reset flows, add MFA if needed, and then build an authorization layer that checks roles, permissions, ownership, tenant boundaries, and action-specific policies before executing protected operations. This is very possible in principle, but it is easy to get wrong in edge cases such as password recovery, token revocation, CSRF, refresh logic, secret rotation, privilege escalation, and auditability. That is why many teams rely on established protocols and battle-tested libraries rather than hand-rolling the entire system.


Why people use frameworks and services now

Authentication and authorization are easy to underestimate.

What looks simple at first quickly expands into:

  • login UI
  • password hashing
  • email verification
  • password reset
  • MFA enrollment
  • token issuance
  • token refresh
  • session revocation
  • audit trails
  • federation with external identity providers
  • SSO
  • permissions and policy evaluation
  • admin management

Because of that complexity, many teams now prefer:

  • libraries for lower-level auth primitives
  • framework-integrated auth middleware
  • external identity providers
  • managed auth platforms

This is not laziness.

It is often good security engineering.

You still need to understand the concepts, but you should not reinvent everything carelessly.


Tools and frameworks: broad categories

Instead of memorizing one product list only, it is better to understand the major categories.

1. Framework-level authentication and authorization systems

Most major web frameworks provide built-in or ecosystem-supported support for:

  • login middleware
  • session handling
  • policy checks
  • role checks
  • bearer token validation

Examples by ecosystem include:

  • ASP.NET Core Identity and ASP.NET Core authorization policies
  • Spring Security in Java
  • Django auth in Python
  • Laravel auth systems in PHP
  • Express or NestJS middleware ecosystems in Node.js
  • Rails authentication and authorization libraries in Ruby

These help because they integrate auth with:

  • routing
  • middleware
  • request context
  • session or token handling

2. Standards-based identity libraries

These help applications work with:

  • OAuth 2.0
  • OpenID Connect
  • JWT validation
  • SAML in some environments

They are used when the system needs:

  • external login
  • SSO
  • delegated authorization
  • token issuance or validation

3. Managed identity providers

Many teams use dedicated identity services such as:

  • Auth0
  • Okta
  • Microsoft Entra ID
  • Amazon Cognito
  • Keycloak
  • Clerk
  • Firebase Authentication
  • Supabase Auth

These provide varying combinations of:

  • user directories
  • login flows
  • social login
  • enterprise SSO
  • MFA
  • token issuance
  • user management

The advantage is reduced implementation burden.

The tradeoff is dependency on platform conventions, pricing, and integration boundaries.

4. Access control and policy engines

For complex authorization, some systems use policy engines or dedicated authorization tools.

Important names include:

  • OPA / Open Policy Agent
  • Zanzibar-inspired relationship systems
  • Cedar-inspired policy models in some ecosystems

These are useful when authorization is:

  • complex
  • cross-service
  • highly policy-driven
  • relationship-rich

5. Secrets and key management systems

Auth also depends on managing:

  • signing keys
  • client secrets
  • encryption material

So infrastructure tools such as:

  • cloud secret managers
  • HSM-backed key systems
  • Vault-style secret stores

are part of the broader auth story too.


Frameworks do not remove responsibility

Using a framework or identity provider does not mean security is solved automatically.

You still must decide:

  • what identities exist
  • what trust boundaries exist
  • what the token audience should be
  • what privileges each role or scope has
  • how tenant isolation works
  • what should be logged
  • what recovery flows are allowed
  • what session duration is acceptable

Frameworks reduce implementation risk in many areas, but they do not replace security design judgment.


Session-based vs token-based today

People often ask which one is “best.”

That is the wrong question.

The better question is:

“Which model fits this system and threat model?”

Session-based auth is often strong for:

  • traditional web apps
  • browser-based systems
  • systems where server-controlled revocation is important

Token-based auth is often strong for:

  • APIs
  • mobile clients
  • service-to-service systems
  • federated identity environments

Many modern architectures use a mix:

  • browser login via identity provider
  • backend session or token handling
  • access tokens for APIs
  • refresh tokens or re-auth flows

The correct design depends on architecture and risk.


Common mistakes

Weak auth systems often show one or more of these problems:

  • storing plain-text passwords
  • using fast hashes for passwords
  • confusing authentication with authorization
  • treating “logged in” as “fully trusted”
  • embedding too much permanent trust into long-lived tokens
  • weak tenant isolation
  • no MFA for high-value accounts
  • insecure password reset flows
  • role checks scattered randomly through code
  • no audit trail for sensitive actions
  • trusting client-supplied claims without server validation
  • exposing internal admin APIs too broadly

These are not edge details.

They are common sources of serious security failures.


A practical design workflow

When designing auth for a system, a useful sequence is:

  1. Identify the actors: users, admins, services, devices, partners.
  2. Identify the resources and actions that need protection.
  3. Decide the trust model: local accounts, external identity provider, SSO, service identity, or a mix.
  4. Choose the authentication mechanism appropriate to the software type.
  5. Choose the authorization model: roles, permissions, policies, relationships, tenant rules.
  6. Define session or token lifetime, revocation, recovery, and MFA strategy.
  7. Secure secrets, signing keys, and transport.
  8. Add audit logging, rate limiting, and failure monitoring.
  9. Test not only valid access, but denied access and boundary violations.
  10. Revisit the design as the system becomes more distributed or more security-sensitive.

This workflow is much more valuable than “just plug in a login package.”


The most important conceptual thread

If you want one flow that ties the whole topic together, it is this:

Authentication establishes identity, while authorization decides allowed actions. Modern software must often authenticate not only users, but also services, devices, and organizations. Different software types use different mechanisms: web apps often use sessions and cookies, APIs and mobile systems often use tokens, enterprise systems often use SSO and identity providers, and distributed backends often use service identity. Authorization then applies roles, permissions, policies, ownership, and tenant boundaries to those identities. Today, most serious systems rely on standard protocols, framework support, and managed identity tooling for the heavy lifting, while still requiring application-specific authorization logic, careful policy design, and strong operational practices such as MFA, secure secret handling, audit logging, and least privilege.


What you should come away knowing

You should leave this topic with these ideas clearly separated:

  1. Authentication is about identity.
  2. Authorization is about permissions.
  3. Many software systems need both, but not all in the same form.
  4. Passwords are only one authentication method, and must be stored properly if used.
  5. Sessions, cookies, tokens, OAuth, and OIDC solve different parts of the problem.
  6. API keys, service identity, and SSO matter in different architectures.
  7. Authorization models include roles, permissions, policies, attributes, and relationships.
  8. Tenant isolation and ownership checks are critical in many modern systems.
  9. Frameworks and identity providers help a lot, but they do not replace security thinking.
  10. The hardest part in many systems is not login itself, but getting authorization boundaries correct.

Bottom line

Authentication and authorization are foundational security boundaries in software. Authentication proves who the caller is, and authorization determines what that caller may do. Different software types implement them differently depending on whether the system is a browser app, mobile app, API platform, internal enterprise product, or distributed backend. Modern practice usually combines established password hashing, sessions or tokens, standards such as OAuth and OpenID Connect, MFA where appropriate, and framework or managed identity support, while keeping authorization logic explicit, domain-aware, least-privileged, and carefully audited.