1<?php
2
3declare(strict_types=1);
4
5/*
6 * The MIT License (MIT)
7 *
8 * Copyright (c) 2014-2021 Spomky-Labs
9 *
10 * This software may be modified and distributed under the terms
11 * of the MIT license.  See the LICENSE file for details.
12 */
13
14namespace Webauthn\MetadataService;
15
16use Assert\Assertion;
17use Base64Url\Base64Url;
18use Psr\Http\Client\ClientInterface;
19use Psr\Http\Message\RequestFactoryInterface;
20use function Safe\json_decode;
21use function Safe\sprintf;
22
23class DistantSingleMetadata extends SingleMetadata
24{
25    /**
26     * @var ClientInterface
27     */
28    private $httpClient;
29
30    /**
31     * @var RequestFactoryInterface
32     */
33    private $requestFactory;
34
35    /**
36     * @var array
37     */
38    private $additionalHeaders;
39
40    /**
41     * @var string
42     */
43    private $uri;
44
45    /**
46     * @var bool
47     */
48    private $isBase64Encoded;
49
50    public function __construct(string $uri, bool $isBase64Encoded, ClientInterface $httpClient, RequestFactoryInterface $requestFactory, array $additionalHeaders = [])
51    {
52        parent::__construct($uri, $isBase64Encoded); //Useless
53        $this->uri = $uri;
54        $this->isBase64Encoded = $isBase64Encoded;
55        $this->httpClient = $httpClient;
56        $this->requestFactory = $requestFactory;
57        $this->additionalHeaders = $additionalHeaders;
58    }
59
60    public function getMetadataStatement(): MetadataStatement
61    {
62        $payload = $this->fetch();
63        $json = $this->isBase64Encoded ? Base64Url::decode($payload) : $payload;
64        $data = json_decode($json, true);
65
66        return MetadataStatement::createFromArray($data);
67    }
68
69    private function fetch(): string
70    {
71        $request = $this->requestFactory->createRequest('GET', $this->uri);
72        foreach ($this->additionalHeaders as $k => $v) {
73            $request = $request->withHeader($k, $v);
74        }
75        $response = $this->httpClient->sendRequest($request);
76        Assertion::eq(200, $response->getStatusCode(), sprintf('Unable to contact the server. Response code is %d', $response->getStatusCode()));
77        $content = $response->getBody()->getContents();
78        Assertion::notEmpty($content, 'Unable to contact the server. The response has no content');
79
80        return $content;
81    }
82}
83