Browse Source

Allow config of anonymous access

Maurits van der Schee 6 years ago
parent
commit
bfb7740109

+ 6
- 2
README.md View File

@@ -161,9 +161,12 @@ You can tune the middleware behavior using middleware specific configuration par
161 161
 - "cors.allowMethods": The methods allowed in the CORS request ("OPTIONS, GET, PUT, POST, DELETE, PATCH")
162 162
 - "cors.allowCredentials": To allow credentials in the CORS request ("true")
163 163
 - "cors.maxAge": The time that the CORS grant is valid in seconds ("1728000")
164
+- "jwtAuth.mode": Set to "optional" if you want to allow anonymous access ("required")
164 165
 - "jwtAuth.leeway": The acceptable number of seconds of clock skew ("5")
165 166
 - "jwtAuth.ttl": The number of seconds the token is valid ("30")
166 167
 - "jwtAuth.secret": The shared secret used to sign the JWT token with ("")
168
+- "basicAuth.mode": Set to "optional" if you want to allow anonymous access ("required")
169
+- "basicAuth.realm": Text to prompt when showing login ("Username and password required")
167 170
 - "basicAuth.passwordFile": The file to read for username/password combinations (".htpasswd")
168 171
 - "authorization.tableHandler": Handler to implement table authorization rules ("")
169 172
 - "authorization.columnHandler": Handler to implement column authorization rules ("")
@@ -793,11 +796,12 @@ The following errors may be reported:
793 796
 - 1008: Cannot read HTTP message (422 UNPROCESSABLE ENTITY)
794 797
 - 1009: Duplicate key exception (409 CONFLICT)
795 798
 - 1010: Data integrity violation (409 CONFLICT)
796
-- 1011: Authorization required (401 UNAUTHORIZED)
797
-- 1012: Access denied (403 FORBIDDEN)
799
+- 1011: Authentication required (401 UNAUTHORIZED)
800
+- 1012: Authentication failed (403 FORBIDDEN)
798 801
 - 1013: Input validation failed (422 UNPROCESSABLE ENTITY)
799 802
 - 1014: Operation forbidden (403 FORBIDDEN)
800 803
 - 1015: Operation not supported (405 METHOD NOT ALLOWED)
804
+- 1016: Temporary or permanently blocked (403 FORBIDDEN)
801 805
 - 9999: Unknown error (500: INTERNAL SERVER ERROR)
802 806
 
803 807
 The following JSON structure is used:

+ 10
- 1
src/Tqdev/PhpCrudApi/Middleware/BasicAuthMiddleware.php View File

@@ -85,7 +85,16 @@ class BasicAuthMiddleware extends Middleware
85 85
             $validUser = $this->getValidUsername($username, $password, $passwordFile);
86 86
             $_SESSION['username'] = $validUser;
87 87
             if (!$validUser) {
88
-                return $this->responder->error(ErrorCode::ACCESS_DENIED, $username);
88
+                return $this->responder->error(ErrorCode::AUTHENTICATION_FAILED, $username);
89
+            }
90
+        }
91
+        if (!isset($_SESSION['username']) || !$_SESSION['username']) {
92
+            $authenticationMode = $this->getProperty('mode', 'required');
93
+            if ($authenticationMode == 'required') {
94
+                $response = $this->responder->error(ErrorCode::AUTHENTICATION_REQUIRED, '');
95
+                $realm = $this->getProperty('realm', 'Username and password required');
96
+                $response->addHeader('WWW-Authenticate', "Basic realm=\"$realm\"");
97
+                return $response;
89 98
             }
90 99
         }
91 100
         return $this->next->handle($request);

+ 1
- 1
src/Tqdev/PhpCrudApi/Middleware/FirewallMiddleware.php View File

@@ -46,7 +46,7 @@ class FirewallMiddleware extends Middleware
46 46
         }
47 47
         $allowedIpAddresses = $this->getProperty('allowedIpAddresses', '');
48 48
         if (!$this->isIpAllowed($ipAddress, $allowedIpAddresses)) {
49
-            $response = $this->responder->error(ErrorCode::ACCESS_DENIED, $ipAddress);
49
+            $response = $this->responder->error(ErrorCode::TEMPORARY_OR_PERMANENTLY_BLOCKED, '');
50 50
         } else {
51 51
             $response = $this->next->handle($request);
52 52
         }

+ 7
- 1
src/Tqdev/PhpCrudApi/Middleware/JwtAuthMiddleware.php View File

@@ -87,7 +87,13 @@ class JwtAuthMiddleware extends Middleware
87 87
             $claims = $this->getClaims($token);
88 88
             $_SESSION['claims'] = $claims;
