1<?php 2 3namespace SimpleSAML\Auth; 4 5/** 6 * A class that generates and verifies time-limited tokens. 7 */ 8class TimeLimitedToken 9{ 10 11 /** 12 * @var string 13 */ 14 protected $secretSalt; 15 16 /** 17 * @var int 18 */ 19 protected $lifetime; 20 21 /** 22 * @var int 23 */ 24 protected $skew; 25 26 /** 27 * @var string 28 */ 29 protected $algo; 30 31 32 /** 33 * Create a new time-limited token. 34 * 35 * Please note that the default algorithm will change in SSP 1.15.0 to SHA-256 instead of SHA-1. 36 * 37 * @param int $lifetime Token lifetime in seconds. Defaults to 900 (15 min). 38 * @param string $secretSalt A random and unique salt per installation. Defaults to the salt in the configuration. 39 * @param int $skew The allowed time skew (in seconds) to correct clock deviations. Defaults to 1 second. 40 * @param string $algo The hash algorithm to use to generate the tokens. Defaults to SHA-1. 41 * 42 * @throws \InvalidArgumentException if the given parameters are invalid. 43 */ 44 public function __construct($lifetime = 900, $secretSalt = null, $skew = 1, $algo = 'sha1') 45 { 46 if ($secretSalt === null) { 47 $secretSalt = \SimpleSAML\Utils\Config::getSecretSalt(); 48 } 49 50 if (!in_array($algo, hash_algos(), true)) { 51 throw new \InvalidArgumentException('Invalid hash algorithm "'.$algo.'"'); 52 } 53 54 $this->secretSalt = $secretSalt; 55 $this->lifetime = $lifetime; 56 $this->skew = $skew; 57 $this->algo = $algo; 58 } 59 60 61 /** 62 * Add some given data to the current token. This data will be needed later too for token validation. 63 * 64 * This mechanism can be used to provide context for a token, such as a user identifier of the only subject 65 * authorised to use it. Note also that multiple data can be added to the token. This means that upon validation, 66 * not only the same data must be added, but also in the same order. 67 * 68 * @param string $data The data to incorporate into the current token. 69 */ 70 public function addVerificationData($data) 71 { 72 $this->secretSalt .= '|'.$data; 73 } 74 75 76 /** 77 * Calculates a token value for a given offset. 78 * 79 * @param int $offset The offset to use. 80 * @param int|null $time The time stamp to which the offset is relative to. Defaults to the current time. 81 * 82 * @return string The token for the given time and offset. 83 */ 84 private function calculateTokenValue($offset, $time = null) 85 { 86 if ($time === null) { 87 $time = time(); 88 } 89 // a secret salt that should be randomly generated for each installation 90 return hash( 91 $this->algo, 92 $offset.':'.floor(($time - $offset) / ($this->lifetime + $this->skew)).':'.$this->secretSalt 93 ); 94 } 95 96 97 /** 98 * Generates a token that contains an offset and a token value, using the current offset. 99 * 100 * @return string A time-limited token with the offset respect to the beginning of its time slot prepended. 101 */ 102 public function generate() 103 { 104 $time = time(); 105 $current_offset = ($time - $this->skew) % ($this->lifetime + $this->skew); 106 return dechex($current_offset).'-'.$this->calculateTokenValue($current_offset, $time); 107 } 108 109 110 /** 111 * @see generate 112 * @deprecated This method will be removed in SSP 2.0. Use generate() instead. 113 */ 114 public function generate_token() 115 { 116 return $this->generate(); 117 } 118 119 120 /** 121 * Validates a token by calculating the token value for the provided offset and comparing it. 122 * 123 * @param string $token The token to validate. 124 * 125 * @return boolean True if the given token is currently valid, false otherwise. 126 */ 127 public function validate($token) 128 { 129 $splittoken = explode('-', $token); 130 if (count($splittoken) !== 2) { 131 return false; 132 } 133 $offset = intval(hexdec($splittoken[0])); 134 $value = $splittoken[1]; 135 return ($this->calculateTokenValue($offset) === $value); 136 } 137 138 139 /** 140 * @see validate 141 * @deprecated This method will be removed in SSP 2.0. Use validate() instead. 142 */ 143 public function validate_token($token) 144 { 145 return $this->validate($token); 146 } 147} 148