diff --git a/content/totp-why-you-need-it-and-how-it-works/index.md b/content/totp-why-you-need-it-and-how-it-works/index.md index b67f4c86..88e0c2df 100644 --- a/content/totp-why-you-need-it-and-how-it-works/index.md +++ b/content/totp-why-you-need-it-and-how-it-works/index.md @@ -49,7 +49,7 @@ TOTP, however, generates codes offline, making it both secure and convenient. Yo - **Mechanism**: Counter increments after each use. - **Use Cases**: Ideal for hardware tokens where clocks are not synchronized. -![HOTP password](./hotp-flow.png) +![HOTP password](./hotp.png) ### TOTP (Time-Based One-Time Password) diff --git a/content/what-is-cross-origin-resource-sharing/cors.png b/content/what-is-cross-origin-resource-sharing/cors.png new file mode 100644 index 00000000..aa7fcb29 Binary files /dev/null and b/content/what-is-cross-origin-resource-sharing/cors.png differ diff --git a/content/what-is-cross-origin-resource-sharing/index.md b/content/what-is-cross-origin-resource-sharing/index.md index 58b0f966..d20a3671 100644 --- a/content/what-is-cross-origin-resource-sharing/index.md +++ b/content/what-is-cross-origin-resource-sharing/index.md @@ -1,166 +1,273 @@ --- title: "What is Cross Origin Resource Sharing (CORS)?" description: "Cross-Origin Resource Sharing (CORS) is a mechanism that supports secure requests and data transfers from outside origins (domain, scheme, or port)." -date: "2022-10-27" +date: "2024-07-06" cover: "cors-cover.png" category: "programming" -author: "Rishabh Poddar" +author: "Mostafa Ibrahim" --- -## Table Of Contents: - - [Introduction](#introduction) - - [CORS History](#cors-history) - - [CORS preflight request](#cors-preflight-request) - - [CORS actual request](#cors-actual-request) - - [Wildcards in CORS](#wildcards-in-cors) - - [CORS vulnerability](#cors-vulnerability) - - [Conclusion](#conclusion) +## Table Of Contents +- [What is Cross Origin Resource Sharing (CORS)?](#what-is-cross-origin-resource-sharing-cors) +- [Why is Cross Origin Resource Sharing Important?](#why-is-cross-origin-resource-sharing-important) +- [How Does Cross Origin Resource Sharing Work?](#how-does-cross-origin-resource-sharing-work) +- [How to Enable CORS?](#how-to-enable-cors) +- [Examples of Access Control Scenarios](#examples-of-access-control-scenarios) +- [Tools and Solutions for Cross Origin Resource Sharing](#tools-and-solutions-for-cross-origin-resource-sharing) +- [Security Best Practices for CORS](#security-best-practices-for-cors) +- [Conclusion](#conclusion) -## Introduction -Cross-Origin Resource Sharing (CORS) is a mechanism that supports secure requests and data transfers from outside origins (domain, scheme, or port). -For example, `example.com` uses a text font that's hosted on `fonts.com`. When visiting `example.com`, the user's browser will make a request for the font from `fonts.com`. Because `fonts.com` and `example.com` are two different origins, this is a cross-origin request. If `fonts.com` allows cross-origin resource sharing to `example.com`, then the browser will proceed with loading the font. Otherwise, the browser will cancel the request. +## What is Cross Origin Resource Sharing (CORS)? -More concretely, CORS is a way for web servers to say "Accept cross-origin requests from this origin" or "Do not accept cross-origin requests from this origin". +![cors](./cors.png) -This is important because cross-origin requests can be quite scary. I could be logged into my bank account and on visiting a malicious site, it could make requests to the bank's servers without my knowledge, and if CORS rules didn't exist, the request would go through - potentially changing or leaking my account information. +Cross Origin Resource Sharing (CORS) is a security mechanism implemented by web browsers that allows web applications to access resources from domains other than the one serving the application. It's a crucial component of modern web development, enabling developers to build more flexible and powerful applications while maintaining security. -CORS is a protocol that defines the limitations of cross-origin requests. These limitations are enforced by our browsers. As a result, we can still make cross-origin requests while still maintaining a high level of security. By specifying which origins are allowed to make requests and which methods and headers are allowed, the browser makes sure that malicious actors can't retrieve sensitive data with cross-origin requests. +To understand CORS better, we first need to grasp the concept of the Same-Origin Policy. This policy is a fundamental security measure implemented by web browsers to prevent malicious scripts from accessing sensitive data on different domains. Under this policy, a web page can only make requests to the same domain (origin) from which it was served. -## CORS History +While the Same-Origin Policy is essential for security, it can be overly restrictive for legitimate use cases. This is where CORS steps in, providing a controlled way to relax these restrictions and allow specific cross-origin requests. -CORS was invented to extend and add flexibility to the Same Origin Policy (SOP). +CORS works by adding new HTTP headers that allow servers to describe which origins are permitted to read that information from a web browser. When a browser receives a response with these headers, it can determine whether to allow or block the response based on the origin of the request. -Same origin policy is essentially what the name suggests - resources can only be loaded from the same origin. Two origins are defined as the same if the protocol, port (if specified), and host are the same. +## Why is Cross Origin Resource Sharing Important? -From a technical perspective, an origin can still request a resource from another origin, but the browser prevents the response from being readable. -However, sometimes, we still need to access resources from other origins - such as from `fonts.com`. That's where CORS comes in. CORS relaxes the Same Origin Policy by defining trusted or allowed origins, methods, and headers. +CORS plays a vital role in modern web development for several reasons: -## CORS preflight request +- **Enabling Resource Sharing**: In today's microservices architecture, different components of an application may be hosted on separate domains. CORS allows these components to communicate seamlessly, enhancing functionality and user experience. +- **API Consumption**: Many web applications rely on third-party APIs to provide features like weather updates, social media integration, or payment processing. CORS enables these applications to access these APIs securely. +- **Security Enhancement**: While CORS relaxes some restrictions of the Same-Origin Policy, it does so in a controlled manner. It allows developers to specify exactly which domains can access their resources, maintaining a high level of security. +- **Improved User Experience**: By allowing resources to be shared across origins, CORS enables developers to create more feature-rich and responsive web applications. +- **Compliance with Modern Web Standards**: As web applications become more complex and distributed, CORS has become an essential part of web standards, ensuring interoperability and security across the web. -So now, let's get into the actual motion of what happens when requesting resources from another domain. +## How Does Cross Origin Resource Sharing Work? +CORS operates through a series of HTTP headers that are exchanged between the browser and the server. Let's break down the key components: -We've set up an example website at [emailpassword.demo.supertokens.com](https://emailpassword.demo.supertokens.com) where we can see the full CORS motion. This website calls an API on `https://api-emailpassword.demo.supertokens.com`. Even though both domains are subdomains of `demo.supertokens.com`, our browsers register them as different origins, and thus, CORS comes into the picture. +### a) HTTP Headers: +- `Access-Control-Allow-Origin`: Specifies which origins are allowed to access the resource. +- `Access-Control-Allow-Methods`: Indicates which HTTP methods are allowed when accessing the resource. +- `Access-Control-Allow-Headers`: Specifies which HTTP headers can be used during the actual request. +- `Access-Control-Allow-Credentials`: Indicates whether the response can be shared when the credentials flag is true. -During sign in, if you open the browser's dev tools and see the network tab, you will see the preflight request being made. More specifically, the preflight request is an `OPTIONS` request made to our API domain with a couple of headers. Let's take a look at what happens when we click sign in - +### b) Types of CORS Requests: +- **Simple Requests**: These don't trigger a preflight check. They must use methods like GET, HEAD, or POST, and can only use certain headers and content types. +- **Preflight Requests**: For requests that may have side effects on user data, the browser first sends an HTTP OPTIONS request to determine whether the actual request is safe to send. +- **Actual Requests**: These are the requests that carry the actual data payload after the preflight check (if required) has been completed successfully. -``` -OPTIONS /auth/signin HTTP/1.1 -Host: api-emailpassword.demo.supertokens.com -Access-Control-Request-Method: POST -Access-Control-Request-Headers: content-type,fdi-version,rid -Origin: https://emailpassword.demo.supertokens.com +### c) Browser Handling: +When a web application makes a cross-origin request, the browser automatically adds the Origin header to the request. The server then responds with the appropriate CORS headers. If the Origin is allowed, the browser proceeds with the request; otherwise, it blocks it. + +### d) Error Handling: +Common CORS errors include: +- "No 'Access-Control-Allow-Origin' header is present on the requested resource". +- "The 'Access-Control-Allow-Origin' header has a value that is not equal to the supplied origin". + +These errors indicate that the server is not configured to allow requests from the origin of your web application. + +## How to Enable CORS? +Enabling CORS involves configuring both the server and, in some cases, the client-side application. Let's explore how to set up CORS in various environments: + +### Enabling CORS in Different Web Servers + +#### a) Apache: +To enable CORS in Apache, you need to edit the `.htaccess` file or the server configuration file. Here's an example configuration: + +```apache +Header set Access-Control-Allow-Origin "*" +Header set Access-Control-Allow-Methods "GET,POST,OPTIONS,DELETE,PUT" +Header set Access-Control-Allow-Headers "Content-Type, Authorization" ``` -So that's our pre-flight request. Breaking this down, we have four key things to look at. +#### b) Nginx: + +For Nginx, you'll need to modify the nginx.conf file: + +```nginx +location / { + if ($request_method = 'OPTIONS') { + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; + add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Content-Type' 'text/plain; charset=utf-8'; + add_header 'Content-Length' 0; + return 204; + } + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; + add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; +} + +``` -- `Host` - The "host" of the resource that we're requesting. For us, that's `api-emailpassword.demo.supertokens.com` -- `Access-Control-Request-Method` - The method of the request being made by our operation. This can be any of the HTTP request methods, including `GET`, `POST`, `PUT`, `DELETE`, and `CONNECT`. -- `Access-Control-Request-Headers` - A comma-separated list of [HTTP headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) that would be used in the actual request. -- `Origin` - Where the request is coming from. For us, that's `https://emailpassword.demo.supertokens.com` +#### c) Microsoft IIS: -After getting this pre-flight / `OPTIONS` request, the API server sends over a pre-flight response. Here's our response from `api-emailpassword.demo.supertokens.com`. +For IIS, you can configure CORS using the IIS Manager or by modifying the web.config: +```xml + + + + + + + + + ``` -HTTP/1.1 204 No Content -Access-Control-Allow-Origin: https://emailpassword.demo.supertokens.com/ -Access-Control-Allow-Credentials: true -Access-Control-Allow-Methods: GET,PUT,POST,DELETE -Access-Control-Allow-Headers: content-type,rid,fdi-version,anti-csrf + +### Configuring CORS in Backend Frameworks + +#### a) Node.js (Express) + +In Express, you can use the `cors` middleware: + +```js +const express = require('express'); +const cors = require('cors'); +const app = express(); + +app.use(cors()); ``` -Let's break this response down. +#### b) Django: +For Django, you can use the django-cors-headers package: + +```python +INSTALLED_APPS = [ + ... + 'corsheaders', + ... +] -- `Access-Control-Allow-Origin` - The origins that the API server has whitelisted. Notice that the value of this is the same as our website domain. This tells the browser that the server expects requests from this client. -- `Access-Control-Allow-Credentials` - The server telling us whether the actual request can include cookies in it, or that the response of the actual request can set-cookies. In our case, cookies refer to the session tokens of the user, which act as the credentials of the user once they're signed in. -- `Access-Control-Allow-Methods` - A comma-separated list of HTTP methods that the API domain allows for cross-origin requests -- `Access-Control-Allow-Headers` - A comma-separated list of HTTP headers that the API domain allows for cross-origin requests +MIDDLEWARE = [ + ... + 'corsheaders.middleware.CorsMiddleware', + 'django.middleware.common.CommonMiddleware', + ... +] + +CORS_ALLOW_ALL_ORIGINS = True # Or specify allowed origins +``` -The browser then takes this response from the API server to determine if the actual request should be sent. If the response from the API doesn't include the requested origin, methods, or headers from the preflight request, then the browser will not send the actual request. +#### c) Flask -## CORS actual request +In Flask, you can use the flask-cors extension -If the response from the API includes the requested origin, it's time to send the actual `POST` request to sign in. +```python +from flask import Flask +from flask_cors import CORS +app = Flask(__name__) +CORS(app) ``` -POST /auth/signin HTTP/1.1 -Host: http://api-emailpassword.demo.supertokens.com/ -content-type: application/json -fdi-version: 1.15 -rid: emailpassword -Content-Length: 92 -Origin: https://emailpassword.demo.supertokens.com/ + +## Implementing CORS in Frontend Frameworks + +### a) React + +In React, you can handle CORS using `fetch` or `axios`. For `create-react-app` projects, you can also set up a proxy in the `package.json` file: + +```json +{ + "proxy": "http://localhost:5000" +} ``` -Note that the origin and the headers that are sent (`fdi-version`, `rid`, `content-type`), are whitelisted by the server, and the browser knows this because of the pre-flight response. +### b) Angular + +In Angular services, you can configure CORS when making HTTP requests: -Now let's take a look at the response from the server. +```typescript +import { HttpClient, HttpHeaders } from '@angular/common/http'; +constructor(private http: HttpClient) {} + +getData() { + const headers = new HttpHeaders().set('Content-Type', 'application/json'); + return this.http.get('http://api.example.com/data', { headers: headers }); +} ``` -HTTP/1.1 200 OK -Access-Control-Allow-Origin: https://emailpassword.demo.supertokens.com/ -Access-Control-Allow-Credentials: true -front-token: ... -Access-Control-Expose-Headers: front-token, id-refresh-token -Set-Cookie: ... + +### c) Vue.js: + +In Vue.js, you can handle CORS in your API calls or use plugins like `axios`: + +```js +import axios from 'axios'; + +axios.get('http://api.example.com/data', { + headers: { + 'Content-Type': 'application/json' + } +}) +.then(response => console.log(response)) +.catch(error => console.error(error)); ``` -Here, we get the response from the server with cookies and tokens that allows us to proceed with the sign-in operation. One thing to note is that compared to our pre-flight, we now also have an additional `Access-Control-Expose-Headers` header. +## Examples of Access Control Scenarios -- `Access-Control-Expose-Headers` - The server indicating which response headers are available for the scripts running in the browser. Interestingly, the reason this exists is not because of security, but because of backward compatibility to when CORS did not exist. +Let's look at two common scenarios for implementing CORS: -With this, we've now completed our first pre-flight request/response as well as our actual request/response for signing in! +### Scenario 1: Public API Access -## Wildcards in CORS +Imagine you're building a weather application that needs to access a public weather API. In this case, you want to allow access from any origin: -One common mistake in configuring CORS is around the use of wildcards. Often, developers will elect to use the wildcard, `*`, when defining the origins, methods, or headers allowed with CORS. +```http +Access-Control-Allow-Origin: * +``` -While wildcards will work for simple requests (requests without [HTTP cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) or HTTP authentication information), requests with credentials will often encounter a CORS not authorized error. +This configuration allows any domain to access your API, which is suitable for public APIs -That's because in requests with credentials (cookies), the wildcard is treated as the literal method name or origin name `"*"` without special semantics. This occurs both in `Access-Control-Allow-Origin` and `Access-Control-Allow-Methods`, and some browsers like Safari simply don't have support for wildcards at all. +### Scenario 2: Restricted API Access -All in all, it's good hygiene to avoid the wildcard and use a comma-separated list when configuring CORS. +Now, let's say you're developing an internal application and want to restrict API access to specific domains: -## CORS vulnerability +```http +Access-Control-Allow-Origin: https://app1.yourdomain.com, https://app2.yourdomain.com +``` -When configured improperly, CORS can lead to major vulnerabilities. Below, we'll list a couple of common issues when configuring CORS. +This configuration ensures that only the specified domains can access your API, providing an additional layer of security. -### Mishandling origin whitelist +## Tools and Solutions for Cross Origin Resource Sharing -One of the easiest mistakes to make when implementing CORS is mishandling the origin whitelist. When whitelisting origins, it's often easy to do simple matches with URL prefixes or suffixes, or using regular expressions. However, this can lead to quite a few issues. +To help you work with CORS effectively, consider using these tools: -Let's say that we grant access to all websites with the suffix `whitelisted-website.com`. This makes it easy for us to grant access to `api.whitelisted-website.com`. +### a) Browser Extensions -But an attacker could use a website such as `maliciouswhitelisted-website.com` and gain access. +- **CORS Everywhere (Firefox)**: Allows you to toggle CORS restrictions on and off for testing purposes. +- **Allow CORS: Access-Control-Allow-Origin (Chrome)**: Adds CORS headers to responses for testing. -The best approach here to avoid potential abuse is to explicitly define origins on the whitelist for sensitive operations when implementing CORS - for example, specify the strings `"https://whitelisted-website.com"` and `"https://api.whitelisted-website.com"` which will grant access to only these domains. +### b) API Testing Tools -### Requests with null origin +- **Postman**: Allows you to send requests with custom headers, useful for testing CORS configurations. +- **cURL**: A command-line tool for making HTTP requests, helpful for debugging CORS issues. -Another common misconfiguration is whitelisting origins with the value `null`. Browsers might send the value `null` in the origin header in situations such as: +### c) CORS Proxies -- Request with file -- Sandboxed cross-origin requests +- **CORS Anywhere**: A NodeJS proxy which adds CORS headers to the proxied request. -In this case, an attacker can use various tricks to generate a request containing the value `null` as the origin which is whitelisted in our configurations. For example, the attacker could use the following sandboxed iframe exploit - +Remember, while these tools are useful for development and testing, they should not be used to bypass CORS in production environments, as this could introduce security vulnerabilities. -```html - -``` +## Security Best Practices for CORS + +When implementing CORS, keep these security best practices in mind: + +- Avoid using '*' for Access-Control-Allow-Origin in production environments. Instead, specify the exact origins that should have access. +- Use the Access-Control-Allow-Credentials header cautiously. Only set it to 'true' if you absolutely need to send cookies or HTTP authentication. +- Implement proper authentication and authorization alongside CORS. CORS is not a substitute for server-side security measures. +- Regularly audit your CORS configuration to ensure it aligns with your security requirements. +- Use HTTPS for all cross-origin requests to prevent man-in-the-middle attacks. +- Be cautious when allowing all HTTP methods. Only allow the methods that your API actually needs. ## Conclusion -We hope this article helps you understand the basic tenets behind CORS as well as some common pitfalls when implementing CORS.  +Cross Origin Resource Sharing (CORS) is a crucial mechanism in modern web development, enabling secure communication between different domains while maintaining essential security measures. By understanding how CORS works and implementing it correctly, you can create more powerful, flexible, and secure web applications. + +As you've seen, configuring CORS involves both server-side and client-side considerations. Whether you're working with Apache, Nginx, or IIS on the server side, or React, Angular, or Vue.js on the client side, there are straightforward ways to implement CORS in your stack. + +Remember, while CORS is powerful, it's just one piece of the web security puzzle. It should be used in conjunction with other security measures like proper authentication, authorization, and data validation. For a deeper dive into related topics, check out our articles on [Cross-Site Request Forgery (CSRF)](https://supertokens.com/blog/what-is-cross-site-request-forgery/), [JWT authentication](https://supertokens.com/blog/what-is-jwt), and [user session security](https://supertokens.com/blog/all-you-need-to-know-about-user-session-security). -SuperTokens is building open-source user authentication. We help companies manage authentication nuances, including handling CORS when calling an authentication server. If you encounter CORS related issues when implementing SuperTokens, [head over to our docs](https://supertokens.com/docs/thirdpartyemailpassword/troubleshooting/cors-issues) to debug common issues or ask us directly on our Discord! \ No newline at end of file +Are you looking to implement robust authentication in your web applications? Consider using [SuperTokens](https://supertokens.com), an open-source authentication solution that makes it easy to add secure login functionality to your apps. Whether you need [social login, email/password authentication](https://supertokens.com/blog/how-to-set-up-social-and-email-password-login-with-reactjs), or more advanced features, SuperTokens has you covered. [Get started with SuperTokens](https://supertokens.com/) today and take your web application security to the next level! \ No newline at end of file