diff --git a/src/Controllers/ApiController.php b/src/Controllers/ApiController.php
index faad6ab5..77af8e32 100644
--- a/src/Controllers/ApiController.php
+++ b/src/Controllers/ApiController.php
@@ -47,16 +47,14 @@ function actionDebug() {
function actionIndex()
{
- $token = false;
+ $settings = CraftQL::getInstance()->getSettings();
- $authorization = Craft::$app->request->headers->get('authorization');
- preg_match('/^(?:b|B)earer\s+(?.+)/', $authorization, $matches);
- $token = Token::findId(@$matches['tokenId']);
+ $token = static::findToken($settings->authorizationHeader, Craft::$app->request->headers);
// @todo, check user permissions when PRO license
$response = \Craft::$app->getResponse();
- if ($allowedOrigins = CraftQL::getInstance()->getSettings()->allowedOrigins) {
+ if ($allowedOrigins = $settings->allowedOrigins) {
if (is_string($allowedOrigins)) {
$allowedOrigins = [$allowedOrigins];
}
@@ -65,9 +63,15 @@ function actionIndex()
$response->headers->add('Access-Control-Allow-Origin', $origin);
}
$response->headers->add('Access-Control-Allow-Credentials', 'true');
- $response->headers->add('Access-Control-Allow-Headers', 'Authorization, Content-Type');
+
+ $allowedHeaders = ['Authorization', 'Content-Type'];
+ if ($settings->authorizationHeader) {
+ $allowedHeaders[] = $settings->authorizationHeader;
+ }
+
+ $response->headers->add('Access-Control-Allow-Headers', implode(', ', $allowedHeaders));
}
- $response->headers->add('Allow', implode(', ', CraftQL::getInstance()->getSettings()->verbs));
+ $response->headers->add('Allow', implode(', ', $settings->verbs));
if (\Craft::$app->getRequest()->isOptions) {
return '';
@@ -120,7 +124,7 @@ function actionIndex()
$result = $this->graphQl->execute($schema, $input, $variables);
Craft::trace('CraftQL: Execution complete');
- $customHeaders = CraftQL::getInstance()->getSettings()->headers ?: [];
+ $customHeaders = $settings->headers ?: [];
foreach ($customHeaders as $key => $value) {
if (is_callable($value)) {
$value = $value($schema, $input, $variables, $result);
@@ -148,4 +152,23 @@ function actionIndex()
return $this->asJson($result);
}
+
+ private static function findToken($authorizationHeader, $headers)
+ {
+ // Default, for cases when token header is not found to use user based token
+ // resolution, if possible.
+ $tokenId = null;
+
+ if ($authorizationHeader) {
+ if ($headers->has($authorizationHeader)) {
+ $tokenId = $headers->get($authorizationHeader);
+ }
+ } else if ($headers->has('authorization')) {
+ $authorization = $headers->get('authorization');
+ preg_match('/^(?:b|B)earer\s+(?.+)/', $authorization, $matches);
+ $tokenId = @$matches['tokenId'];
+ }
+
+ return Token::findId($tokenId);
+ }
}
diff --git a/src/Controllers/CpController.php b/src/Controllers/CpController.php
index 64494477..b05c3893 100644
--- a/src/Controllers/CpController.php
+++ b/src/Controllers/CpController.php
@@ -64,6 +64,7 @@ function actionGraphiql()
$this->renderTemplate('craftql/graphiql', [
'url' => "{$url}{$uri}",
'token' => false,
+ 'authorizationHeader' => $instance->settings->authorizationHeader,
]);
}
@@ -78,6 +79,7 @@ function actionGraphiqlas($token)
$this->renderTemplate('craftql/graphiql', [
'url' => "{$url}{$uri}",
'token' => $token,
+ 'authorizationHeader' => $instance->settings->authorizationHeader,
]);
}
}
diff --git a/src/CraftQL.php b/src/CraftQL.php
index d98eb169..502a0baa 100644
--- a/src/CraftQL.php
+++ b/src/CraftQL.php
@@ -107,8 +107,13 @@ protected function createSettingsModel()
*/
protected function settingsHtml()
{
+ $settings = $this->getSettings();
+
+ $curlAuthorizationHeader = $settings->authorizationHeader ? "{$settings->authorizationHeader}:" : 'Authorization: Bearer';
+
return \Craft::$app->getView()->renderTemplate('craftql/settings', [
- 'settings' => $this->getSettings()
+ 'settings' => $settings,
+ 'curlAuthorizationHeader' => $curlAuthorizationHeader
]);
}
diff --git a/src/Models/Settings.php b/src/Models/Settings.php
index 5b3c4ba3..712bbfa8 100644
--- a/src/Models/Settings.php
+++ b/src/Models/Settings.php
@@ -7,6 +7,7 @@
class Settings extends Model
{
+ public $authorizationHeader = '';
public $uri = 'api';
public $verbs = ['POST'];
public $allowedOrigins = [];
diff --git a/src/templates/graphiql.html b/src/templates/graphiql.html
index 50fd0006..97582f7a 100644
--- a/src/templates/graphiql.html
+++ b/src/templates/graphiql.html
@@ -148,7 +148,11 @@
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
+ {% if authorizationHeader and token %}
+ '{{ authorizationHeader }}': '{{ token }}',
+ {% elseif token %}
'Authorization': 'Bearer {{ token }}',
+ {% endif %}
},
body: JSON.stringify(graphQLParams),
credentials: 'include',
diff --git a/src/templates/settings.html b/src/templates/settings.html
index b05f9062..213eee33 100644
--- a/src/templates/settings.html
+++ b/src/templates/settings.html
@@ -55,7 +55,7 @@
2. **Curl**
{% if settings.tokens|length %}You can query your schema directly by passing a GraphQL statement throuh a `query` variable. The following Curl statement should get you started,
-$ curl -H "Authorization: bearer {{ settings.tokens[0].token|default('{TOKEN}') }}" -H "Content-type: application/json" -d '{"query":"{ helloWorld }"}' {{ siteUrl }}{{ settings.uri }}
+$ curl -H "{{ curlAuthorizationHeader }} {{ settings.tokens[0].token|default('{TOKEN}') }}" -H "Content-type: application/json" -d '{"query":"{ helloWorld }"}' {{ siteUrl }}{{ settings.uri }}
{% else %}
Before you can use Curl you need to [add a token]({{ url('craftql/token-gen') }}) for authenticated access in to Craft.
{% endif %}
@@ -68,6 +68,15 @@
+
Custom Authorization Header
+
+ {{ forms.textField({
+ first: true,
+ name: 'authorizationHeader',
+ value: settings.authorizationHeader,
+ instructions: 'Custom header to be used to check for authorization token. Useful if site is behind Basic Auth and conflicts with default Authorization Bearer.'
+ }) }}
+
URI
{{ forms.textField({