89 89
             if (empty($claims)) {
90
-                return $this->responder->error(ErrorCode::ACCESS_DENIED, 'JWT');
90
+                return $this->responder->error(ErrorCode::AUTHENTICATION_FAILED, 'JWT');
91
+            }
92
+        }
93
+        if (empty($_SESSION['claims'])) {
94
+            $authenticationMode = $this->getProperty('mode', 'required');
95
+            if ($authenticationMode == 'required') {
96
+                return $this->responder->error(ErrorCode::AUTHENTICATION_REQUIRED, '');
91 97
             }
92 98
         }
93 99
         return $this->next->handle($request);

+ 6
- 4
src/Tqdev/PhpCrudApi/Record/ErrorCode.php View File

@@ -22,11 +22,12 @@ class ErrorCode
22 22
     const HTTP_MESSAGE_NOT_READABLE = 1008;
23 23
     const DUPLICATE_KEY_EXCEPTION = 1009;
24 24
     const DATA_INTEGRITY_VIOLATION = 1010;
25
-    const AUTHORIZATION_REQUIRED = 1011;
26
-    const ACCESS_DENIED = 1012;
25
+    const AUTHENTICATION_REQUIRED = 1011;
26
+    const AUTHENTICATION_FAILED = 1012;
27 27
     const INPUT_VALIDATION_FAILED = 1013;
28 28
     const OPERATION_FORBIDDEN = 1014;
29 29
     const OPERATION_NOT_SUPPORTED = 1015;
30
+    const TEMPORARY_OR_PERMANENTLY_BLOCKED = 1016;
30 31
 
31 32
     private $values = [
32 33
         9999 => ["%s", Response::INTERNAL_SERVER_ERROR],
@@ -41,11 +42,12 @@ class ErrorCode
41 42
         1008 => ["Cannot read HTTP message", Response::UNPROCESSABLE_ENTITY],
42 43
         1009 => ["Duplicate key exception", Response::CONFLICT],
43 44
         1010 => ["Data integrity violation", Response::CONFLICT],
44
-        1011 => ["Authorization required", Response::UNAUTHORIZED],
45
-        1012 => ["Access denied for '%s'", Response::FORBIDDEN],
45
+        1011 => ["Authentication required", Response::UNAUTHORIZED],
46
+        1012 => ["Authentication failed for '%s'", Response::FORBIDDEN],
46 47
         1013 => ["Input validation failed for '%s'", Response::UNPROCESSABLE_ENTITY],
47 48
         1014 => ["Operation forbidden", Response::FORBIDDEN],
48 49
         1015 => ["Operation '%s' not supported", Response::METHOD_NOT_ALLOWED],
50
+        1016 => ["Temporary or permanently blocked", Response::FORBIDDEN],
49 51
     ];
50 52
 
51 53
     public function __construct(int $code)

+ 2
- 0
tests/config/base.php View File

@@ -5,8 +5,10 @@ $settings = [
5 5
     'password' => 'php-crud-api',
6 6
     'controllers' => 'records,columns,cache,openapi',
7 7
     'middlewares' => 'cors,jwtAuth,basicAuth,authorization,validation,sanitation,multiTenancy,customization',
8
+    'jwtAuth.mode' => 'optional',
8 9
     'jwtAuth.time' => '1538207605',
9 10
     'jwtAuth.secret' => 'axpIrCGNGqxzx2R9dtXLIPUSqPo778uhb8CA0F4Hx',
11
+    'basicAuth.mode' => 'optional',
10 12
     'basicAuth.passwordFile' => __DIR__ . DIRECTORY_SEPARATOR . '.htpasswd',
11 13
     'authorization.tableHandler' => function ($operation, $tableName) {
12 14
         return !($tableName == 'invisibles' && !isset($_SESSION['claims']['name']) && empty($_SESSION['username']));

+ 2
- 2
tests/functional/002_auth/001_jwt_auth.log View File

@@ -20,9 +20,9 @@ Authorization: Bearer invalid
20 20
 ===
21 21
 403
22 22
 Content-Type: application/json
23
-Content-Length: 49
23
+Content-Length: 57
24 24
 
25
-{"code":1012,"message":"Access denied for 'JWT'"}
25
+{"code":1012,"message":"Authentication failed for 'JWT'"}
26 26
 ===
27 27
 GET /records/invisibles/e42c77c6-06a4-4502-816c-d112c7142e6d
28 28
 ===

+ 2
- 2
tests/functional/002_auth/002_basic_auth.log View File

@@ -20,9 +20,9 @@ Authorization: Basic aW52YWxpZHVzZXI6aW52YWxpZHBhc3M
20 20
 ===
21 21
 403
22 22
 Content-Type: application/json
23
-Content-Length: 57
23
+Content-Length: 65
24 24
 
25
-{"code":1012,"message":"Access denied for 'invaliduser'"}
25
+{"code":1012,"message":"Authentication failed for 'invaliduser'"}
26 26
 ===
27 27
 GET /records/invisibles/e42c77c6-06a4-4502-816c-d112c7142e6d
28 28
 ===

Loading…
Cancel
Save