Bird
Raised Fist0
Ruby on Railsframework~15 mins

CORS configuration in Ruby on Rails - Deep Dive

Choose your learning style10 modes available
Overview - CORS configuration
What is it?
CORS configuration is how a Rails application controls which other websites can ask it for data. It stands for Cross-Origin Resource Sharing, a security feature in browsers that stops unwanted websites from reading your app's data. By setting CORS rules, you tell browsers which external sites are allowed to talk to your Rails backend. This keeps your app safe while letting trusted sites access your resources.
Why it matters
Without CORS configuration, browsers block requests from other websites, breaking features like APIs or frontend apps hosted separately. If you don't set it up, your users might see errors or missing data when your app tries to share information across sites. Proper CORS setup ensures smooth, secure communication between your Rails backend and other web apps, improving user experience and protecting data.
Where it fits
Before learning CORS configuration, you should understand HTTP basics and how web browsers enforce security. Knowing Rails middleware and how requests flow through your app helps too. After mastering CORS, you can explore API authentication, security headers, and advanced Rails security practices.
Mental Model
Core Idea
CORS configuration is a gatekeeper that tells browsers which external websites can safely access your Rails app's data.
Think of it like...
Imagine your Rails app is a private clubhouse. CORS configuration is the guest list that the doorman checks before letting visitors in. Only guests on the list can enter and interact; others are politely turned away.
┌───────────────┐       ┌───────────────┐       ┌───────────────┐
│ External Site │──────▶│ Browser (Gate)│──────▶│ Rails Backend │
└───────────────┘       └───────────────┘       └───────────────┘
         │                      │                      │
         │  Sends request       │ Checks CORS rules    │ Processes request
         │                      │                      │
         ▼                      ▼                      ▼
   Allowed? ───────────────▶ Yes ───────────────▶ Response
         │
         └──────────────▶ No ───────────────▶ Blocked by browser
