ContentSecurityPolicyNonceManager.php 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace OC\Security\CSP;
  8. use OC\AppFramework\Http\Request;
  9. use OC\Security\CSRF\CsrfTokenManager;
  10. use OCP\IRequest;
  11. /**
  12. * @package OC\Security\CSP
  13. */
  14. class ContentSecurityPolicyNonceManager {
  15. private string $nonce = '';
  16. public function __construct(
  17. private CsrfTokenManager $csrfTokenManager,
  18. private IRequest $request,
  19. ) {
  20. }
  21. /**
  22. * Returns the current CSP nonce
  23. */
  24. public function getNonce(): string {
  25. if ($this->nonce === '') {
  26. if (empty($this->request->server['CSP_NONCE'])) {
  27. // Get the token from the CSRF token, we only use the "shared secret" part
  28. // as the first part does not add any security / entropy to the token
  29. // so it can be ignored to keep the nonce short while keeping the same randomness
  30. $csrfSecret = explode(':', ($this->csrfTokenManager->getToken()->getEncryptedValue()));
  31. $this->nonce = end($csrfSecret);
  32. } else {
  33. $this->nonce = $this->request->server['CSP_NONCE'];
  34. }
  35. }
  36. return $this->nonce;
  37. }
  38. /**
  39. * Check if the browser supports CSP v3
  40. */
  41. public function browserSupportsCspV3(): bool {
  42. $browserBlocklist = [
  43. Request::USER_AGENT_IE,
  44. ];
  45. if ($this->request->isUserAgent($browserBlocklist)) {
  46. return false;
  47. }
  48. return true;
  49. }
  50. }