Skip to content

Commit cb12e54

Browse files
[6.x] REST API Authentication (#12051)
Co-authored-by: Jason Varga <jason@pixelfear.com>
1 parent fd2b27b commit cb12e54

4 files changed

Lines changed: 122 additions & 2 deletions

File tree

config/api.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,24 @@
3131

3232
/*
3333
|--------------------------------------------------------------------------
34-
| Middleware & Authentication
34+
| Authentication
35+
|--------------------------------------------------------------------------
36+
|
37+
| By default, the API will be publicly accessible. However, you may define
38+
| an API token here which will be used to authenticate requests.
39+
|
40+
*/
41+
42+
'auth_token' => env('STATAMIC_API_AUTH_TOKEN'),
43+
44+
/*
45+
|--------------------------------------------------------------------------
46+
| Middleware
3547
|--------------------------------------------------------------------------
3648
|
3749
| Define the middleware / middleware group that will be applied to the
3850
| API route group. If you want to externally expose this API, here
39-
| you can configure a middleware based authentication layer.
51+
| you can configure a middleware-based authentication layer.
4052
|
4153
*/
4254

routes/routes.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
use Illuminate\Support\Facades\Route;
44
use Statamic\API\Middleware\Cache;
5+
use Statamic\API\Middleware\HandleAuthentication;
56
use Statamic\Facades\Glide;
67
use Statamic\Http\Middleware\CP\SwapExceptionHandler as SwapCpExceptionHandler;
78
use Statamic\Http\Middleware\RequireStatamicPro;
89

910
if (config('statamic.api.enabled')) {
1011
Route::middleware([
1112
RequireStatamicPro::class,
13+
HandleAuthentication::class,
1214
Cache::class,
1315
])->group(function () {
1416
Route::middleware(config('statamic.api.middleware'))
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace Statamic\API\Middleware;
4+
5+
use Closure;
6+
7+
class HandleAuthentication
8+
{
9+
/**
10+
* Handle an incoming request.
11+
*
12+
* @param \Illuminate\Http\Request $request
13+
* @return mixed
14+
*/
15+
public function handle($request, Closure $next)
16+
{
17+
if (
18+
($token = config('statamic.api.auth_token'))
19+
&& ($request->bearerToken() !== $token)
20+
) {
21+
abort(401);
22+
}
23+
24+
return $next($request);
25+
}
26+
}

tests/API/AuthenticationTest.php

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
namespace vendor\statamic\cms\tests\API;
4+
5+
use PHPUnit\Framework\Attributes\Test;
6+
use Statamic\Facades;
7+
use Tests\PreventSavingStacheItemsToDisk;
8+
use Tests\TestCase;
9+
10+
class AuthenticationTest extends TestCase
11+
{
12+
use PreventSavingStacheItemsToDisk;
13+
14+
private $collection;
15+
16+
public function setUp(): void
17+
{
18+
parent::setUp();
19+
20+
Facades\Config::set('statamic.api.enabled', true);
21+
Facades\Config::set('statamic.api.resources.collections', true);
22+
23+
$this->collection = Facades\Collection::make('articles')->save();
24+
}
25+
26+
#[Test]
27+
public function it_can_authenticate_using_auth_token()
28+
{
29+
Facades\Config::set('statamic.api.auth_token', 'foobar');
30+
31+
$this
32+
->withToken('foobar')
33+
->getJson('/api/collections/articles/entries')
34+
->assertOk();
35+
}
36+
37+
#[Test]
38+
public function it_cant_authenticate_with_invalid_auth_token()
39+
{
40+
Facades\Config::set('statamic.api.auth_token', 'foobar');
41+
42+
$this
43+
->withToken($token = 'invalid')
44+
->getJson($url = '/api/collections/articles/entries')
45+
->assertUnauthorized();
46+
47+
$this
48+
->withToken($token)
49+
->get($url)
50+
->assertUnauthorized();
51+
}
52+
53+
#[Test]
54+
public function it_cant_authenticate_without_auth_token()
55+
{
56+
Facades\Config::set('statamic.api.auth_token', 'foobar');
57+
58+
$this
59+
->getJson($url = '/api/collections/articles/entries')
60+
->assertUnauthorized();
61+
62+
$this
63+
->get($url)
64+
->assertUnauthorized();
65+
}
66+
67+
#[Test]
68+
public function authentication_only_required_when_auth_token_is_set()
69+
{
70+
Facades\Config::set('statamic.api.auth_token', null);
71+
72+
$this
73+
->getJson($url = '/api/collections/articles/entries')
74+
->assertOk();
75+
76+
$this
77+
->get($url)
78+
->assertOk();
79+
}
80+
}

0 commit comments

Comments
 (0)