Loading learning content...
Before an operating system can enforce confidentiality, integrity, or availability policies, it must answer a fundamental question: Who is making this request? A file marked 'readable only by admin' is useless if anyone can claim to be admin. An access control list that grants privileges to 'alice' has no meaning if the system cannot distinguish alice from bob.
Authentication is the process of verifying that an entity is who or what it claims to be. It's the foundation upon which all other security mechanisms rest. Without reliable authentication, access controls become theater—apparently secure but trivially bypassed.
By the end of this page, you will understand authentication as a protection goal and its role in security, distinguish between different authentication factors, understand how operating systems implement user authentication, appreciate the challenges of secure authentication, and recognize modern approaches including multi-factor authentication.
Authentication establishes identity. In the physical world, we authenticate people through face recognition, voice recognition, signatures, or identity documents. In computer systems, we need technical mechanisms to achieve the same goal.
The Three Authentication Factors:
Authentication mechanisms are traditionally categorized into three factors based on what they verify:
Something you know — Passwords, PINs, security questions. Knowledge that should be known only by the legitimate user.
Something you have — Smart cards, hardware tokens, mobile phones. Physical possession of an item that should be held only by the legitimate user.
Something you are — Fingerprints, facial features, iris patterns, voice. Biometric characteristics inherent to the user's body.
| Factor | Examples | Strengths | Weaknesses |
|---|---|---|---|
| Knowledge | Password, PIN, security questions | Easy to implement, no hardware needed, easily changed if compromised | Can be guessed, phished, or forgotten; reuse across services |
| Possession | Smart card, hardware token, phone | Physical item is harder to steal remotely; can be combined with PIN | Can be lost, stolen, or damaged; requires distribution |
| Inherence | Fingerprint, face, iris, voice | Always with user, difficult to transfer, unique | Cannot be changed if compromised; privacy concerns; spoofable |
Multi-Factor Authentication (MFA):
Using multiple factors together dramatically improves security. Even if an attacker steals a password (knowledge), they still need the hardware token (possession). The security of MFA comes from the independence of factors—compromising one doesn't help compromise the other.
Identity vs. Authentication:
It's crucial to distinguish between identity (who you are) and authentication (proving who you are). A username is an identity claim; authentication verifies that claim. Modern systems often separate identity providers (who manage identity databases) from service providers (who rely on authentication assertions).
Some security frameworks recognize a fourth factor: 'somewhere you are' or contextual authentication. Location (IP geolocation, network), time of day, device fingerprinting, and behavioral patterns can supplement traditional factors. While not standalone authenticators, they help detect anomalies that suggest compromised credentials.
Passwords remain the most common authentication mechanism in operating systems despite their well-known weaknesses. Understanding how operating systems handle passwords—and how that has evolved—reveals important security principles.
The Evolution of Password Storage:
Early Unix stored password hashes in the world-readable /etc/passwd file. The assumption was that hashing made this safe. However, as computing power increased, offline dictionary attacks became practical. Modern systems store hashes in /etc/shadow, readable only by root, and use much stronger hashing algorithms.
Secure Password Hashing:
Modern password hashing differs from general cryptographic hashing. Password hashes must be:
| Algorithm | Era | Salt | Iterations | Security Status |
|---|---|---|---|---|
| DES crypt | 1970s | 12 bits | 25 | Completely broken |
| MD5 crypt ($1$) | 1994 | 48 bits | 1000 | Obsolete, too fast |
| SHA-512 crypt ($6$) | 2007 | 96 bits | 5000+ | Acceptable, not optimal |
| bcrypt ($2a$) | 1999 | 128 bits | 2^cost | Good, widely used |
| scrypt | 2009 | Variable | Configurable | Good, memory-hard |
| Argon2 (id) | 2015 | 128+ bits | Configurable | Best, PHC winner |
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
#include <stdio.h>#include <string.h>#include <crypt.h>#include <stdlib.h>#include <time.h> /** * Demonstrates secure password handling in system authentication. * This illustrates the mechanisms used by /etc/shadow. */ /* Generate cryptographically secure random salt */void generate_salt(char *salt, size_t len) { const char charset[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789./"; FILE *urandom = fopen("/dev/urandom", "r"); if (!urandom) { /* Fallback - NOT cryptographically secure! */ srand(time(NULL)); for (size_t i = 0; i < len; i++) { salt[i] = charset[rand() % (sizeof(charset) - 1)]; } } else { for (size_t i = 0; i < len; i++) { unsigned char byte; fread(&byte, 1, 1, urandom); salt[i] = charset[byte % (sizeof(charset) - 1)]; } fclose(urandom); } salt[len] = '\0';} /* * Hash password using modern algorithm (SHA-512 crypt). * Format: $6$<salt>$<hash> * $6$ indicates SHA-512 with 5000 rounds * For more rounds: $6$rounds=<n>$<salt>$<hash> */char* hash_password_sha512(const char *password) { char salt[20]; char setting[40]; /* Generate 16-character random salt */ generate_salt(salt, 16); /* Construct setting string with algorithm and rounds */ snprintf(setting, sizeof(setting), "$6$rounds=100000$%s$", salt); /* crypt() is thread-unsafe; use crypt_r() in production */ return crypt(password, setting);} /* * Verify password against stored hash. * The hash contains the algorithm, rounds, and salt, * so we just need to hash with same settings. */int verify_password(const char *password, const char *stored_hash) { /* Extract setting (everything up to and including salt) */ /* For $6$rounds=100000$SALT$HASH, setting is $6$rounds=100000$SALT$ */ char *computed_hash = crypt(password, stored_hash); if (computed_hash == NULL) { return -1; /* Hash computation failed */ } /* Constant-time comparison to prevent timing attacks */ size_t len = strlen(stored_hash); size_t computed_len = strlen(computed_hash); volatile unsigned char result = 0; if (len != computed_len) { return -1; /* Lengths differ - not equal */ } for (size_t i = 0; i < len; i++) { result |= stored_hash[i] ^ computed_hash[i]; } return result == 0 ? 0 : -1;} /* Example: What /etc/shadow entries look like *//* * root:$6$rounds=100000$AbC123...$<long hash>:18500:0:99999:7::: * ^algorithm ^salt ^hash ^password dates * * Fields: * 1: username * 2: hashed password or special values: * $6$... = SHA-512, $y$... = yescrypt, etc. * * or ! = account disabled * !! = password never set * 3: days since epoch of last password change * 4: minimum days between password changes * 5: maximum password age * 6: warning days before expiration * 7: days after expiration until account disabled * 8: absolute expiration date (days since epoch) * 9: reserved */String comparison typically stops at the first different character. An attacker can measure response time to determine how many characters matched, then brute-force character by character. Constant-time comparison always checks all characters, preventing this timing oracle. This seems paranoid but has enabled real attacks.
Early Unix systems had authentication logic integrated directly into login programs. This created maintenance nightmares when authentication requirements changed—every program needed modification. Pluggable Authentication Modules (PAM) solves this by providing a flexible, modular authentication framework.
PAM Architecture:
PAM separates applications from authentication mechanisms through a library interface. Applications call PAM, PAM consults configuration files, and PAM invokes appropriate modules. This allows:
| Type | Purpose | When Invoked |
|---|---|---|
| auth | Verify user identity (authenticate) | At login, when password is provided |
| account | Validate account (not locked, not expired) | After authentication, before access granted |
| password | Update authentication tokens (password change) | When user changes password |
| session | Session setup/teardown (mount home, logging) | At session start and end |
Control Flags:
PAM modules return success or failure. Control flags determine how PAM interprets these results:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
# /etc/pam.d/sshd - PAM configuration for SSH login# Format: type control module [options] # --- Authentication stack --- # Deny access to users in /etc/ssh/deny-users (if exists)auth requisite pam_listfile.so item=user sense=deny \ file=/etc/ssh/deny-users onerr=succeed # Standard Unix password authenticationauth required pam_unix.so try_first_pass # Two-factor: Google Authenticator TOTP# Required means both password AND OTP must succeedauth required pam_google_authenticator.so nullok # Log auth failure/success for auditingauth required pam_tally2.so deny=5 unlock_time=1800 \ audit silent # --- Account validation --- # Check account status (locked, expired, etc.) account required pam_unix.soaccount required pam_nologin.so # Check time-based access restrictionsaccount required pam_time.so # --- Session management --- # Set up user environmentsession required pam_unix.sosession required pam_limits.sosession optional pam_lastlog.so showfailedsession optional pam_motd.so # --- Password changes ---password required pam_pwquality.so minlen=12 dcredit=-1 \ ucredit=-1 ocredit=-1 lcredit=-1password required pam_unix.so sha512 shadow remember=12 # ========================================# Additional PAM modules and their uses:# ======================================== # pam_ldap.so - LDAP directory authentication# pam_krb5.so - Kerberos authentication# pam_fprintd.so - Fingerprint authentication# pam_pkcs11.so - Smart card (PKI) authentication# pam_u2f.so - FIDO U2F hardware token# pam_faillock.so - Account lockout after failures# pam_access.so - Access control by user/host/tty# pam_duo.so - Duo Security push notification # Example: Require hardware token for specific group# auth requisite pam_succeed_if.so user notingroup admin# auth required pam_u2f.so authfile=/etc/u2f_mappingsPAM configuration errors can lock everyone out of a system—including root. Always maintain console access when testing PAM changes. A misconfigured 'required' module on the authentication stack will deny all logins. Consider pam_warn.so for logging during testing, and never edit PAM files remotely without a backup access method.
Biometric authentication uses unique physical or behavioral characteristics to verify identity. Modern operating systems increasingly support fingerprints, facial recognition, and other biometrics as alternatives or supplements to passwords.
How Biometric Authentication Works:
Biometric systems don't store actual fingerprints or face images. Instead:
Accuracy Metrics:
Biometric systems trade off between two types of errors:
The Equal Error Rate (EER) is the point where FRR = FAR, used to compare biometric systems.
Operating System Integration:
Modern operating systems integrate biometrics at the platform level:
Secure Biometric Handling:
Biometric data is extremely sensitive—if leaked, it compromises the user forever. Best practices:
Unlike passwords, biometrics are not secret. Your fingerprints are on everything you touch; your face is photographed constantly. Biometrics prove 'this is the same finger that enrolled' but not 'this finger is attached to a living, willing participant.' Spoofing attacks using photos, 3D-printed fingerprints, or even masks have defeated commercial systems. Never rely on biometrics alone for high-security applications.
Possession-based authentication uses physical or cryptographic tokens to prove identity. Unlike passwords, tokens can't be easily guessed or phished. Unlike biometrics, they can be revoked and replaced.
Hardware Security Keys:
FIDO U2F and FIDO2/WebAuthn standards define interoperable hardware security keys. These devices perform cryptographic operations internally, never exposing private keys. They're phishing-resistant because they verify they're communicating with the legitimate site before authenticating.
Smart Cards and PKI:
Smart cards store X.509 certificates and private keys. During authentication, the card proves possession of the private key by signing a challenge. The server verifies the signature against the certificate. Operating systems support smart cards through PKCS#11 interfaces and dedicated middleware.
| Technology | Mechanism | OS Integration | Security Level |
|---|---|---|---|
| TOTP (Google Auth) | Time-based one-time passwords | PAM module (pam_oath) | Good, but phishable |
| HOTP | Counter-based one-time passwords | PAM module | Good, but phishable |
| Smart Card (X.509) | PKI challenge-response | PKCS#11, OS native | High |
| FIDO U2F | Hardware challenge-response | Browser, SSH via pam_u2f | High, phishing-resistant |
| FIDO2/WebAuthn | Platform authenticators, passwordless | Windows Hello, platform APIs | Highest, passwordless capable |
| PIV Card | US Gov smart card standard | Windows, macOS native, Linux pkcs11 | High, government approved |
123456789101112131415161718192021222324252627282930313233343536373839404142
# Setting up hardware security key authentication for SSH# Uses FIDO2/resident key (ed25519-sk) for passwordless login # Generate SSH key stored on hardware token# The key never leaves the device; private key operations # happen on the YubiKey itselfssh-keygen -t ed25519-sk -O resident -O verify-required \ -f ~/.ssh/id_ed25519_sk # Options explained:# -t ed25519-sk : Use Ed25519 with security key (FIDO2)# -O resident : Store key handle on device (portable)# -O verify-required : Require touch AND PIN for each use # For older U2F-only keys, use:ssh-keygen -t ecdsa-sk -O resident # The public key can be added to remote servers as usualcat ~/.ssh/id_ed25519_sk.pub >> ~/.ssh/authorized_keys # When connecting, SSH will prompt:# "Confirm user presence for key ED25519-SK..."# User must physically touch the security key # On server side, configure sshd for key-only auth# /etc/ssh/sshd_config:# PubkeyAuthentication yes# PasswordAuthentication no# ChallengeResponseAuthentication no # For resident keys, you can load from any machine:ssh-keygen -K # Downloads resident keys from device # Protecting SSH keys with FIDO2 PIN:# The -O verify-required option ensures even if someone# steals the hardware key, they need the PIN to use it. # Why hardware keys are phishing-resistant:# 1. Key is bound to specific origin (website/server)# 2. Browser/SSH verifies origin before authentication# 3. Attacker's phishing site has different origin# 4. Key refuses to authenticate to fake originFIDO2/WebAuthn enables true passwordless authentication. Passkeys (synced FIDO credentials) stored in platform authenticators or password managers combine security of hardware keys with convenience of passwords. Major operating systems now support passkeys, and adoption is accelerating. This may finally end the era of password-based attacks.
Authentication is among the most attacked surfaces in computing. Understanding attack vectors helps design resistant systems.
Credential Attacks:
Attackers targeting knowledge factors use:
Social Engineering:
Often easier than technical attacks:
| Attack | Primary Defense | Additional Measures |
|---|---|---|
| Brute force | Account lockout, rate limiting | CAPTCHA, progressive delays |
| Dictionary | Strong password requirements | Password blacklists, breach checking |
| Credential stuffing | MFA | Breach credential monitoring |
| Phishing | FIDO2/WebAuthn (origin binding) | User training, email filtering |
| Offline cracking | Strong hash algorithms (Argon2) | Proper salting, key stretching |
| Session hijacking | Secure cookies, short expiry | Binding to IP/device fingerprint |
| MFA fatigue | Number matching, location display | Rate limit push attempts |
Authentication security is bound by its weakest component. Requiring MFA for login but allowing email-based recovery defeats the purpose. Storing passwords securely but transmitting them over HTTP exposes them. Security-conscious design considers the entire authentication lifecycle, including enrollment, recovery, and session management.
As enterprises grow and cloud services proliferate, users face dozens of separate authentication requirements. Single Sign-On (SSO) addresses this by allowing one authentication to grant access to multiple services.
Benefits of SSO:
Identity Federation:
Federation extends SSO across organizational boundaries. Users authenticate with their home organization, then access services at partnering organizations. Standards like SAML, OpenID Connect, and OAuth enable this interoperability.
| Protocol | Primary Use | Token Type | OS/Enterprise Integration |
|---|---|---|---|
| Kerberos | Enterprise SSO | Tickets | Windows AD, Linux SSSD, MIT Kerberos |
| SAML 2.0 | Enterprise federation, web SSO | XML assertions | Enterprise apps, cloud services |
| OpenID Connect | Consumer/enterprise web SSO | JWT tokens | Modern apps, OAuth 2.0 based |
| WS-Federation | Microsoft-centric federation | XML tokens | ADFS, Azure AD |
| LDAP + Kerberos | Enterprise authentication backend | N/A (protocol) | PAM, SSSD, nslcd |
Kerberos: The Backbone of Enterprise SSO:
Kerberos, named after the three-headed dog of Greek mythology, provides SSO in most enterprise environments. Key concepts:
When you log into a Windows domain workstation, you receive a TGT. When you access a file server, your computer automatically requests a service ticket for that server. You're never prompted for credentials again during your session.
1234567891011121314151617181920212223242526272829303132333435363738394041424344
# Kerberos authentication from Linux command line # Authenticate and obtain TGT$ kinit alice@EXAMPLE.COMPassword for alice@EXAMPLE.COM: # List current tickets$ klistTicket cache: FILE:/tmp/krb5cc_1000Default principal: alice@EXAMPLE.COM Valid starting Expires Service principal01/15/24 10:00:00 01/15/24 20:00:00 krbtgt/EXAMPLE.COM@EXAMPLE.COM renew until 01/22/24 10:00:00 # Access Kerberized SSH - automatic ticket request$ ssh server.example.com# No password prompt - service ticket automatically obtained # Check tickets again - service ticket was added$ klistValid starting Expires Service principal01/15/24 10:00:00 01/15/24 20:00:00 krbtgt/EXAMPLE.COM@EXAMPLE.COM01/15/24 10:05:00 01/15/24 20:00:00 host/server.example.com@EXAMPLE.COM # Access Kerberized web service$ curl --negotiate -u : https://webapp.example.com/ # Destroy tickets on logout$ kdestroy # Linux PAM configuration for Kerberos login# /etc/pam.d/common-authauth sufficient pam_krb5.so minimum_uid=1000auth required pam_unix.so try_first_pass nullok # SSSD configuration for Active Directory integration# /etc/sssd/sssd.conf[domain/example.com]id_provider = adauth_provider = adkrb5_realm = EXAMPLE.COMad_server = dc.example.comad_domain = example.comSSO concentrates risk—compromise of the identity provider compromises all connected services. Protecting the identity provider is paramount. This includes MFA for IdP access, monitoring for anomalous authentication patterns, and robust key management for signing tokens. The convenience of SSO justifies the effort only if the IdP is exceptionally well-protected.
Authentication verifies identity, enabling operating systems to enforce security policies on the correct principals. From passwords to biometrics to hardware tokens, multiple mechanisms exist with different security and usability characteristics. Let's consolidate our understanding:
What's Next:
Authentication answers 'who are you?' The next question is 'what are you allowed to do?' In the final page of this module, we'll explore Authorization—the process of determining what actions an authenticated identity may perform. Together, authentication and authorization form the complete access control picture.
You now understand authentication as a protection goal, including the three factors, password handling, PAM, biometrics, hardware tokens, and SSO. This knowledge enables you to design robust authentication systems and evaluate their security. Next, we'll examine authorization—how authenticated identities are granted or denied access to resources.