[ Index ]

PHP Cross Reference of YOURLS

title

Body

[close]

/tests/tests/auth/ -> SigTest.php (source)

   1  <?php
   2  /**
   3   * Tests with signatures
   4   */
   5  #[\PHPUnit\Framework\Attributes\Group('auth')]
   6  #[\PHPUnit\Framework\Attributes\Group('signatures')]
   7  class SigTest extends PHPUnit\Framework\TestCase {
   8  
   9      protected $backup_request;
  10  
  11      protected function setUp(): void {
  12          $this->backup_request = $_REQUEST;
  13      }
  14  
  15      protected function tearDown(): void {
  16          $_REQUEST = $this->backup_request;
  17          yourls_remove_all_filters( 'auth_signature' );
  18          yourls_remove_all_filters( 'auth_signature_length' );
  19      }
  20  
  21      /**
  22       * Check that empty signature isn't valid
  23       */
  24      public function test_signature_empty() {
  25          unset( $_REQUEST['signature'] );
  26          $this->assertFalse( yourls_check_signature() );
  27      }
  28  
  29      /**
  30       * Check that random signature isn't valid
  31       */
  32      public function test_signature_random() {
  33          $_REQUEST['signature'] = rand_str();
  34          $this->assertFalse( yourls_check_signature() );
  35      }
  36  
  37      /**
  38       * Check that empty signature and timestamp isn't valid
  39       */
  40      public function test_signature_timestamp_empty() {
  41          unset( $_REQUEST['signature'] );
  42          unset( $_REQUEST['timestamp'] );
  43          $this->assertFalse( yourls_check_signature_timestamp() );
  44      }
  45  
  46      /**
  47       * Check that random signature and timestamp isn't valid
  48       */
  49      public function test_signature_timestamp_random() {
  50          $_REQUEST['signature'] = rand_str();
  51          $_REQUEST['timestamp'] = rand_str();
  52          $this->assertFalse( yourls_check_signature_timestamp() );
  53      }
  54  
  55      /**
  56       * Check that valid sha256 (default algo) timestamped sig is valid
  57       */
  58      public function test_signature_timestamp_sha256() {
  59          $timestamp = time();
  60          $_REQUEST['timestamp'] = $timestamp;
  61  
  62          global $yourls_user_passwords;
  63          $random_user = array_rand($yourls_user_passwords);
  64          $signature = yourls_auth_signature($random_user);
  65  
  66          $hash = hash( 'sha256', $timestamp . $signature );
  67          $_REQUEST['signature'] = $hash;
  68          $this->assertTrue( yourls_check_signature_timestamp() );
  69  
  70          $hash = hash( 'sha256', $signature . $timestamp );
  71          $_REQUEST['signature'] = $hash;
  72          $this->assertTrue( yourls_check_signature_timestamp() );
  73      }
  74  
  75      /**
  76       * Check that valid hashed timestamped sig with a specified algo is valid
  77       */
  78      public function test_signature_timestamp_hash() {
  79          $timestamp = time();
  80          $_REQUEST['timestamp'] = $timestamp;
  81  
  82          global $yourls_user_passwords;
  83          $random_user = array_rand($yourls_user_passwords);
  84          $signature = yourls_auth_signature($random_user);
  85  
  86          $algos = [ 'sha256', 'sha384', 'sha512' ];
  87  
  88          foreach( $algos as $algo ) {
  89              $hash = hash( $algo, $timestamp . $signature );
  90              $_REQUEST['hash'] = $algo;
  91              $_REQUEST['signature'] = $hash;
  92              $this->assertTrue( yourls_check_signature_timestamp() );
  93  
  94              $hash = hash( $algo, $signature . $timestamp );
  95              $_REQUEST['signature'] = $hash;
  96              $this->assertTrue( yourls_check_signature_timestamp() );
  97  
  98              $_REQUEST['hash'] = rand_str();
  99              $this->assertFalse( yourls_check_signature_timestamp() );
 100          }
 101      }
 102  
 103      /**
 104       * Make sure we always define a default hash algo and an allowed hash algos list, so that future update of function
 105       * will maintain the same behavior (allow algo other than sha256, sha384 and sha512 via filter)
 106       */
 107      public function test_signature_timestamp_default_algo() {
 108          $this->assertIsString( yourls_default_hash_algo() );
 109          $this->assertIsArray( yourls_allowed_hash_algos() );
 110      }
 111  
 112      /**
 113       * Provide valid and invalid timestamps as compared to current time and nonce life
 114       */
 115      public static function timestamps(): \Iterator {
 116          $now  = time();
 117          $life = yourls_get_nonce_life();
 118          $little_in_the_future = $now + ( $life / 2 );
 119          $little_in_the_past   = $now - ( $life / 2 );
 120          $far_in_the_future    = $now + ( $life * 2 );
 121          $far_in_the_past      = $now - ( $life * 2 );
 122          yield array( 0, false );
 123          yield array( $now, true );
 124          yield array( $little_in_the_future, true );
 125          yield array( $little_in_the_past, true );
 126          yield array( $far_in_the_future, false );
 127          yield array( $far_in_the_past, false );
 128      }
 129  
 130      /**
 131       * Check that timestamps are correctly handled (too old = bad, too future = bad, ...)
 132       */
 133      #[\PHPUnit\Framework\Attributes\DataProvider('timestamps')]
 134      public function test_check_timestamp( $timestamp, $is_valid ) {
 135          $this->assertSame(yourls_check_timestamp( $timestamp ), $is_valid );
 136      }
 137  
 138      /**
 139       * Check that auth signature length defaults to 32 and is an integer
 140       */
 141      public function test_auth_signature_length_default() {
 142          $this->assertSame( 32, yourls_auth_signature_length() );
 143      }
 144  
 145      /**
 146       * Check that auth signature length can be filtered
 147       */
 148      public function test_auth_signature_length_filtered() {
 149          $hook = 'auth_signature_length';
 150          // Filter with an int, and with a non int that must be cast to int
 151          yourls_add_filter( $hook, fn() => 16 );
 152          $this->assertSame( 16, yourls_auth_signature_length() );
 153          yourls_remove_all_filters( $hook );
 154  
 155          yourls_add_filter( $hook, fn() => '24' );
 156          $this->assertSame( 24, yourls_auth_signature_length() );
 157          yourls_remove_all_filters( $hook );
 158      }
 159  
 160      /**
 161       * Check that auth signature is constant for a given user and differs between users
 162       */
 163      public function test_auth_signature_is_deterministic_and_user_specific() {
 164          $this->assertSame( yourls_auth_signature( 'ozh' ), yourls_auth_signature( 'ozh' ) );
 165          $this->assertNotSame( yourls_auth_signature( 'dgw' ), yourls_auth_signature( 'Leo' ) );
 166      }
 167  
 168      /**
 169       * Check that auth signature with a falsy username falls back to YOURLS_USER, or errors when none is defined
 170       */
 171      public function test_auth_signature_no_username() {
 172          if ( defined( 'YOURLS_USER' ) && YOURLS_USER ) {
 173              // A falsy username falls back to the currently logged in user
 174              $this->assertSame( yourls_auth_signature( YOURLS_USER ), yourls_auth_signature() );
 175              $this->assertSame( yourls_auth_signature( YOURLS_USER ), yourls_auth_signature( false ) );
 176              $this->assertSame( yourls_auth_signature( YOURLS_USER ), yourls_auth_signature( '' ) );
 177          } else {
 178              // No username and no logged in user yields the error message
 179              $this->assertSame( 'Cannot generate auth signature: no username', yourls_auth_signature() );
 180              $this->assertSame( 'Cannot generate auth signature: no username', yourls_auth_signature( false ) );
 181              $this->assertSame( 'Cannot generate auth signature: no username', yourls_auth_signature( '' ) );
 182          }
 183      }
 184  
 185      /**
 186       * Check that auth signature honors its length filter
 187       */
 188      public function test_auth_signature_honors_length_filter() {
 189          yourls_add_filter( 'auth_signature_length', fn() => 10 );
 190  
 191          $signature = yourls_auth_signature( 'ozh' );
 192          $this->assertSame( 10, strlen( $signature ) );
 193      }
 194  
 195      /**
 196       * Check that auth signature can be filtered
 197       */
 198      public function test_auth_signature_filtered() {
 199          yourls_add_filter( 'auth_signature', fn( $signature, $username ) => 'filtered:' . $username, 10, 2 );
 200  
 201          $this->assertSame( 'filtered:ozh', yourls_auth_signature( 'ozh' ) );
 202      }
 203  
 204  }


Generated: Sat Jul 11 05:10:54 2026 Cross-referenced by PHPXref 0.7.1