Build-Up - 7 Steps
1
FoundationWhat is CORS and Why It Exists
🤔
Concept: Introduce the basic idea of CORS as a browser security feature that controls cross-site requests.
Browsers prevent web pages from making requests to a different domain than the one that served the page. This is called the Same-Origin Policy. CORS is a way for servers to say, "It's okay for these other sites to ask me for data." Without CORS, your Rails app would only respond to requests from its own domain.
Result
You understand that CORS is a browser rule that your Rails app can configure to allow or block requests from other websites.
Understanding CORS as a browser-enforced security rule explains why your Rails app needs explicit configuration to share data safely.
2
FoundationHow Rails Handles CORS Requests
🤔
Concept: Explain that Rails uses middleware to process CORS headers before reaching your app logic.
Rails apps use middleware like 'rack-cors' to add CORS headers to responses. When a browser sends a request from another site, the middleware checks if the request's origin is allowed. If yes, it adds headers that tell the browser to accept the response. If not, the browser blocks the response.
Result
You see that CORS is handled early in the request cycle, controlling access before your Rails code runs.
Knowing that middleware manages CORS helps you understand where and how to configure it in Rails.
3
IntermediateConfiguring rack-cors in Rails
🤔Before reading on: Do you think CORS settings go in controller code or middleware configuration? Commit to your answer.
Concept: Learn how to install and configure the rack-cors gem to set CORS rules in Rails.
Add 'rack-cors' to your Gemfile and run bundle install. Then, in config/application.rb or config/initializers/cors.rb, add a configuration block specifying allowed origins, resources, and HTTP methods. For example: Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins 'https://trustedsite.com' resource '*', headers: :any, methods: [:get, :post, :options] end end
Result
Your Rails app now sends CORS headers allowing requests from 'https://trustedsite.com' with specified methods.
Configuring CORS in middleware centralizes access control, keeping your app secure and maintainable.
4
IntermediateUnderstanding Preflight Requests
🤔Before reading on: Do you think all cross-origin requests trigger a preflight OPTIONS request? Commit to yes or no.
Concept: Explain the browser's preflight OPTIONS request that checks permissions before sending actual data requests.
For some requests (like POST with JSON), browsers first send an OPTIONS request to ask the server if the real request is allowed. Your Rails app must respond to OPTIONS with correct CORS headers. rack-cors handles this automatically if configured properly.
Result
You understand why your Rails app sometimes receives OPTIONS requests and how CORS configuration handles them.
Knowing about preflight requests prevents confusion when debugging cross-origin request failures.
5
IntermediateAllowing Multiple Origins and Dynamic Origins
🤔Before reading on: Can rack-cors accept a list of origins or a dynamic function? Commit to your answer.
Concept: Learn how to allow multiple or dynamic origins in CORS configuration for flexible access control.
You can specify multiple origins by listing them in the origins method, like origins 'https://site1.com', 'https://site2.com'. For dynamic control, you can pass a lambda that checks the origin string and returns true or false. This lets you allow or deny origins based on custom logic.
Result
Your Rails app can flexibly allow requests from many or conditionally approved sites.
Dynamic origin control lets you balance security and usability in complex environments.
6
AdvancedSecuring CORS to Prevent Data Leaks
🤔Before reading on: Is it safe to set origins to '*' in production? Commit to yes or no.
Concept: Understand the security risks of overly permissive CORS settings and how to tighten them.
Setting origins to '*' allows any site to access your API, which can expose sensitive data or enable attacks. Instead, specify exact trusted domains. Also, limit allowed HTTP methods and headers. Use credentials: false unless you need cookies or authentication headers shared cross-origin, which requires extra care.
Result
You know how to configure CORS securely to protect your Rails app and users.
Recognizing CORS risks helps prevent serious security vulnerabilities in production.
7
ExpertCORS and Rails API Mode Internals
🤔Before reading on: Does Rails API mode change how CORS middleware works? Commit to yes or no.
Concept: Explore how Rails API mode affects middleware stack and CORS behavior internally.
Rails API mode uses a slimmer middleware stack for performance. rack-cors must be explicitly added because default middleware like session or cookies are removed. This means CORS configuration is critical to enable cross-origin requests in API-only apps. Also, understand how middleware order affects header setting and request handling.
Result
You grasp how Rails API mode changes CORS setup and why middleware order matters.
Knowing Rails internals prevents subtle bugs and ensures reliable CORS behavior in API apps.
Under the Hood
When a browser makes a cross-origin request, it sends the Origin header with the request. The Rails app's rack-cors middleware intercepts this request early, checks if the Origin matches allowed origins, and if so, adds Access-Control-Allow-Origin and other CORS headers to the response. For preflight OPTIONS requests, rack-cors responds with allowed methods and headers without invoking the main app logic. The browser reads these headers to decide if it should allow the frontend JavaScript to access the response data.
Why designed this way?
Browsers enforce the Same-Origin Policy to protect users from malicious sites stealing data. CORS was designed as a controlled relaxation of this policy, letting servers explicitly declare trusted origins. rack-cors middleware fits into Rails as a modular, configurable layer to handle these headers cleanly without cluttering app code. This separation keeps security concerns centralized and easier to maintain.
┌───────────────┐
│ Browser sends │
│ request with  │
│ Origin header │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ rack-cors     │
│ middleware    │
│ checks Origin │
│ against rules │
└──────┬────────┘
       │
       │ Allowed?
       │ Yes
       ▼
