silverstripe-framework/docs/en/02_Developer_Guides/19_GraphQL/04_security_and_best_practices/02_cors.md
Joe Chenevey 9f9ff0151e
Update 02_cors.md
Updating docs page to reflect that CORS allowed-origins require the protocol on the front in order to function correctly.
2021-03-04 17:34:49 -05:00

155 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Cross-Origin Resource Sharing (CORS)
summary: Ensure that requests to your API come from a whitelist of origins
---
# Security & best practices
[CHILDREN asList]
[alert]
You are viewing docs for a pre-release version of silverstripe/graphql (4.x).
Help us improve it by joining #graphql on the [Community Slack](https://www.silverstripe.org/blog/community-slack-channel/),
and report any issues at [github.com/silverstripe/silverstripe-graphql](https://github.com/silverstripe/silverstripe-graphql).
Docs for the current stable version (3.x) can be found
[here](https://github.com/silverstripe/silverstripe-graphql/tree/3)
[/alert]
## Cross-Origin Resource Sharing (CORS)
By default [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) is disabled in the GraphQL Server. This can be easily enabled via YAML:
```yaml
SilverStripe\GraphQL\Controller:
cors:
Enabled: true
```
Once you have enabled CORS you can then control four new headers in the HTTP Response.
1. **Access-Control-Allow-Origin.**
This lets you define which domains are allowed to access your GraphQL API. There are
4 options:
* **Blank**:
Deny all domains (except localhost)
```yaml
Allow-Origin:
```
* **'\*'**:
Allow requests from all domains.
```yaml
Allow-Origin: '*'
```
* **Single Domain**:
Allow requests from one specific external domain.
```yaml
Allow-Origin: 'https://my.domain.com'
```
* **Multiple Domains**:
Allow requests from multiple specified external domains.
```yaml
Allow-Origin:
- 'https://my.domain.com'
- 'https://your.domain.org'
```
2. **Access-Control-Allow-Headers.**
Access-Control-Allow-Headers is part of a CORS 'pre-flight' request to identify
what headers a CORS request may include. By default, the GraphQL server enables the
`Authorization` and `Content-Type` headers. You can add extra allowed headers that
your GraphQL may need by adding them here. For example:
```yaml
Allow-Headers: 'Authorization, Content-Type, Content-Language'
```
[notice]
If you add extra headers to your GraphQL server, you will need to write a
custom resolver function to handle the response.
[/notice]
3. **Access-Control-Allow-Methods.**
This defines the HTTP request methods that the GraphQL server will handle. By
default this is set to `GET, PUT, OPTIONS`. Again, if you need to support extra
methods you will need to write a custom resolver to handle this. For example:
```yaml
Allow-Methods: 'GET, PUT, DELETE, OPTIONS'
```
4. **Access-Control-Max-Age.**
Sets the maximum cache age (in seconds) for the CORS pre-flight response. When
the client makes a successful OPTIONS request, it will cache the response
headers for this specified duration. If the time expires or the required
headers are different for a new CORS request, the client will send a new OPTIONS
pre-flight request to ensure it still has authorisation to make the request.
This is set to 86400 seconds (24 hours) by default but can be changed in YAML as
in this example:
```yaml
Max-Age: 600
```
5. **Access-Control-Allow-Credentials.**
When a request's credentials mode (Request.credentials) is "include", browsers
will only expose the response to frontend JavaScript code if the
Access-Control-Allow-Credentials value is true.
The Access-Control-Allow-Credentials header works in conjunction with the
XMLHttpRequest.withCredentials property or with the credentials option in the
Request() constructor of the Fetch API. For a CORS request with credentials,
in order for browsers to expose the response to frontend JavaScript code, both
the server (using the Access-Control-Allow-Credentials header) and the client
(by setting the credentials mode for the XHR, Fetch, or Ajax request) must
indicate that theyre opting in to including credentials.
This is set to empty by default but can be changed in YAML as in this example:
```yaml
Allow-Credentials: 'true'
```
### Apply a CORS config to all GraphQL endpoints
```yaml
## CORS Config
SilverStripe\GraphQL\Controller:
cors:
Enabled: true
Allow-Origin: 'https://silverstripe.org'
Allow-Headers: 'Authorization, Content-Type'
Allow-Methods: 'GET, POST, OPTIONS'
Allow-Credentials: 'true'
Max-Age: 600 # 600 seconds = 10 minutes.
```
### Apply a CORS config to a single GraphQL endpoint
```yaml
## CORS Config
SilverStripe\Core\Injector\Injector:
SilverStripe\GraphQL\Controller.default
properties:
corsConfig:
Enabled: false
```
### Further reading
[CHILDREN]