Overview
Authentication and authorization represent two distinct security mechanisms that control access to application resources. Authentication verifies identity—confirming that users are who they claim to be. Authorization determines permissions—defining what authenticated users can access or modify within the system.
The distinction matters because these processes serve different security functions and occur at different stages of access control. Authentication happens first, establishing user identity through credentials like passwords, tokens, or biometric data. Authorization follows, checking the authenticated identity against access rules to grant or deny specific operations.
Consider a web application: when users enter their username and password, the system performs authentication by validating credentials against stored records. After successful authentication, when users attempt to view another user's profile or delete a post, the system performs authorization by checking whether their role permits those actions.
This separation of concerns enables flexible security models. Systems can authenticate users through multiple methods while maintaining centralized authorization logic. Applications can also implement different authorization schemes for the same authenticated users based on context, resource sensitivity, or business rules.
Key Principles
Authentication establishes identity through credential verification. The process involves presenting credentials (knowledge factors like passwords, possession factors like security keys, or inherence factors like fingerprints) and validating them against stored authentication data. Successful authentication produces an identity token or session that represents the authenticated user for subsequent requests.
Authentication mechanisms vary in strength and implementation complexity. Password-based authentication compares submitted passwords against stored hashes. Token-based authentication validates cryptographic tokens issued during initial login. Multi-factor authentication combines multiple credential types to increase security. Certificate-based authentication verifies cryptographic certificates issued by trusted authorities.
The authentication process typically generates a session identifier or authentication token after successful verification. This token accompanies subsequent requests, allowing the system to recognize the authenticated user without requiring credential resubmission for each action. Session tokens expire after defined periods to limit exposure from token theft.
Authorization operates on the established identity to control resource access. The system evaluates whether the authenticated identity has permission to perform requested operations on specific resources. Authorization decisions consider multiple factors: user roles, resource ownership, operation type, and contextual conditions like time of day or IP address.
Authorization models structure permission decisions differently. Role-Based Access Control (RBAC) assigns permissions to roles, then assigns roles to users. Users inherit permissions from all assigned roles. Attribute-Based Access Control (ABAC) evaluates attributes of users, resources, and environmental context to make decisions. Access Control Lists (ACL) attach permissions directly to resources, specifying which users or groups can perform which operations.
The authorization process occurs after authentication establishes identity. Each request carries authentication credentials or tokens that identify the user. The authorization system loads the user's permissions, evaluates them against the requested operation and resource, then allows or denies the request. This evaluation happens for every access attempt, even when users remain authenticated for extended periods.
Separation between authentication and authorization enables independent evolution of each mechanism. Applications can change authentication methods—from passwords to OAuth to biometrics—without modifying authorization logic. Organizations can restructure permission models without affecting how users authenticate. This decoupling reduces complexity and improves security by allowing each system to focus on its specific responsibility.
Security Implications
Authentication vulnerabilities expose systems to identity theft and unauthorized access. Weak password policies allow brute force attacks to guess credentials. Credential storage flaws, like plain text passwords or weak hashing algorithms, enable attackers who breach databases to immediately access accounts. Session token weaknesses permit session hijacking, where attackers steal tokens to impersonate authenticated users.
Secure authentication requires strong credential storage. Systems must hash passwords using algorithms like bcrypt, scrypt, or Argon2 that resist brute force attacks through computational cost. Password hashing should include per-user salts to prevent rainbow table attacks. Never store passwords reversibly or use fast hashing functions like MD5 or SHA-1 for credential storage.
require 'bcrypt'
# Secure password storage
class User
attr_accessor :email, :password_hash
def password=(new_password)
@password_hash = BCrypt::Password.create(new_password)
end
def authenticate(password_attempt)
BCrypt::Password.new(@password_hash) == password_attempt
end
end
user = User.new
user.email = "user@example.com"
user.password = "secure_password_123"
# => Stores hashed password
user.authenticate("wrong_password")
# => false
user.authenticate("secure_password_123")
# => true
Session token security prevents unauthorized access after authentication. Tokens should be cryptographically random with sufficient entropy to resist guessing. Applications must implement token expiration, forcing reauthentication after defined periods. Secure cookies require HttpOnly flags to prevent JavaScript access and Secure flags to ensure HTTPS-only transmission. Token rotation on privilege escalation limits exposure from stolen tokens.
Multi-factor authentication significantly improves security by requiring multiple credential types. Even if attackers steal passwords, they cannot authenticate without the second factor. Time-based One-Time Passwords (TOTP) generate temporary codes from shared secrets. SMS-based codes send authentication values to registered phone numbers. Hardware tokens provide possession-based authentication that resists remote attacks.
Authorization vulnerabilities allow privilege escalation where users access resources beyond their permissions. Insecure Direct Object References (IDOR) occur when applications fail to verify authorization before serving requested resources. Parameter tampering enables users to modify request parameters to access unauthorized data. Missing function-level access control allows users to invoke administrative functions by directly calling endpoints.
Secure authorization requires explicit permission checks for every access attempt. Applications must verify authorization after authentication but before serving resources or executing operations. Permission checks should occur at multiple levels: controller actions must verify broad access rights, while service layer logic enforces resource-specific permissions based on ownership and roles.
class PostsController < ApplicationController
before_action :authenticate_user!
before_action :set_post, only: [:show, :edit, :update, :destroy]
before_action :authorize_post_access, only: [:edit, :update, :destroy]
def show
# Public posts visible to all authenticated users
# Authorization check happens in set_post
end
def edit
# Only authorized users reach this action
end
def update
if @post.update(post_params)
redirect_to @post
else
render :edit
end
end
private
def set_post
@post = Post.find(params[:id])
# Verify basic read access
authorize_read_access
end
def authorize_read_access
unless @post.public? || @post.user == current_user || current_user.admin?
redirect_to root_path, alert: "Not authorized"
end
end
def authorize_post_access
unless @post.user == current_user || current_user.admin?
redirect_to root_path, alert: "Not authorized"
end
end
end
Horizontal privilege escalation occurs when users access resources belonging to other users at the same privilege level. Applications must verify resource ownership or explicit permissions before allowing access. Database queries should filter results by user identity, not rely solely on client-provided identifiers. Parameter validation must reject attempts to access resources through ID manipulation.
Vertical privilege escalation enables regular users to perform administrative functions. Applications must implement role checks for sensitive operations, not just authentication checks. Administrative endpoints require explicit role verification. Default deny policies improve security by requiring explicit permission grants rather than blocking known unauthorized operations.
Time-of-check to time-of-use (TOCTOU) vulnerabilities arise when authorization checks occur separately from resource access. Attackers can modify state between the authorization check and actual operation. Applications should perform authorization checks atomically with resource operations, or implement locking mechanisms to prevent state changes between check and use.
Ruby Implementation
Ruby applications implement authentication through various gems and frameworks. Devise provides comprehensive authentication including password resets, email confirmation, and session management. Clearance offers simpler authentication for applications needing basic functionality. Authlogic gives developers more control through explicit authentication logic rather than framework magic.
Devise integrates authentication into Rails applications through generated models, controllers, and views. The gem handles password encryption, session management, and security features like Rememberable for persistent sessions and Lockable for account locking after failed attempts.
# Gemfile
gem 'devise'
# app/models/user.rb
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable,
:confirmable, :lockable, :timeoutable
end
# config/routes.rb
Rails.application.routes.draw do
devise_for :users
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :authenticate_user!
def current_user
# Provided by Devise
end
end
JWT authentication supports stateless authentication for API applications. The server signs tokens containing user identity and expiration data. Clients include tokens in request headers for authentication. The server verifies signatures and expiration before authorizing requests.
require 'jwt'
class AuthenticationService
SECRET_KEY = ENV['JWT_SECRET_KEY']
ALGORITHM = 'HS256'
def self.encode_token(payload, expiration = 24.hours.from_now)
payload[:exp] = expiration.to_i
JWT.encode(payload, SECRET_KEY, ALGORITHM)
end
def self.decode_token(token)
decoded = JWT.decode(token, SECRET_KEY, true, algorithm: ALGORITHM)
decoded[0]
rescue JWT::DecodeError, JWT::ExpiredSignature
nil
end
end
# Usage in controller
class ApiController < ActionController::API
before_action :authenticate_request
private
def authenticate_request
header = request.headers['Authorization']
token = header.split(' ').last if header
decoded = AuthenticationService.decode_token(token)
if decoded
@current_user = User.find(decoded['user_id'])
else
render json: { error: 'Unauthorized' }, status: :unauthorized
end
end
end
Authorization in Ruby applications uses specialized gems for permission management. Pundit implements policy-based authorization where each model has a corresponding policy class defining permissions. CanCanCan uses ability classes to centralize authorization rules. ActionPolicy provides behavior-driven authorization with explicit policy testing.
Pundit structures authorization around policy classes that define permission methods. Controllers query policies before allowing actions. Policies receive the current user and resource, returning boolean values indicating permission status.
# Gemfile
gem 'pundit'
# app/policies/post_policy.rb
class PostPolicy
attr_reader :user, :post
def initialize(user, post)
@user = user
@post = post
end
def show?
post.published? || post.user == user || user.admin?
end
def update?
post.user == user || user.admin?
end
def destroy?
post.user == user || user.admin?
end
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
if user.admin?
scope.all
else
scope.where(published: true).or(scope.where(user: user))
end
end
end
end
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
include Pundit::Authorization
def index
@posts = policy_scope(Post)
end
def show
@post = Post.find(params[:id])
authorize @post
end
def update
@post = Post.find(params[:id])
authorize @post
if @post.update(post_params)
redirect_to @post
else
render :edit
end
end
end
CanCanCan centralizes authorization in ability classes that define what users can do. The gem uses a declarative syntax specifying abilities for roles or conditions. Controllers check abilities using simple method calls.
# Gemfile
gem 'cancancan'
# app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user
if user.admin?
can :manage, :all
elsif user.moderator?
can :read, Post, published: true
can :manage, Post, user_id: user.id
can :manage, Comment
else
can :read, Post, published: true
can :create, Post
can :manage, Post, user_id: user.id
can :create, Comment
can :manage, Comment, user_id: user.id
end
end
end
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
load_and_authorize_resource
def show
# @post already loaded and authorized
end
def update
if @post.update(post_params)
redirect_to @post
else
render :edit
end
end
end
Custom authorization implementations provide flexibility for complex requirements. Applications can build authorization services that evaluate permissions based on multiple factors including user attributes, resource state, and environmental context.
class AuthorizationService
def initialize(user)
@user = user
end
def can?(action, resource)
case resource
when Post
can_access_post?(action, resource)
when Comment
can_access_comment?(action, resource)
else
false
end
end
private
def can_access_post?(action, post)
case action
when :read
post.published? || post.user == @user || @user.admin?
when :create
@user.present?
when :update, :destroy
post.user == @user || @user.admin?
else
false
end
end
def can_access_comment?(action, comment)
case action
when :read
comment.post.published? || @user.admin?
when :create
@user.present? && comment.post.published?
when :update, :destroy
comment.user == @user || @user.admin?
else
false
end
end
end
# Usage in controllers
class ApplicationController < ActionController::Base
def authorize_action(action, resource)
service = AuthorizationService.new(current_user)
unless service.can?(action, resource)
redirect_to root_path, alert: "Not authorized"
end
end
end
Practical Examples
Web applications demonstrate the interaction between authentication and authorization. Users authenticate through login forms, receiving session cookies that persist their identity. Subsequent requests use session cookies for authentication, then authorization checks determine whether authenticated users can perform requested actions.
# Authentication: Login action
class SessionsController < ApplicationController
skip_before_action :authenticate_user!, only: [:new, :create]
def new
# Login form
end
def create
user = User.find_by(email: params[:email])
if user && user.authenticate(params[:password])
# Authentication successful
session[:user_id] = user.id
redirect_to dashboard_path
else
# Authentication failed
flash.now[:alert] = "Invalid email or password"
render :new
end
end
def destroy
session[:user_id] = nil
redirect_to root_path
end
end
# Application controller handles authentication
class ApplicationController < ActionController::Base
before_action :authenticate_user!
private
def authenticate_user!
unless current_user
redirect_to login_path, alert: "Please log in"
end
end
def current_user
@current_user ||= User.find_by(id: session[:user_id])
end
end
# Authorization: Resource controller
class ArticlesController < ApplicationController
def edit
@article = Article.find(params[:id])
# Authorization check
unless @article.user == current_user || current_user.admin?
redirect_to articles_path, alert: "Not authorized"
end
end
end
API applications implement token-based authentication without server-side sessions. Clients authenticate by submitting credentials to receive JWT tokens. Subsequent API requests include tokens in Authorization headers. The server validates tokens to authenticate requests, then checks permissions to authorize operations.
class AuthController < ApiController
skip_before_action :authenticate_request, only: [:login]
def login
user = User.find_by(email: params[:email])
if user && user.authenticate(params[:password])
token = AuthenticationService.encode_token(
user_id: user.id,
email: user.email,
role: user.role
)
render json: { token: token, user: user }, status: :ok
else
render json: { error: 'Invalid credentials' }, status: :unauthorized
end
end
end
class ArticlesController < ApiController
def create
article = Article.new(article_params)
article.user = @current_user
if article.save
render json: article, status: :created
else
render json: { errors: article.errors }, status: :unprocessable_entity
end
end
def update
article = Article.find(params[:id])
# Authorization check
unless article.user == @current_user || @current_user.admin?
return render json: { error: 'Forbidden' }, status: :forbidden
end
if article.update(article_params)
render json: article
else
render json: { errors: article.errors }, status: :unprocessable_entity
end
end
end
Multi-tenant applications separate authentication from tenant-specific authorization. Users authenticate once but may have different permissions across multiple tenants. Authorization checks must verify both user identity and tenant-specific permissions.
class Account < ApplicationRecord
has_many :memberships
has_many :users, through: :memberships
has_many :projects
end
class Membership < ApplicationRecord
belongs_to :account
belongs_to :user
enum role: { viewer: 0, editor: 1, admin: 2, owner: 3 }
end
class ApplicationController < ActionController::Base
before_action :authenticate_user!
before_action :set_current_account
private
def set_current_account
@current_account = Account.find_by(subdomain: request.subdomain)
@current_membership = @current_account.memberships.find_by(user: current_user)
unless @current_membership
redirect_to accounts_path, alert: "Access denied to this account"
end
end
def authorize_account_action(required_role)
role_levels = { viewer: 0, editor: 1, admin: 2, owner: 3 }
user_level = role_levels[@current_membership.role.to_sym]
required_level = role_levels[required_role]
unless user_level >= required_level
redirect_to account_path(@current_account),
alert: "Insufficient permissions"
end
end
end
class ProjectsController < ApplicationController
def create
authorize_account_action(:editor)
@project = @current_account.projects.build(project_params)
@project.user = current_user
if @project.save
redirect_to @project
else
render :new
end
end
def destroy
@project = @current_account.projects.find(params[:id])
authorize_account_action(:admin)
@project.destroy
redirect_to projects_path
end
end
OAuth authentication enables users to authenticate through third-party providers. Applications redirect users to providers for authentication, receiving authorization codes after successful authentication. Applications exchange codes for access tokens, using tokens to retrieve user information and authenticate users in the application.
# config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET'],
{
scope: 'email,profile',
prompt: 'select_account'
}
end
class SessionsController < ApplicationController
def create_from_omniauth
auth = request.env['omniauth.auth']
# Find or create user from OAuth data
user = User.find_or_create_by(provider: auth.provider, uid: auth.uid) do |u|
u.email = auth.info.email
u.name = auth.info.name
u.oauth_token = auth.credentials.token
u.oauth_expires_at = Time.at(auth.credentials.expires_at)
end
session[:user_id] = user.id
redirect_to root_path
end
end
Common Pitfalls
Confusing authentication with authorization leads to security vulnerabilities. Developers sometimes implement authentication checks but assume authenticated users can access all resources. Applications must explicitly authorize each action, not just verify authentication. Authentication confirms identity while authorization controls access.
# INCORRECT: Only checks authentication
class PostsController < ApplicationController
before_action :authenticate_user!
def destroy
@post = Post.find(params[:id])
@post.destroy
redirect_to posts_path
end
end
# CORRECT: Checks both authentication and authorization
class PostsController < ApplicationController
before_action :authenticate_user!
def destroy
@post = Post.find(params[:id])
unless @post.user == current_user || current_user.admin?
redirect_to posts_path, alert: "Not authorized"
return
end
@post.destroy
redirect_to posts_path
end
end
Relying on client-side authorization creates security holes. JavaScript that hides UI elements does not prevent unauthorized API calls. Users can manipulate browser state or call APIs directly to bypass client-side restrictions. Applications must enforce authorization on the server for every request.
Storing authentication tokens in localStorage exposes applications to XSS attacks. JavaScript running in the page can access localStorage, allowing attackers to steal tokens through injected scripts. Session cookies with HttpOnly flags prevent JavaScript access, improving security. Applications requiring localStorage for tokens must implement strong XSS protections.
Implementing authentication without proper session management creates vulnerabilities. Applications must implement session expiration, forcing reauthentication after inactivity periods. Sessions should invalidate on logout, preventing reuse of old session identifiers. Password changes should invalidate existing sessions, ensuring stolen credentials become useless after password resets.
Missing authorization checks on API endpoints allow unauthorized access. Developers sometimes secure web UI routes but forget to protect API endpoints with equivalent authorization. APIs must implement the same authorization logic as web interfaces. Each endpoint requires explicit authorization validation.
# INCORRECT: Missing authorization on API endpoint
class Api::PostsController < ApiController
def update
@post = Post.find(params[:id])
if @post.update(post_params)
render json: @post
else
render json: { errors: @post.errors }, status: :unprocessable_entity
end
end
end
# CORRECT: Authorization check before operation
class Api::PostsController < ApiController
def update
@post = Post.find(params[:id])
unless @post.user == current_user || current_user.admin?
return render json: { error: 'Forbidden' }, status: :forbidden
end
if @post.update(post_params)
render json: @post
else
render json: { errors: @post.errors }, status: :unprocessable_entity
end
end
end
Hardcoding role checks throughout the application creates maintenance problems. Authorization logic scattered across controllers becomes difficult to update consistently. Centralizing authorization in policy classes or ability definitions enables consistent enforcement and easier modifications.
Using authentication tokens as authorization tokens conflates identity verification with permission grants. JWT tokens containing user IDs authenticate users but do not inherently authorize actions. Applications must still query user permissions and evaluate them against requested operations. Tokens can include permission data to reduce database queries, but must be validated carefully to prevent tampering.
Failing to validate token expiration enables attackers to use stolen tokens indefinitely. Authentication systems must implement token expiration with reasonable timeouts. Short-lived tokens improve security by limiting exposure windows. Refresh token mechanisms enable extended sessions while maintaining short access token lifetimes.
Implementing authorization without considering resource ownership creates horizontal privilege escalation. Checking user roles without verifying resource ownership allows users to modify other users' data. Authorization logic must verify both role-based permissions and resource-specific ownership or explicit grants.
Design Considerations
Selecting authentication methods balances security requirements against user experience. Password-based authentication provides familiar workflows but depends on users choosing strong passwords. Multi-factor authentication significantly improves security but adds friction to the login process. Biometric authentication offers convenience but requires specialized hardware and raises privacy concerns.
Token-based authentication suits API-driven applications and mobile clients. Tokens enable stateless authentication, eliminating server-side session storage requirements. JWT tokens encode user information and permissions, reducing database queries for each request. However, tokens cannot be revoked before expiration without additional infrastructure like token blacklists or short expiration times with refresh tokens.
OAuth and social login reduce authentication implementation complexity by delegating to established providers. Users benefit from single sign-on across services and avoid creating additional passwords. Applications must trust OAuth providers and handle cases where providers become unavailable or users revoke access. OAuth also introduces dependency on external services for critical authentication functionality.
Authorization model selection depends on application complexity and permission structures. RBAC works well for applications with stable roles and clear organizational hierarchies. Users receive roles that grant collections of permissions. RBAC simplifies permission management when users fit cleanly into defined roles but struggles with fine-grained permissions or dynamic access rules.
ABAC provides flexibility for complex authorization scenarios. Policies evaluate multiple attributes including user properties, resource metadata, and environmental context. ABAC handles dynamic permissions that change based on conditions like time, location, or data sensitivity. However, ABAC policies become complex to author, understand, and debug as rule sets grow.
ACL authorization works well for applications where resources have clear ownership and users need specific permissions on individual resources. File systems and document management systems commonly use ACLs. ACLs allow fine-grained control but become difficult to manage at scale when permission grants multiply across many resources and users.
Implementing authorization at the application layer versus database layer involves trade-offs. Application-layer authorization using frameworks like Pundit or CanCanCan provides flexible, testable permission logic. Applications can implement complex business rules and integrate permissions with application state. However, authorization happens after data retrieval, requiring careful implementation to avoid loading unauthorized data.
Database-layer authorization using row-level security policies enforces permissions at the database level. PostgreSQL row security policies automatically filter query results based on user context. This approach prevents unauthorized data access even when application code contains bugs. Database authorization requires careful policy design and testing to ensure correct behavior across different query patterns.
Distributed systems complicate authentication and authorization. Services must share authentication state or validate tokens independently. Centralized authentication services issue tokens that distributed services validate. This architecture requires secure token distribution and validation across services. Services should validate tokens locally to avoid authentication becoming a bottleneck.
Authorization in distributed systems requires careful consideration of data synchronization. Services need consistent permission information to make correct authorization decisions. Centralized permission services provide consistency but add latency and create single points of failure. Cached permissions improve performance but introduce consistency challenges when permissions change.
Reference
Authentication Methods Comparison
| Method | Security Level | Implementation Complexity | User Experience | Use Cases |
|---|---|---|---|---|
| Password | Medium | Low | Familiar | General web applications |
| Multi-Factor | High | Medium | Additional step | Sensitive applications |
| Token-Based | Medium-High | Medium | Seamless for APIs | APIs and mobile apps |
| OAuth/Social | Medium | Medium | Convenient | Consumer applications |
| Certificate | High | High | Transparent | Enterprise and IoT |
| Biometric | High | High | Convenient | Mobile applications |
Authorization Models Comparison
| Model | Best For | Complexity | Flexibility | Management Overhead |
|---|---|---|---|---|
| RBAC | Stable organizational roles | Low | Medium | Low |
| ABAC | Dynamic complex rules | High | High | Medium |
| ACL | Resource-specific permissions | Medium | Medium | High at scale |
| Policy-Based | Complex business rules | Medium | High | Medium |
Common HTTP Status Codes
| Status Code | Meaning | Usage |
|---|---|---|
| 200 OK | Request successful | Successful authentication or authorized access |
| 401 Unauthorized | Authentication failed | Invalid credentials or missing authentication |
| 403 Forbidden | Authorization failed | Valid authentication but insufficient permissions |
| 404 Not Found | Resource not found | Can hide unauthorized resource existence |
Ruby Authentication Gems
| Gem | Approach | Flexibility | Features |
|---|---|---|---|
| Devise | Full-featured framework | Medium | Password reset, confirmable, lockable |
| Clearance | Lightweight framework | Medium | Simple authentication workflows |
| Authlogic | Explicit authentication | High | Developer controls logic flow |
| Sorcery | Modular approach | High | Pick needed features only |
| JWT | Token-based | High | Stateless API authentication |
Ruby Authorization Gems
| Gem | Approach | Learning Curve | Best For |
|---|---|---|---|
| Pundit | Policy objects | Low | Object-oriented permissions |
| CanCanCan | Ability definitions | Low | Centralized authorization |
| ActionPolicy | Behavior-driven | Medium | Complex policy testing |
| Rolify | Role management | Low | RBAC implementations |
Security Headers for Authentication
| Header | Purpose | Example |
|---|---|---|
| Authorization | Carry authentication tokens | Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 |
| WWW-Authenticate | Indicate authentication required | Bearer realm="api" |
| Set-Cookie | Establish session cookies | session_id=abc123; HttpOnly; Secure |
Session Cookie Flags
| Flag | Purpose | Security Benefit |
|---|---|---|
| HttpOnly | Prevent JavaScript access | Protects against XSS token theft |
| Secure | HTTPS-only transmission | Prevents token interception |
| SameSite | Control cross-site requests | Mitigates CSRF attacks |
| Max-Age | Session expiration | Limits token lifetime exposure |
Common Authorization Checks
| Check Type | Validates | Implementation |
|---|---|---|
| Role check | User has required role | user.role == 'admin' |
| Ownership check | User owns resource | resource.user_id == user.id |
| Permission check | User has specific permission | user.can?(:delete, resource) |
| Scope check | Resource in accessible scope | user.accessible_resources.include?(resource) |