┌───────────────┐
│ Add CORS      │
│ headers to    │
│ response      │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ Rails app     │
│ processes     │
│ request       │
└───────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does setting origins to '*' always allow all cross-origin requests including credentials? Commit to yes or no.
Common Belief:Setting origins to '*' means any website can access your API with credentials like cookies.
Tap to reveal reality
Reality:Browsers block credentialed requests if Access-Control-Allow-Origin is '*'. You must specify exact origins to allow credentials.
Why it matters:Misconfiguring this leads to failed authenticated requests and broken user sessions.
Quick: Do you think CORS is a server-side security feature? Commit to yes or no.
Common Belief:CORS protects the server from unauthorized access by blocking bad requests.
Tap to reveal reality
Reality:CORS is enforced by browsers on the client side; servers respond with headers but do not block requests themselves.
Why it matters:Assuming CORS is server-side security can cause developers to neglect proper backend authentication and authorization.
Quick: Do you think all cross-origin requests trigger a preflight OPTIONS request? Commit to yes or no.
Common Belief:Every cross-origin request sends a preflight OPTIONS request first.
Tap to reveal reality
Reality:Only requests with certain methods or headers trigger preflight; simple GET requests usually do not.
Why it matters:Misunderstanding this can lead to confusion when debugging CORS issues and unnecessary server handling.
Quick: Can rack-cors configuration be placed anywhere in Rails code with the same effect? Commit to yes or no.
Common Belief:You can configure rack-cors anywhere in Rails and it will work the same.
Tap to reveal reality
Reality:rack-cors must be inserted early in the middleware stack to handle requests before other middleware.
Why it matters:Placing CORS config too late causes headers not to be set, breaking cross-origin requests.
Expert Zone
1
Middleware order is critical: rack-cors must be inserted before other middleware that might consume the request or modify headers.
2
Dynamic origin lambdas can introduce performance overhead and complexity; caching allowed origins can improve efficiency.
3
In API-only Rails apps, missing rack-cors setup is a common silent failure causing CORS errors that are hard to diagnose.
When NOT to use
Avoid using overly permissive CORS settings like origins '*' in production. Instead, use strict origin lists or token-based authentication. For internal microservices, consider private networks or VPNs instead of CORS. If you need fine-grained access control, combine CORS with OAuth or API keys.
Production Patterns
In production, teams often configure CORS per environment, allowing localhost and staging domains during development but restricting to exact domains in production. They also monitor CORS errors via logging and browser reports. Some use environment variables to manage allowed origins dynamically without code changes.
Connections
HTTP Headers
CORS relies on specific HTTP headers to communicate permissions between server and browser.
Understanding HTTP headers like Origin and Access-Control-Allow-Origin clarifies how CORS controls cross-site requests.
Web Security Policies
CORS is part of a broader set of browser security policies including Content Security Policy and Same-Origin Policy.
Knowing CORS in context helps grasp how browsers protect users and how developers can safely share resources.
Access Control in Operating Systems
Both CORS and OS access control manage who can access resources, using rules and permissions.
Seeing CORS as a form of access control helps understand its role in protecting resources from unauthorized access.
Common Pitfalls
#1Allowing all origins with '*' in production including credentialed requests.
Wrong approach:Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins '*' resource '*', headers: :any, methods: [:get, :post], credentials: true end end
Correct approach:Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins 'https://trustedsite.com' resource '*', headers: :any, methods: [:get, :post], credentials: true end end
Root cause:Misunderstanding that '*' cannot be used with credentials in CORS, leading to broken authenticated requests.
#2Configuring rack-cors too late in middleware stack causing headers not to be set.
Wrong approach:Rails.application.config.middleware.use Rack::Cors do allow do origins 'https://example.com' resource '*', headers: :any, methods: [:get] end end
Correct approach:Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins 'https://example.com' resource '*', headers: :any, methods: [:get] end end
Root cause:Using 'use' instead of 'insert_before 0' places middleware too late, so CORS headers are not added in time.
#3Ignoring preflight OPTIONS requests causing 404 errors.
Wrong approach:Not handling OPTIONS requests in routes or middleware, leading to errors when browser sends preflight.
Correct approach:rack-cors middleware automatically handles OPTIONS requests if configured properly, no extra routes needed.
Root cause:Not understanding that browsers send OPTIONS preflight requests and that middleware must respond correctly.
Key Takeaways
CORS configuration in Rails controls which external websites can access your app's data through browser-enforced rules.
rack-cors middleware is the standard way to set CORS policies in Rails, and it must be configured early in the middleware stack.
Preflight OPTIONS requests are a key part of CORS and must be handled correctly to allow complex cross-origin requests.
Security is critical: avoid using wildcard origins with credentials and always specify trusted domains in production.
Understanding CORS deeply helps prevent common bugs and security issues when building APIs and frontend-backend integrations.

Practice

(1/5)
1. What is the main purpose of configuring CORS in a Rails application?
easy
A. To speed up database queries
B. To control which external websites can access your app's resources
C. To manage user sessions securely
D. To style the frontend pages

Solution

  1. Step 1: Understand CORS role

    CORS (Cross-Origin Resource Sharing) controls access from other websites to your app's resources.
  2. Step 2: Identify main purpose

    It restricts or allows external origins to make requests, enhancing security.
  3. Final Answer:

    To control which external websites can access your app's resources -> Option B
  4. Quick Check:

    CORS controls access = B [OK]
Hint: Remember CORS is about cross-site access control [OK]
Common Mistakes:
  • Confusing CORS with database or session management
  • Thinking CORS affects frontend styling
  • Assuming CORS speeds up app performance
2. Which of the following is the correct way to add CORS middleware in a Rails app initializer?
easy
A. Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins '*' resource '*', headers: :any, methods: [:get, :post] end end
B. Rails.middleware.use Rack::Cors do allow do origins '*' resource '*', headers: :any, methods: [:get, :post] end end
C. config.middleware.add Rack::Cors do allow do origins '*' resource '*', headers: :any, methods: [:get, :post] end end
D. Rails.application.middleware.insert_after 0, Rack::Cors do allow do origins '*' resource '*', headers: :any, methods: [:get, :post] end end

