1: <?php
2: /**
3: * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
4: * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
5: *
6: * Licensed under The MIT License
7: * For full copyright and license information, please see the LICENSE.txt
8: * Redistributions of files must retain the above copyright notice.
9: *
10: * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
11: * @link https://cakephp.org CakePHP(tm) Project
12: * @since 2.0.0
13: * @license https://opensource.org/licenses/mit-license.php MIT License
14: */
15: namespace Cake\Auth;
16:
17: use Cake\Http\Exception\UnauthorizedException;
18: use Cake\Http\Response;
19: use Cake\Http\ServerRequest;
20:
21: /**
22: * Basic Authentication adapter for AuthComponent.
23: *
24: * Provides Basic HTTP authentication support for AuthComponent. Basic Auth will
25: * authenticate users against the configured userModel and verify the username
26: * and passwords match.
27: *
28: * ### Using Basic auth
29: *
30: * Load `AuthComponent` in your controller's `initialize()` and add 'Basic' in 'authenticate' key
31: * ```
32: * $this->loadComponent('Auth', [
33: * 'authenticate' => ['Basic']
34: * 'storage' => 'Memory',
35: * 'unauthorizedRedirect' => false,
36: * ]);
37: * ```
38: *
39: * You should set `storage` to `Memory` to prevent CakePHP from sending a
40: * session cookie to the client.
41: *
42: * You should set `unauthorizedRedirect` to `false`. This causes `AuthComponent` to
43: * throw a `ForbiddenException` exception instead of redirecting to another page.
44: *
45: * Since HTTP Basic Authentication is stateless you don't need call `setUser()`
46: * in your controller. The user credentials will be checked on each request. If
47: * valid credentials are not provided, required authentication headers will be sent
48: * by this authentication provider which triggers the login dialog in the browser/client.
49: *
50: * @see https://book.cakephp.org/3.0/en/controllers/components/authentication.html
51: */
52: class BasicAuthenticate extends BaseAuthenticate
53: {
54:
55: /**
56: * Authenticate a user using HTTP auth. Will use the configured User model and attempt a
57: * login using HTTP auth.
58: *
59: * @param \Cake\Http\ServerRequest $request The request to authenticate with.
60: * @param \Cake\Http\Response $response The response to add headers to.
61: * @return mixed Either false on failure, or an array of user data on success.
62: */
63: public function authenticate(ServerRequest $request, Response $response)
64: {
65: return $this->getUser($request);
66: }
67:
68: /**
69: * Get a user based on information in the request. Used by cookie-less auth for stateless clients.
70: *
71: * @param \Cake\Http\ServerRequest $request Request object.
72: * @return mixed Either false or an array of user information
73: */
74: public function getUser(ServerRequest $request)
75: {
76: $username = $request->getEnv('PHP_AUTH_USER');
77: $pass = $request->getEnv('PHP_AUTH_PW');
78:
79: if (!is_string($username) || $username === '' || !is_string($pass) || $pass === '') {
80: return false;
81: }
82:
83: return $this->_findUser($username, $pass);
84: }
85:
86: /**
87: * Handles an unauthenticated access attempt by sending appropriate login headers
88: *
89: * @param \Cake\Http\ServerRequest $request A request object.
90: * @param \Cake\Http\Response $response A response object.
91: * @return void
92: * @throws \Cake\Http\Exception\UnauthorizedException
93: */
94: public function unauthenticated(ServerRequest $request, Response $response)
95: {
96: $Exception = new UnauthorizedException();
97: $Exception->responseHeader($this->loginHeaders($request));
98: throw $Exception;
99: }
100:
101: /**
102: * Generate the login headers
103: *
104: * @param \Cake\Http\ServerRequest $request Request object.
105: * @return array Headers for logging in.
106: */
107: public function loginHeaders(ServerRequest $request)
108: {
109: $realm = $this->getConfig('realm') ?: $request->getEnv('SERVER_NAME');
110:
111: return [
112: 'WWW-Authenticate' => sprintf('Basic realm="%s"', $realm)
113: ];
114: }
115: }
116: