Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 43 |
| BasicAuth | |
0.00% |
0 / 1 |
|
0.00% |
0 / 4 |
132 | |
0.00% |
0 / 43 |
| __construct | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 5 |
|||
| applies | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 4 |
|||
| authenticate | |
0.00% |
0 / 1 |
42 | |
0.00% |
0 / 28 |
|||
| challengeException | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 6 |
|||
| <?php | |
| /** | |
| * @file | |
| * Contains \Drupal\basic_auth\Authentication\Provider\BasicAuth. | |
| */ | |
| namespace Drupal\basic_auth\Authentication\Provider; | |
| use Drupal\Component\Utility\SafeMarkup; | |
| use Drupal\Core\Authentication\AuthenticationProviderInterface; | |
| use Drupal\Core\Authentication\AuthenticationProviderChallengeInterface; | |
| use Drupal\Core\Config\ConfigFactoryInterface; | |
| use Drupal\Core\Entity\EntityManagerInterface; | |
| use Drupal\Core\Flood\FloodInterface; | |
| use Drupal\user\UserAuthInterface; | |
| use Symfony\Component\HttpFoundation\Request; | |
| use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; | |
| /** | |
| * HTTP Basic authentication provider. | |
| */ | |
| class BasicAuth implements AuthenticationProviderInterface, AuthenticationProviderChallengeInterface { | |
| /** | |
| * The config factory. | |
| * | |
| * @var \Drupal\Core\Config\ConfigFactoryInterface | |
| */ | |
| protected $configFactory; | |
| /** | |
| * The user auth service. | |
| * | |
| * @var \Drupal\user\UserAuthInterface | |
| */ | |
| protected $userAuth; | |
| /** | |
| * The flood service. | |
| * | |
| * @var \Drupal\Core\Flood\FloodInterface | |
| */ | |
| protected $flood; | |
| /** | |
| * The entity manager. | |
| * | |
| * @var \Drupal\Core\Entity\EntityManagerInterface | |
| */ | |
| protected $entityManager; | |
| /** | |
| * Constructs a HTTP basic authentication provider object. | |
| * | |
| * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory | |
| * The config factory. | |
| * @param \Drupal\user\UserAuthInterface $user_auth | |
| * The user authentication service. | |
| * @param \Drupal\Core\Flood\FloodInterface $flood | |
| * The flood service. | |
| * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager | |
| * The entity manager service. | |
| */ | |
| public function __construct(ConfigFactoryInterface $config_factory, UserAuthInterface $user_auth, FloodInterface $flood, EntityManagerInterface $entity_manager) { | |
| $this->configFactory = $config_factory; | |
| $this->userAuth = $user_auth; | |
| $this->flood = $flood; | |
| $this->entityManager = $entity_manager; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function applies(Request $request) { | |
| $username = $request->headers->get('PHP_AUTH_USER'); | |
| $password = $request->headers->get('PHP_AUTH_PW'); | |
| return isset($username) && isset($password); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function authenticate(Request $request) { | |
| $flood_config = $this->configFactory->get('user.flood'); | |
| $username = $request->headers->get('PHP_AUTH_USER'); | |
| $password = $request->headers->get('PHP_AUTH_PW'); | |
| // Flood protection: this is very similar to the user login form code. | |
| // @see \Drupal\user\Form\UserLoginForm::validateAuthentication() | |
| // Do not allow any login from the current user's IP if the limit has been | |
| // reached. Default is 50 failed attempts allowed in one hour. This is | |
| // independent of the per-user limit to catch attempts from one IP to log | |
| // in to many different user accounts. We have a reasonably high limit | |
| // since there may be only one apparent IP for all users at an institution. | |
| if ($this->flood->isAllowed('basic_auth.failed_login_ip', $flood_config->get('ip_limit'), $flood_config->get('ip_window'))) { | |
| $accounts = $this->entityManager->getStorage('user')->loadByProperties(array('name' => $username, 'status' => 1)); | |
| $account = reset($accounts); | |
| if ($account) { | |
| if ($flood_config->get('uid_only')) { | |
| // Register flood events based on the uid only, so they apply for any | |
| // IP address. This is the most secure option. | |
| $identifier = $account->id(); | |
| } | |
| else { | |
| // The default identifier is a combination of uid and IP address. This | |
| // is less secure but more resistant to denial-of-service attacks that | |
| // could lock out all users with public user names. | |
| $identifier = $account->id() . '-' . $request->getClientIP(); | |
| } | |
| // Don't allow login if the limit for this user has been reached. | |
| // Default is to allow 5 failed attempts every 6 hours. | |
| if ($this->flood->isAllowed('basic_auth.failed_login_user', $flood_config->get('user_limit'), $flood_config->get('user_window'), $identifier)) { | |
| $uid = $this->userAuth->authenticate($username, $password); | |
| if ($uid) { | |
| $this->flood->clear('basic_auth.failed_login_user', $identifier); | |
| return $this->entityManager->getStorage('user')->load($uid); | |
| } | |
| else { | |
| // Register a per-user failed login event. | |
| $this->flood->register('basic_auth.failed_login_user', $flood_config->get('user_window'), $identifier); | |
| } | |
| } | |
| } | |
| } | |
| // Always register an IP-based failed login event. | |
| $this->flood->register('basic_auth.failed_login_ip', $flood_config->get('ip_window')); | |
| return []; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function challengeException(Request $request, \Exception $previous) { | |
| $site_name = $this->configFactory->get('system.site')->get('name'); | |
| $challenge = SafeMarkup::format('Basic realm="@realm"', array( | |
| '@realm' => !empty($site_name) ? $site_name : 'Access restricted', | |
| )); | |
| return new UnauthorizedHttpException((string) $challenge, 'No authentication credentials provided.', $previous); | |
| } | |
| } |