Solution

  1. Step 1: Recall correct middleware insertion

    In Rails, middleware is added using Rails.application.config.middleware.insert_before or insert_after.
  2. Step 2: Identify correct syntax

    The common pattern is insert_before 0, Rack::Cors with a block for configuration.
  3. Final Answer:

    Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins '*' resource '*', headers: :any, methods: [:get, :post] end end -> Option A
  4. Quick Check:

    Use insert_before 0 with config.middleware = C [OK]
Hint: Use Rails.application.config.middleware.insert_before 0 for CORS [OK]
Common Mistakes:
  • Using Rails.middleware instead of Rails.application.config.middleware
  • Using insert_after instead of insert_before 0
  • Missing config in middleware insertion
3. Given this CORS config in Rails initializer:
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'https://example.com'
    resource '*', headers: :any, methods: [:get, :post]
  end
end
What happens if a request comes from 'https://evil.com'?
medium
A. The request is blocked due to origin mismatch
B. The request causes a server error
C. The request is allowed but only GET method works
D. The request is allowed with all headers and methods

Solution

  1. Step 1: Analyze allowed origins

    The config allows only 'https://example.com' origin.
  2. Step 2: Check request origin

    Request from 'https://evil.com' is not in allowed origins, so it is blocked by CORS policy.
  3. Final Answer:

    The request is blocked due to origin mismatch -> Option A
  4. Quick Check:

    Origin not allowed = request blocked = D [OK]
Hint: Only origins listed in config are allowed [OK]
Common Mistakes:
  • Assuming wildcard '*' allows all origins when specific origins set
  • Thinking request causes server error instead of CORS block
  • Confusing allowed methods with allowed origins
4. You wrote this CORS config:
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins '*'
    resource '*', headers: :any, methods: [:get, :post, :put]
  end
end
But PUT requests from frontend are failing with CORS errors. What is the likely problem?
medium
A. The methods list is missing :put
B. The frontend is not sending the correct Origin header
C. The server needs to allow OPTIONS method for preflight
D. The origins '*' is too restrictive

Solution

  1. Step 1: Check methods allowed

    PUT is included in methods, so it's not missing.
  2. Step 2: Understand CORS preflight

    PUT requests trigger a preflight OPTIONS request which must be allowed by server.
  3. Step 3: Identify missing OPTIONS method

    OPTIONS method is not listed, so preflight fails causing CORS error.
  4. Final Answer:

    The server needs to allow OPTIONS method for preflight -> Option C
  5. Quick Check:

    Preflight OPTIONS missing = CORS fail = A [OK]
Hint: Always allow OPTIONS method for CORS preflight [OK]
Common Mistakes:
  • Forgetting to allow OPTIONS method
  • Assuming '*' origin is restrictive
  • Blaming frontend Origin header without checking server
5. You want to allow CORS only for two trusted domains: 'https://app1.com' and 'https://app2.com'. Which config correctly implements this securely in Rails?
hard
A. Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins 'app1.com' resource '*', headers: :any, methods: [:get, :post, :options] end allow do origins 'app2.com' resource '*', headers: :any, methods: [:get, :post, :options] end end
B. Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins '*' resource '*', headers: :any, methods: :any end end
C. Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins 'app1.com', 'app2.com' resource '*', headers: :any, methods: [:get, :post] end end
D. Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins 'https://app1.com', 'https://app2.com' resource '*', headers: :any, methods: [:get, :post, :options] end end

Solution

  1. Step 1: Identify correct origins format

    Origins must include full URLs with protocol for security, so 'https://app1.com' and 'https://app2.com' are correct.
  2. Step 2: Check methods and resource

    Allowing common methods including OPTIONS for preflight is necessary.
  3. Step 3: Compare options

    Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins 'https://app1.com', 'https://app2.com' resource '*', headers: :any, methods: [:get, :post, :options] end end correctly lists both origins in one allow block with proper methods and full URLs.
  4. Final Answer:

    Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins 'https://app1.com', 'https://app2.com' resource '*', headers: :any, methods: [:get, :post, :options] end end -> Option D
  5. Quick Check:

    Trusted full origins with methods including OPTIONS = A [OK]
Hint: List full trusted origins with needed methods including OPTIONS [OK]
Common Mistakes:
  • Using '*' origin which is insecure
  • Omitting protocol in origins
  • Not allowing OPTIONS method for preflight
  • Splitting origins into multiple allow blocks unnecessarily
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard