class wfJWT {
private $claims;
const JWT_TTL = 600;
const ISSUER = 600;
public static function extractTokenContents($token) {
if (!is_string($token)) {
throw new InvalidArgumentException('Token is not a string. ' . gettype($token) . ' given.');
}
// Verify the token matches the JWT format.
if (!preg_match('/^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?$/', $token)) {
throw new wfJWTException('Invalid token format.');
}
list($header, $body, $signature) = explode('.', $token);
// Test that the token is valid and not expired.
$decodedHeader = base64_decode($header);
if (!(is_string($decodedHeader) && $decodedHeader)) {
throw new wfJWTException('Token header is invalid.');
}
$header = json_decode($decodedHeader, true);
if (!is_array($header)) {
throw new wfJWTException('Token header is invalid.');
}
$decodedBody = base64_decode($body);
if (!(is_string($decodedBody) && $decodedBody)) {
throw new wfJWTException('Token body is invalid.');
}
$body = json_decode($decodedBody, true);
if (!is_array($body)) {
throw new wfJWTException('Token body is invalid.');
}
return array(
'header' => $header,
'body' => $body,
'signature' => $signature,
);
}
/**
* @param mixed $subject
*/
public function __construct($subject = null) {
$this->claims = $this->getClaimDefaults();
$this->claims['sub'] = $subject;
}
/**
* @return string
*/
public function encode() {
$header = $this->encodeString($this->buildHeader());
$body = $this->encodeString($this->buildBody());
return sprintf('%s.%s.%s', $header, $body,
$this->encodeString($this->sign(sprintf('%s.%s', $header, $body))));
}
/**
* @param string $token
* @return array
* @throws wfJWTException|InvalidArgumentException
*/
public function decode($token) {
if (!is_string($token)) {
throw new InvalidArgumentException('Token is not a string. ' . gettype($token) . ' given.');
}
// Verify the token matches the JWT format.
if (!preg_match('/^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?$/', $token)) {
throw new wfJWTException('Invalid token format.');
}
list($header, $body, $signature) = explode('.', $token);
// Verify signature matches the supplied payload.
if (!$this->verifySignature($this->decodeString($signature), sprintf('%s.%s', $header, $body))) {
throw new wfJWTException('Invalid signature.');
}
// Test that the token is valid and not expired.
$decodedHeader = base64_decode($header);
if (!(is_string($decodedHeader) && $decodedHeader)) {
throw new wfJWTException('Token header is invalid.');
}
$header = json_decode($decodedHeader, true);
if (!(
is_array($header) &&
array_key_exists('alg', $header) &&
$header['alg'] === 'HS256' &&
$header['typ'] === 'JWT'
)) {
throw new wfJWTException('Token header is invalid.');
}
$decodedBody = base64_decode($body);
if (!(is_string($decodedBody) && $decodedBody)) {
throw new wfJWTException('Token body is invalid.');
}
$body = json_decode($decodedBody, true);
if (!(
is_array($body) &&
// Check the token not before now timestamp.
array_key_exists('nbf', $body) &&
is_numeric($body['nbf']) &&
$body['nbf'] <= time() &&
// Check the token is not expired.
array_key_exists('exp', $body) &&
is_numeric($body['exp']) &&
$body['exp'] >= time() &&
// Check the issuer and audience is ours.
$body['iss'] === 'Wordfence ' . WORDFENCE_VERSION &&
$body['aud'] === 'Wordfence Central'
)) {
throw new wfJWTException('Token is invalid or expired.');
}
return array(
'header' => $header,
'body' => $body,
);
}
/**
* @param string $string
* @return string
*/
public function sign($string) {
$salt = wp_salt('auth');
return hash_hmac('sha256', $string, $salt, true);
}
/**
* @param string $signature
* @param string $message
* @return bool
*/
public function verifySignature($signature, $message) {
return hash_equals($this->sign($message), $signature);
}
/**
* @return string
*/
public function __toString() {
return $this->encode();
}
/**
* @param string $data
* @return string
*/
public function encodeString($data) {
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
/**
* @param string $data
* @return bool|string
*/
public function decodeString($data) {
return base64_decode(strtr($data, '-_', '+/'));
}
/**
* @return mixed|string
*/
protected function buildHeader() {
return '{"alg":"HS256","typ":"JWT"}';
}
/**
* @return mixed|string
*/
protected function buildBody() {
return json_encode($this->getClaims());
}
/**
* @return array
*/
protected function getClaimDefaults() {
$now = time();
return array(
'iss' => 'Wordfence ' . WORDFENCE_VERSION,
'aud' => 'Wordfence Central',
'nbf' => $now,
'iat' => $now,
'exp' => $now + self::JWT_TTL,
);
}
/**
* @param array $claims
*/
public function addClaims($claims) {
if (!is_array($claims)) {
throw new InvalidArgumentException(__METHOD__ . ' expects argument 1 to be array.');
}
$this->setClaims(array_merge($this->getClaims(), $claims));
}
/**
* @return array
*/
public function getClaims() {
return $this->claims;
}
/**
* @param array $claims
*/
public function setClaims($claims) {
$this->claims = $claims;
}
}
class wfJWTException extends Exception {
}
Brickbat: Not Good Enough To Give Away | Right Tactics
Brickbat: Not Good Enough To Give Away
In Scotland, Nigel Carter collected 500 bicycles to send to Sudan, for people who need access to cheap transportation. But the Scottish Environment Protection Agency blocked the shipment after an inspector deemed the bikes unfit for use because some of them needed repairs. Carter said the bikes had only minor damage such as rust, broken brake cables, and chains that needed to be oiled. He also said that the charity he is working with in Sudan is aware of their condition. If Carter can’t ship the bikes to Sudan, he said he may have to scrap them.
The post Brickbat: Not Good Enough To Give Away appeared first on Reason.com .