Skip to content

Commit 50635d9

Browse files
#28561: GraphQL added CORS headers
1 parent b3d318d commit 50635d9

File tree

11 files changed

+374
-0
lines changed

11 files changed

+374
-0
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
namespace Magento\GraphQl\Controller\HttpResponse\Cors;
4+
5+
use Magento\Framework\App\Response\HeaderProvider\HeaderProviderInterface;
6+
use Magento\GraphQl\Model\Cors\ConfigurationInterface;
7+
8+
class CorsAllowCredentialsHeaderProvider implements HeaderProviderInterface
9+
{
10+
protected $headerName = 'Access-Control-Allow-Credentials';
11+
12+
/**
13+
* CORS configuration provider
14+
*
15+
* @var \Magento\GraphQl\Model\Cors\ConfigurationInterface
16+
*/
17+
private $corsConfiguration;
18+
19+
public function __construct(ConfigurationInterface $corsConfiguration)
20+
{
21+
$this->corsConfiguration = $corsConfiguration;
22+
}
23+
24+
public function getName()
25+
{
26+
return $this->headerName;
27+
}
28+
29+
public function getValue()
30+
{
31+
return true;
32+
}
33+
34+
public function canApply() : bool
35+
{
36+
return $this->corsConfiguration->isEnabled() && $this->corsConfiguration->isCredentialsAllowed();
37+
}
38+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
4+
namespace Magento\GraphQl\Controller\HttpResponse\Cors;
5+
6+
use Magento\Framework\App\Response\HeaderProvider\HeaderProviderInterface;
7+
use Magento\GraphQl\Model\Cors\ConfigurationInterface;
8+
9+
class CorsAllowHeadersHeaderProvider implements HeaderProviderInterface
10+
{
11+
protected $headerName = 'Access-Control-Allow-Headers';
12+
13+
protected $headerValue = '';
14+
15+
/**
16+
* CORS configuration provider
17+
*
18+
* @var \Magento\GraphQl\Model\Cors\ConfigurationInterface
19+
*/
20+
private $corsConfiguration;
21+
22+
public function __construct(ConfigurationInterface $corsConfiguration)
23+
{
24+
$this->corsConfiguration = $corsConfiguration;
25+
}
26+
27+
public function getName()
28+
{
29+
return $this->headerName;
30+
}
31+
32+
public function canApply() : bool
33+
{
34+
return $this->corsConfiguration->isEnabled() && $this->getValue();
35+
}
36+
37+
public function getValue()
38+
{
39+
return $this->corsConfiguration->getAllowedHeaders()
40+
? $this->corsConfiguration->getAllowedHeaders()
41+
: $this->headerValue;
42+
}
43+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
4+
namespace Magento\GraphQl\Controller\HttpResponse\Cors;
5+
6+
7+
use Magento\Framework\App\Response\HeaderProvider\HeaderProviderInterface;
8+
use Magento\GraphQl\Model\Cors\ConfigurationInterface;
9+
10+
class CorsAllowMethodsHeaderProvider implements HeaderProviderInterface
11+
{
12+
protected $headerName = 'Access-Control-Allow-Methods';
13+
14+
protected $headerValue = 'GET,POST,OPTIONS';
15+
16+
/**
17+
* CORS configuration provider
18+
*
19+
* @var \Magento\GraphQl\Model\Cors\ConfigurationInterface
20+
*/
21+
private $corsConfiguration;
22+
23+
public function __construct(ConfigurationInterface $corsConfiguration)
24+
{
25+
$this->corsConfiguration = $corsConfiguration;
26+
}
27+
28+
public function getName()
29+
{
30+
return $this->headerName;
31+
}
32+
33+
public function canApply() : bool
34+
{
35+
return $this->corsConfiguration->isEnabled() && $this->getValue();
36+
}
37+
38+
public function getValue()
39+
{
40+
return $this->corsConfiguration->getAllowedMethods()
41+
? $this->corsConfiguration->getAllowedMethods()
42+
: $this->headerValue;
43+
}
44+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
4+
namespace Magento\GraphQl\Controller\HttpResponse\Cors;
5+
6+
use Magento\Framework\App\Response\HeaderProvider\HeaderProviderInterface;
7+
use Magento\GraphQl\Model\Cors\ConfigurationInterface;
8+
9+
class CorsAllowOriginHeaderProvider implements HeaderProviderInterface
10+
{
11+
protected $headerName = 'Access-Control-Allow-Origin';
12+
13+
/**
14+
* CORS configuration provider
15+
*
16+
* @var \Magento\GraphQl\Model\Cors\ConfigurationInterface
17+
*/
18+
private $corsConfiguration;
19+
20+
public function __construct(ConfigurationInterface $corsConfiguration)
21+
{
22+
$this->corsConfiguration = $corsConfiguration;
23+
}
24+
25+
public function getName()
26+
{
27+
return $this->headerName;
28+
}
29+
30+
public function canApply() : bool
31+
{
32+
return $this->corsConfiguration->isEnabled() && $this->getValue();
33+
}
34+
35+
public function getValue()
36+
{
37+
return $this->corsConfiguration->getAllowedOrigins();
38+
}
39+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
4+
namespace Magento\GraphQl\Controller\HttpResponse\Cors;
5+
6+
7+
use Magento\Framework\App\Response\HeaderProvider\HeaderProviderInterface;
8+
use Magento\GraphQl\Model\Cors\ConfigurationInterface;
9+
10+
class CorsMaxAgeHeaderProvider implements HeaderProviderInterface
11+
{
12+
protected $headerName = 'Access-Control-Max-Age';
13+
14+
protected $headerValue = '86400';
15+
16+
/**
17+
* CORS configuration provider
18+
*
19+
* @var \Magento\GraphQl\Model\Cors\ConfigurationInterface
20+
*/
21+
private $corsConfiguration;
22+
23+
public function __construct(ConfigurationInterface $corsConfiguration)
24+
{
25+
$this->corsConfiguration = $corsConfiguration;
26+
}
27+
28+
public function getName()
29+
{
30+
return $this->headerName;
31+
}
32+
33+
public function canApply()
34+
{
35+
return $this->corsConfiguration->isEnabled() && $this->getValue();
36+
}
37+
38+
public function getValue()
39+
{
40+
return $this->corsConfiguration->getMaxAge()
41+
? $this->corsConfiguration->getMaxAge()
42+
: $this->headerValue;
43+
}
44+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
4+
namespace Magento\GraphQl\Model\Cors;
5+
6+
7+
use Magento\Framework\App\Config\ScopeConfigInterface;
8+
9+
class Configuration implements ConfigurationInterface
10+
{
11+
const XML_PATH_CORS_HEADERS_ENABLED = 'graphql/cors/enabled';
12+
const XML_PATH_CORS_ALLOWED_ORIGINS = 'graphql/cors/allowed_origins';
13+
const XML_PATH_CORS_ALLOWED_HEADERS = 'graphql/cors/allowed_headers';
14+
const XML_PATH_CORS_ALLOWED_METHODS = 'graphql/cors/allowed_methods';
15+
const XML_PATH_CORS_MAX_AGE = 'graphql/cors/max_age';
16+
const XML_PATH_CORS_ALLOW_CREDENTIALS = 'graphql/cors/allow_credentials';
17+
18+
/**
19+
* @var ScopeConfigInterface
20+
*/
21+
protected $scopeConfig;
22+
23+
public function __construct(ScopeConfigInterface $scopeConfig)
24+
{
25+
$this->scopeConfig = $scopeConfig;
26+
}
27+
28+
public function isEnabled(): bool
29+
{
30+
return $this->scopeConfig->isSetFlag(self::XML_PATH_CORS_HEADERS_ENABLED);
31+
}
32+
33+
public function getAllowedOrigins(): ?string
34+
{
35+
return $this->scopeConfig->getValue(self::XML_PATH_CORS_ALLOWED_ORIGINS);
36+
}
37+
38+
public function getAllowedHeaders(): ?string
39+
{
40+
return $this->scopeConfig->getValue(self::XML_PATH_CORS_ALLOWED_HEADERS);
41+
}
42+
43+
public function getAllowedMethods(): ?string
44+
{
45+
return $this->scopeConfig->getValue(self::XML_PATH_CORS_ALLOWED_METHODS);
46+
}
47+
48+
public function getMaxAge(): int
49+
{
50+
return $this->scopeConfig->getValue(self::XML_PATH_CORS_MAX_AGE);
51+
}
52+
53+
public function isCredentialsAllowed(): bool
54+
{
55+
return $this->scopeConfig->isSetFlag(self::XML_PATH_CORS_ALLOW_CREDENTIALS);
56+
}
57+
58+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
4+
namespace Magento\GraphQl\Model\Cors;
5+
6+
7+
interface ConfigurationInterface
8+
{
9+
public function isEnabled() : bool;
10+
11+
public function getAllowedOrigins() : ?string;
12+
13+
public function getAllowedHeaders() : ?string;
14+
15+
public function getAllowedMethods() : ?string;
16+
17+
public function getMaxAge() : int;
18+
19+
public function isCredentialsAllowed() : bool;
20+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
9+
<system>
10+
<section id="graphql" translate="label" type="text" sortOrder="300" showInDefault="1" showInWebsite="1" showInStore="1">
11+
<label>GraphQL</label>
12+
<tab>service</tab>
13+
<resource>Magento_Integration::config_oauth</resource>
14+
<group id="cors" translate="label" type="text" sortOrder="60" showInDefault="1" showInWebsite="1">
15+
<label>CORS Settings</label>
16+
<field id="enabled" translate="label" type="select" sortOrder="1" showInDefault="1" canRestore="1">
17+
<label>CORS Headers Enabled</label>
18+
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
19+
</field>
20+
21+
<field id="allowed_origins" translate="label" type="text" sortOrder="10" showInDefault="1" canRestore="1">
22+
<label>Allowed origins</label>
23+
<depends>
24+
<field id="graphql/cors/enabled">1</field>
25+
</depends>
26+
</field>
27+
28+
<field id="allowed_methods" translate="label" type="text" sortOrder="20" showInDefault="1" canRestore="1">
29+
<label>Allowed methods</label>
30+
<depends>
31+
<field id="graphql/cors/enabled">1</field>
32+
</depends>
33+
</field>
34+
35+
<field id="allowed_headers" translate="label" type="text" sortOrder="30" showInDefault="1" canRestore="1">
36+
<label>Allowed headers</label>
37+
<depends>
38+
<field id="graphql/cors/enabled">1</field>
39+
</depends>
40+
</field>
41+
42+
<field id="max_age" translate="label" type="text" sortOrder="40" showInDefault="1" canRestore="1">
43+
<label>Max Age</label>
44+
<depends>
45+
<field id="graphql/cors/enabled">1</field>
46+
</depends>
47+
</field>
48+
49+
<field id="allow_credentials" translate="label" type="select" sortOrder="50" showInDefault="1" canRestore="1">
50+
<label>Credentials Allowed</label>
51+
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
52+
<depends>
53+
<field id="graphql/cors/enabled">1</field>
54+
</depends>
55+
</field>
56+
</group>
57+
</section>
58+
</system>
59+
</config>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0"?>
2+
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
4+
<default>
5+
<graphql>
6+
<cors>
7+
<enabled>0</enabled>
8+
<allowed_origins></allowed_origins>
9+
<allowed_methods></allowed_methods>
10+
<allowed_headers></allowed_headers>
11+
<max_age>86400</max_age>
12+
<allow_credentials>0</allow_credentials>
13+
</cors>
14+
</graphql>
15+
</default>
16+
</config>

app/code/Magento/GraphQl/etc/di.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,6 @@
9898
<argument name="queryComplexity" xsi:type="number">300</argument>
9999
</arguments>
100100
</type>
101+
102+
<preference for="Magento\GraphQl\Model\Cors\ConfigurationInterface" type="Magento\GraphQl\Model\Cors\Configuration" />
101103
</config>

0 commit comments

Comments
 (0)