Introduction: Authentication vs Authorization
Authentication and authorization are distinct but related concepts. Authentication verifies WHO you are. Authorization determines WHAT you can do.
Series Context: This is Part 15 of 20 in the Complete Protocols Master series. Authentication protocols operate at the Application Layer (Layer 7).
1
Part 1: OSI Model & Protocol Foundations
Network layers, encapsulation, TCP/IP model
2
Physical & Data Link Layers
Ethernet, Wi-Fi, VLANs, MAC addressing
3
Network Layer & IP
IPv4, IPv6, ICMP, routing protocols
4
Transport Layer
TCP, UDP, QUIC, ports, sockets
5
Session & Presentation Layers
TLS handshake, encryption, serialization
6
Web Protocols
HTTP/1.1, HTTP/2, HTTP/3, WebSockets
7
API Protocols
REST, GraphQL, gRPC, SOAP
8
DNS Deep Dive
DNS hierarchy, records, DNSSEC
9
Email Protocols
SMTP, IMAP, POP3, SPF/DKIM/DMARC
10
File Transfer Protocols
FTP, SFTP, SCP, rsync
11
Real-Time Protocols
WebRTC, SIP, RTP, VoIP
12
Streaming Protocols
HLS, DASH, RTMP, media delivery
13
IoT Protocols
MQTT, CoAP, Zigbee, LoRaWAN
14
VPN & Tunneling
IPsec, OpenVPN, WireGuard
15
Authentication Protocols
OAuth, SAML, OIDC, Kerberos
You Are Here
16
Network Management
SNMP, NetFlow, Syslog
17
Security Protocols
TLS/SSL, certificates, PKI
18
Cloud Provider Protocols
AWS, Azure, GCP APIs
19
Emerging Protocols
QUIC, HTTP/3, WebTransport
20
Web Security Standards
CORS, CSP, HSTS, SRI
Concepts
Authentication vs Authorization
Authentication vs Authorization:
AUTHENTICATION (AuthN)
"Who are you?"
• Verifies identity
• Username/password
• Certificates
• Biometrics
AUTHORIZATION (AuthZ)
"What can you access?"
• Permissions
• Roles
• Access control
• Scopes
Example - Hotel:
• AuthN: Show ID at check-in (prove identity)
• AuthZ: Key card grants room access (not other rooms)
Protocol Mapping:
• OAuth 2.0: Authorization only
• OpenID Connect: Authentication (built on OAuth)
• SAML: Both (primarily AuthN)
• Kerberos: Both (tickets grant access)
• LDAP: Directory (stores identity data)
Overview
Protocol Landscape
| Protocol | Type | Best For | Token Format |
| OAuth 2.0 | Authorization | API access, mobile | Opaque/JWT |
| OIDC | AuthN + AuthZ | Web login, SSO | JWT (ID Token) |
| SAML 2.0 | AuthN + AuthZ | Enterprise SSO | XML Assertion |
| Kerberos | AuthN + AuthZ | Active Directory | Tickets |
| LDAP | Directory | User lookup | N/A |
OAuth 2.0: Authorization Framework
OAuth 2.0 is THE authorization standard for APIs. It lets users grant apps limited access without sharing credentials. "Log in with Google" uses OAuth.
Key Insight: OAuth 2.0 is about AUTHORIZATION, not authentication. It answers "Can this app access my photos?" not "Who is this user?"
Roles
OAuth 2.0 Actors
OAuth 2.0 Roles:
1. RESOURCE OWNER
The user who owns the data
Example: You
2. CLIENT
The application wanting access
Example: Third-party photo app
3. AUTHORIZATION SERVER
Issues tokens after user consent
Example: Google's auth server
4. RESOURCE SERVER
Hosts the protected data
Example: Google Photos API
Flow:
User → "I want to use PhotoApp"
PhotoApp → "Please authorize at Google"
User → Google: "Yes, allow read-only photos"
Google → PhotoApp: "Here's an access token"
PhotoApp → Google Photos API: "Token: xyz, get photos"
API → PhotoApp: "Here are the photos"
Grant Types
OAuth 2.0 Flows
OAuth 2.0 Grant Types:
1. AUTHORIZATION CODE (most secure)
Best for: Server-side web apps
Flow: Code exchanged for token server-side
2. AUTHORIZATION CODE + PKCE
Best for: Mobile apps, SPAs
Flow: Code + code_verifier for security
PKCE = Proof Key for Code Exchange
3. CLIENT CREDENTIALS
Best for: Machine-to-machine (no user)
Flow: App authenticates directly
4. DEVICE CODE
Best for: TVs, CLI tools (no browser)
Flow: User authorizes on separate device
5. IMPLICIT (deprecated)
Was for: SPAs (replaced by PKCE)
Issue: Token in URL fragment
# Authorization Code Flow with PKCE
# Step 1: Generate code verifier and challenge
code_verifier="random-43-to-128-character-string"
code_challenge=$(echo -n "$code_verifier" | sha256sum | cut -d' ' -f1 | xxd -r -p | base64 -w0 | tr '+/' '-_' | tr -d '=')
# Step 2: Redirect user to authorization
https://auth.example.com/authorize?
client_id=my-app&
response_type=code&
redirect_uri=https://myapp.com/callback&
scope=read:photos&
state=random-csrf-token&
code_challenge=$code_challenge&
code_challenge_method=S256
# Step 3: User logs in and consents
# Redirected back with authorization code
# Step 4: Exchange code for tokens (server-side)
curl -X POST https://auth.example.com/token \
-d "grant_type=authorization_code" \
-d "code=AUTHORIZATION_CODE" \
-d "redirect_uri=https://myapp.com/callback" \
-d "client_id=my-app" \
-d "code_verifier=$code_verifier"
# Response:
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "dGhpcyBpcyBhIHJlZnJlc2g..."
}
# OAuth 2.0 Client Credentials Flow (Python)
import requests
import base64
def client_credentials_flow():
"""Machine-to-machine authentication"""
client_id = "my-service"
client_secret = "super-secret"
token_url = "https://auth.example.com/token"
# Request access token
response = requests.post(
token_url,
data={
"grant_type": "client_credentials",
"scope": "api:read api:write"
},
auth=(client_id, client_secret)
)
tokens = response.json()
access_token = tokens["access_token"]
print(f"Access Token: {access_token[:50]}...")
print(f"Expires in: {tokens['expires_in']} seconds")
# Use token to call API
api_response = requests.get(
"https://api.example.com/data",
headers={"Authorization": f"Bearer {access_token}"}
)
return api_response.json()
# Token structure (JWT)
print("""
JWT Structure:
HEADER.PAYLOAD.SIGNATURE
Header: {"alg": "RS256", "typ": "JWT"}
Payload: {
"iss": "https://auth.example.com",
"sub": "user123",
"aud": "api.example.com",
"exp": 1735689600,
"scope": "read:photos"
}
Signature: RSASHA256(header + payload, private_key)
""")
OpenID Connect: Identity Layer
OpenID Connect (OIDC) adds authentication to OAuth 2.0. It provides an ID Token that proves who the user is—not just what they can access.
OIDC
OIDC vs OAuth 2.0
OIDC = OAuth 2.0 + Identity
What OIDC Adds:
• ID Token (JWT proving identity)
• UserInfo endpoint
• Standard claims (name, email, picture)
• Discovery endpoint
Tokens in OIDC:
• Access Token: API authorization (same as OAuth)
• ID Token: User identity (NEW in OIDC)
• Refresh Token: Get new tokens (same as OAuth)
ID Token Claims:
{
"iss": "https://accounts.google.com",
"sub": "110169484474386276334", // Unique user ID
"aud": "my-client-id",
"exp": 1735689600,
"iat": 1735686000,
"name": "Jane Doe",
"email": "jane@example.com",
"picture": "https://..."
}
# OIDC Discovery Endpoint
curl https://accounts.google.com/.well-known/openid-configuration
# Returns:
{
"issuer": "https://accounts.google.com",
"authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",
"token_endpoint": "https://oauth2.googleapis.com/token",
"userinfo_endpoint": "https://openidconnect.googleapis.com/v1/userinfo",
"jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",
"scopes_supported": ["openid", "email", "profile"],
"response_types_supported": ["code", "token", "id_token"],
"claims_supported": ["sub", "name", "email", "picture"]
}
# OIDC Authentication (Python with Authlib)
def oidc_example():
"""Demonstrate OIDC authentication"""
print("OIDC Authentication Flow")
print("=" * 50)
print("""
# Flask OIDC Example
from authlib.integrations.flask_client import OAuth
oauth = OAuth(app)
oauth.register(
name='google',
client_id='your-client-id',
client_secret='your-client-secret',
server_metadata_url='https://accounts.google.com/.well-known/openid-configuration',
client_kwargs={'scope': 'openid email profile'}
)
@app.route('/login')
def login():
redirect_uri = url_for('callback', _external=True)
return oauth.google.authorize_redirect(redirect_uri)
@app.route('/callback')
def callback():
token = oauth.google.authorize_access_token()
# ID Token contains user identity
id_token = token['id_token']
userinfo = token['userinfo']
# Now you know WHO the user is
user_id = userinfo['sub']
email = userinfo['email']
name = userinfo['name']
return f'Hello {name}!'
""")
print("\nKey OIDC Scopes:")
print("• openid: Required, returns ID token")
print("• profile: Name, picture, etc.")
print("• email: Email address")
print("• address: Physical address")
print("• phone: Phone number")
oidc_example()
SAML 2.0: Enterprise SSO
SAML (Security Assertion Markup Language) is the enterprise standard for Single Sign-On. XML-based, mature, used by most corporate identity providers.
SAML
SAML Components
SAML 2.0 Components:
1. IDENTITY PROVIDER (IdP)
• Authenticates users
• Issues SAML assertions
• Examples: Okta, Azure AD, ADFS
2. SERVICE PROVIDER (SP)
• Your application
• Trusts the IdP
• Consumes assertions
3. SAML ASSERTION
• XML document proving identity
• Contains attributes (email, groups)
• Digitally signed by IdP
SAML Flows:
• SP-Initiated: User starts at app, redirected to IdP
• IdP-Initiated: User starts at IdP portal
SP-Initiated Flow:
User → SP: "Access app"
SP → User: "Redirect to IdP"
User → IdP: "Login page"
User → IdP: "Credentials"
IdP → User: "SAML Response (redirect to SP)"
User → SP: "Here's SAML Response"
SP → User: "Authenticated! Welcome"
# SAML Response Structure (simplified)
<samlp:Response>
<Issuer>https://idp.example.com</Issuer>
<Status>
<StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</Status>
<Assertion>
<Issuer>https://idp.example.com</Issuer>
<Subject>
<NameID>user@example.com</NameID>
</Subject>
<Conditions NotBefore="2026-01-31T00:00:00Z"
NotOnOrAfter="2026-01-31T00:05:00Z">
<AudienceRestriction>
<Audience>https://sp.example.com</Audience>
</AudienceRestriction>
</Conditions>
<AttributeStatement>
<Attribute Name="email">
<AttributeValue>user@example.com</AttributeValue>
</Attribute>
<Attribute Name="groups">
<AttributeValue>admin</AttributeValue>
<AttributeValue>developers</AttributeValue>
</Attribute>
</AttributeStatement>
<Signature>...</Signature>
</Assertion>
</samlp:Response>
# SAML Service Provider (Python with python-saml)
def saml_sp_example():
"""Demonstrate SAML Service Provider"""
print("SAML Service Provider Configuration")
print("=" * 50)
print("""
# Flask SAML Example (using python3-saml)
from onelogin.saml2.auth import OneLogin_Saml2_Auth
@app.route('/saml/login')
def saml_login():
req = prepare_flask_request(request)
auth = OneLogin_Saml2_Auth(req, custom_base_path=SAML_PATH)
return redirect(auth.login())
@app.route('/saml/acs', methods=['POST'])
def saml_acs():
# Assertion Consumer Service - receives SAML Response
req = prepare_flask_request(request)
auth = OneLogin_Saml2_Auth(req, custom_base_path=SAML_PATH)
auth.process_response()
errors = auth.get_errors()
if not errors:
# Authentication successful
attributes = auth.get_attributes()
name_id = auth.get_nameid()
user_email = attributes.get('email', [None])[0]
user_groups = attributes.get('groups', [])
# Create session
session['user'] = {
'email': user_email,
'groups': user_groups
}
return redirect('/dashboard')
else:
return f'SAML Error: {errors}', 400
""")
print("\nSAML Metadata Exchange:")
print("• SP publishes metadata (entity ID, ACS URL, cert)")
print("• IdP publishes metadata (SSO URL, signing cert)")
print("• Both import each other's metadata")
saml_sp_example()
Kerberos: Network Authentication
Kerberos is the authentication backbone of Active Directory. Uses tickets instead of passwords—users authenticate once, get tickets for services.
Kerberos
Kerberos Architecture
Kerberos Components:
1. KDC (Key Distribution Center)
• Authentication Server (AS)
• Ticket Granting Server (TGS)
• Holds all secrets
2. TICKETS
• TGT (Ticket Granting Ticket): Proves identity
• Service Ticket: Grants access to specific service
3. PRINCIPALS
• Users: user@REALM.COM
• Services: HTTP/web.realm.com@REALM.COM
Kerberos Authentication:
User → AS: "I'm alice, want TGT"
AS → User: "Here's TGT (encrypted)"
User → TGS: "TGT, want ticket for fileserver"
TGS → User: "Here's service ticket"
User → FileServer: "Service ticket"
FileServer → User: "Access granted"
Key Concept: User password NEVER sent over network
# Kerberos ticket management (Linux)
# Initialize (get TGT)
kinit alice@EXAMPLE.COM
# Enter password (locally hashed, not sent)
# List tickets
klist
# Ticket cache: FILE:/tmp/krb5cc_1000
# Default principal: alice@EXAMPLE.COM
#
# Valid starting Expires Service principal
# 01/31/2026 09:00 01/31/2026 19:00 krbtgt/EXAMPLE.COM@EXAMPLE.COM
# Get service ticket (automatic when accessing service)
curl --negotiate -u : http://web.example.com/
# Destroy tickets (logout)
kdestroy
# Check keytab (for service accounts)
klist -k /etc/krb5.keytab
# Kerberos authentication in Python
def kerberos_example():
"""Kerberos authentication demonstration"""
print("Kerberos in Python")
print("=" * 50)
print("""
# Using requests-kerberos
import requests
from requests_kerberos import HTTPKerberosAuth
# Auto-use cached TGT
response = requests.get(
'https://api.example.com/data',
auth=HTTPKerberosAuth()
)
# For SPNEGO (HTTP Negotiate)
from requests_kerberos import HTTPKerberosAuth, OPTIONAL
response = requests.get(
'https://api.example.com/data',
auth=HTTPKerberosAuth(mutual_authentication=OPTIONAL)
)
""")
print("\nKerberos vs Password Auth:")
print("• Kerberos: Ticket-based, password never leaves client")
print("• Password: Sent to server (even if encrypted)")
print("• Kerberos: Mutual auth (server proves identity too)")
print("• Kerberos: Time-limited tickets, auto-expire")
kerberos_example()
LDAP: Directory Services
LDAP (Lightweight Directory Access Protocol) stores and retrieves identity data. It's not strictly an authentication protocol—it's the database that backs authentication.
LDAP
LDAP Structure
LDAP Concepts:
1. DIRECTORY TREE (DIT)
Hierarchical structure
dc=example,dc=com (domain)
└── ou=People
└── uid=alice
└── uid=bob
└── ou=Groups
└── cn=developers
2. DISTINGUISHED NAME (DN)
Unique identifier for entry
uid=alice,ou=People,dc=example,dc=com
3. ATTRIBUTES
cn: Common Name
uid: User ID
mail: Email
userPassword: Hashed password
memberOf: Group membership
4. OPERATIONS
• Bind: Authenticate
• Search: Query
• Add/Modify/Delete: CRUD
# LDAP queries with ldapsearch
# Anonymous search (if allowed)
ldapsearch -x -H ldap://ldap.example.com \
-b "dc=example,dc=com" "(uid=alice)"
# Authenticated search
ldapsearch -x -H ldap://ldap.example.com \
-D "cn=admin,dc=example,dc=com" -W \
-b "ou=People,dc=example,dc=com" "(objectClass=person)"
# Search specific attributes
ldapsearch -x -H ldap://ldap.example.com \
-b "dc=example,dc=com" "(uid=alice)" cn mail memberOf
# Test authentication (bind)
ldapwhoami -x -H ldap://ldap.example.com \
-D "uid=alice,ou=People,dc=example,dc=com" -W
# LDAP authentication in Python
import ldap3
def ldap_auth(username, password):
"""Authenticate user against LDAP"""
server = ldap3.Server('ldap://ldap.example.com', get_info=ldap3.ALL)
user_dn = f"uid={username},ou=People,dc=example,dc=com"
try:
conn = ldap3.Connection(server, user_dn, password, auto_bind=True)
print(f"✅ Authentication successful for {username}")
# Search for user attributes
conn.search(
user_dn,
'(objectClass=person)',
attributes=['cn', 'mail', 'memberOf']
)
if conn.entries:
user = conn.entries[0]
print(f" Name: {user.cn}")
print(f" Email: {user.mail}")
print(f" Groups: {user.memberOf}")
conn.unbind()
return True
except ldap3.core.exceptions.LDAPBindError:
print(f"❌ Authentication failed for {username}")
return False
# Example
# ldap_auth('alice', 'password123')
Protocol Comparison
Decision Guide
Choosing Authentication Protocol
| Scenario | Best Choice | Reason |
| Modern web app | OIDC | Industry standard, JWT tokens |
| Mobile app | OAuth 2.0 + PKCE | Secure, no client secret |
| Enterprise SSO | SAML | Mature, wide support |
| Windows domain | Kerberos | Built into AD |
| API authorization | OAuth 2.0 | Scoped access tokens |
| Machine-to-machine | OAuth 2.0 CC | No user involved |
OIDC vs SAML
When to Use Which
OIDC vs SAML:
OIDC (Modern):
✅ JSON/JWT (lightweight)
✅ Mobile-friendly
✅ REST APIs
✅ Modern IdPs (Auth0, Okta)
✅ Easier to implement
SAML (Enterprise):
✅ Mature, battle-tested
✅ Wide enterprise support
✅ Complex attribute mapping
✅ Legacy system integration
❌ XML (verbose)
❌ Complex to implement
Choose OIDC for:
• New applications
• Mobile apps
• API-first architecture
• Consumer applications
Choose SAML for:
• Enterprise with existing SAML IdP
• Legacy system integration
• Complex attribute requirements
• Regulatory compliance
Summary & Next Steps
Key Takeaways:
- OAuth 2.0: Authorization framework for API access
- OIDC: Identity layer on OAuth, provides ID tokens
- SAML: Enterprise SSO with XML assertions
- Kerberos: Ticket-based auth for AD domains
- LDAP: Directory for storing identity data
Quiz
Test Your Knowledge
- OAuth 2.0 vs OIDC? (AuthZ vs AuthN)
- What is PKCE? (Proof Key for Code Exchange, mobile security)
- SAML vs OIDC token format? (XML vs JWT)
- What's a TGT in Kerberos? (Ticket Granting Ticket)
- LDAP purpose? (Directory storage, identity lookup)
Related Articles
Part 14: VPN & Tunneling
IPsec, WireGuard, OpenVPN for secure tunnels.
Read Article
Part 16: Network Management
SNMP, NetFlow, syslog monitoring.
Read Article