1
<?php
2

3
declare(strict_types=1);
4

5
namespace Kreait\Firebase\Auth;
6

7
use Firebase\Auth\Token\Domain\Generator;
8
use GuzzleHttp\ClientInterface;
9
use InvalidArgumentException;
10
use Kreait\Firebase\Exception\Auth\AuthError;
11
use Kreait\Firebase\Exception\AuthApiExceptionConverter;
12
use Kreait\Firebase\Util\JSON;
13
use Kreait\Firebase\Value\Uid;
14
use Lcobucci\JWT\Builder;
15
use Lcobucci\JWT\Parser;
16
use Lcobucci\JWT\Token;
17
use Throwable;
18

19
class CustomTokenViaGoogleIam implements Generator
20
{
21
    /** @var string */
22
    private $clientEmail;
23

24
    /** @var ClientInterface */
25
    private $client;
26

27 12
    public function __construct(string $clientEmail, ClientInterface $client)
28
    {
29 12
        $this->clientEmail = $clientEmail;
30 12
        $this->client = $client;
31
    }
32

33
    /**
34
     * @param Uid|string$uid
35
     * @param array<string, mixed> $claims
36
     */
37 3
    public function createCustomToken($uid, array $claims = [], ?\DateTimeInterface $expiresAt = null): Token
38
    {
39 3
        $now = \time();
40 3
        $expiration = $expiresAt ? $expiresAt->getTimestamp() : $now + (60 * 60);
41

42 3
        $builder = (new Builder())
43 3
            ->withHeader('alg', 'RS256')
44 3
            ->withClaim('uid', (string) $uid)
45 3
            ->issuedBy($this->clientEmail)
46 3
            ->relatedTo($this->clientEmail)
47 3
            ->issuedAt($now)
48 3
            ->expiresAt($expiration)
49 3
            ->permittedFor('https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit');
50

51 3
        if (!empty($claims)) {
52 3
            $builder = $builder->withClaim('claims', $claims);
53
        }
54

55 3
        $token = $builder->getToken();
56

57 3
        $url = 'https://iam.googleapis.com/v1/projects/-/serviceAccounts/'.$this->clientEmail.':signBlob';
58

59
        try {
60 3
            $response = $this->client->request('POST', $url, [
61
                'json' => [
62 3
                    'bytesToSign' => \base64_encode($token->getPayload()),
63
                ],
64
            ]);
65 3
        } catch (Throwable $e) {
66 3
            throw (new AuthApiExceptionConverter())->convertException($e);
67
        }
68

69 3
        $result = JSON::decode((string) $response->getBody(), true);
70

71 3
        if ($base64EncodedSignature = $result['signature'] ?? null) {
72
            try {
73 3
                return (new Parser())->parse(((string) $token).$base64EncodedSignature);
74 0
            } catch (InvalidArgumentException $e) {
75 0
                throw new AuthError('The custom token API returned an unexpected value: '.$e->getMessage(), $e->getCode(), $e);
76
            }
77
        }
78

79 0
        throw new AuthError('Unable to create custom token.');
80
    }
81
}

Read our documentation on viewing source code .

Loading