<commit_before><?php
declare(strict_types=1);

namespace Genkgo\Push\Apn;

use Apple\ApnPush\Protocol\Http\Authenticator\AuthenticatorInterface;
use Apple\ApnPush\Protocol\Http\Request;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Ecdsa\Sha256;
use Lcobucci\JWT\Signer\Key;

final class JwtAuthenticator implements AuthenticatorInterface
{
    /**
     * @var string
     */
    private $token;

    /**
     * @var string
     */
    private $teamId;

    /**
     * @var string
     */
    private $keyId;

    /**
     * @param string $token
     * @param string $keyId
     * @param string $teamId
     */
    public function __construct(string $token, string $keyId, string $teamId)
    {
        $this->token = $token;
        $this->teamId = $teamId;
        $this->keyId = $keyId;
    }

    /**
     * Authenticate request
     *
     * @param Request $request
     *
     * @return Request
     */
    public function authenticate(Request $request): Request
    {
        $now = \time();
        $expiration = $now + (60 * 60);
        $builder = (new Builder())
            ->issuedBy($this->teamId)
            ->issuedAt($now)
            ->expiresAt($expiration)
            ->withClaim('kid', $this->keyId);

        if (!\file_exists($this->token)) {
            throw new \UnexpectedValueException('Cannot find token ' . $this->token . ', invalid path');
        }

        $keyContent = \file_get_contents($this->token);
        if ($keyContent === false) {
            throw new \UnexpectedValueException('Cannot fetch token content from ' . $this->token . ', file not readable?');
        }

        $token = $builder->getToken(new Sha256(), new Key($keyContent));

        return $request->withHeader('authorization', \sprintf('bearer %s', (string)$token));
    }
}<commit_msg>key id is a header field<commit_after><?php
declare(strict_types=1);

namespace Genkgo\Push\Apn;

use Apple\ApnPush\Protocol\Http\Authenticator\AuthenticatorInterface;
use Apple\ApnPush\Protocol\Http\Request;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Ecdsa\Sha256;
use Lcobucci\JWT\Signer\Key;

final class JwtAuthenticator implements AuthenticatorInterface
{
    /**
     * @var string
     */
    private $token;

    /**
     * @var string
     */
    private $keyId;

    /**
     * @var string
     */
    private $teamId;

    /**
     * @param string $token
     * @param string $keyId
     * @param string $teamId
     */
    public function __construct(string $token, string $keyId, string $teamId)
    {
        $this->token = $token;
        $this->keyId = $keyId;
        $this->teamId = $teamId;
    }

    /**
     * Authenticate request
     *
     * @param Request $request
     *
     * @return Request
     */
    public function authenticate(Request $request): Request
    {
        $now = \time();
        $expiration = $now + (60 * 60);
        $builder = (new Builder())
            ->issuedBy($this->teamId)
            ->issuedAt($now)
            ->expiresAt($expiration)
            ->withHeader('kid', $this->keyId);

        if (!\file_exists($this->token)) {
            throw new \UnexpectedValueException('Cannot find token ' . $this->token . ', invalid path');
        }

        $keyContent = \file_get_contents($this->token);
        if ($keyContent === false) {
            throw new \UnexpectedValueException('Cannot fetch token content from ' . $this->token . ', file not readable?');
        }

        $token = $builder->getToken(new Sha256(), new Key($keyContent));

        return $request->withHeader('Authorization', \sprintf('Bearer %s', (string)$token));
    }
}
{'fraction_non_alphanumeric': 0.14483139856274185, 'fraction_numerical': 0.006080707573244887, 'mean_word_length': 2.3141025641025643, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3075060', 'n_tokens_mistral': 1152, 'n_tokens_neox': 1106, 'n_words': 237}