Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
100.00% |
1 / 1 |
|
100.00% |
4 / 4 |
CRAP | |
100.00% |
26 / 26 |
DefaultAuthorizationForm | |
100.00% |
1 / 1 |
|
100.00% |
4 / 4 |
6 | |
100.00% |
26 / 26 |
__construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
4 / 4 |
|||
showForm | |
100.00% |
1 / 1 |
3 | |
100.00% |
17 / 17 |
|||
transformAuthorizationCode | |
100.00% |
1 / 1 |
1 | |
100.00% |
3 / 3 |
|||
setLogger | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
1 | <?php declare(strict_types=1); |
2 | |
3 | namespace Taproot\IndieAuth\Callback; |
4 | |
5 | use BarnabyWalters\Mf2 as M; |
6 | use Psr\Http\Message\ServerRequestInterface; |
7 | use Nyholm\Psr7\Response; |
8 | use Psr\Http\Message\ResponseInterface; |
9 | use Psr\Log\LoggerAwareInterface; |
10 | use Psr\Log\LoggerInterface; |
11 | use Psr\Log\NullLogger; |
12 | |
13 | use function Taproot\IndieAuth\renderTemplate; |
14 | |
15 | /** |
16 | * Default Authorization Form |
17 | * |
18 | * This implementation of `AuthorizationFormInterface` is used by `Server` if the user doesn’t |
19 | * provide one of their own. It presents the user with a simple consent screen, showing any |
20 | * available details about the client app, and allowing the user to grant any requested scopes. |
21 | * |
22 | * When the form is submitted, any granted scopes are then added to the authorization code data. |
23 | * |
24 | * You can customise the authorization template used by passing a path to your own template to |
25 | * the constructor. Refer to the default template `/templates/default_authorization_page.html.php` |
26 | * as a starting point. |
27 | * |
28 | * If you want to add additional form controls (e.g. configurable token lifetimes), as well as |
29 | * making a new template, you’ll need to make a subclass which overrides `transformAuthorizationCode()` |
30 | * to additionally handle your new form data. |
31 | * |
32 | * For any more involved customisation (for example using a templating library of your choice), it |
33 | * may make sense to create your own implementation of `AuthorizationFormInterface`. |
34 | */ |
35 | class DefaultAuthorizationForm implements AuthorizationFormInterface, LoggerAwareInterface { |
36 | public string $csrfKey; |
37 | |
38 | public string $formTemplatePath; |
39 | |
40 | public LoggerInterface $logger; |
41 | |
42 | /** |
43 | * Constructor |
44 | * |
45 | * @param string|null $formTemplatePath The path to a custom template. Uses the default if null. |
46 | * @param string|null $csrfKey The key used to retrieve a CSRF token from the request attributes, and as its form data name. Uses the default defined in Server if null. Only change this if you’re using a custom CSRF middleware. |
47 | * @param LoggerInterface|null $logger A logger. |
48 | */ |
49 | public function __construct(?string $formTemplatePath=null, ?string $csrfKey=null, ?LoggerInterface $logger=null) { |
50 | $this->formTemplatePath = $formTemplatePath ?? __DIR__ . '/../../templates/default_authorization_page.html.php'; |
51 | $this->csrfKey = $csrfKey ?? \Taproot\IndieAuth\Server::DEFAULT_CSRF_KEY; |
52 | $this->logger = $logger ?? new NullLogger; |
53 | } |
54 | |
55 | public function showForm(ServerRequestInterface $request, array $authenticationResult, string $formAction, ?array $clientHApp): ResponseInterface { |
56 | // Show an authorization page. List all requested scopes, as this default |
57 | // function has now way of knowing which scopes are supported by the consumer. |
58 | $scopes = []; |
59 | foreach(explode(' ', $request->getQueryParams()['scope'] ?? '') as $s) { |
60 | $scopes[$s] = null; // Ideally there would be a description of the scope here, we don’t have one though. |
61 | } |
62 | |
63 | if (is_null($clientHApp)) { |
64 | $clientHApp = [ |
65 | 'type' => ['h-app'], |
66 | 'properties' => [] |
67 | ]; |
68 | } |
69 | |
70 | $hApp = [ |
71 | 'name' => M\getProp($clientHApp, 'name'), |
72 | 'url' => M\getProp($clientHApp, 'url'), |
73 | 'photo' => M\getProp($clientHApp, 'photo') |
74 | ]; |
75 | |
76 | return new Response(200, ['content-type' => 'text/html'], renderTemplate($this->formTemplatePath, [ |
77 | 'scopes' => $scopes, |
78 | 'user' => $authenticationResult, |
79 | 'formAction' => $formAction, |
80 | 'request' => $request, |
81 | 'clientHApp' => $hApp, |
82 | 'clientId' => $request->getQueryParams()['client_id'], |
83 | 'clientRedirectUri' => $request->getQueryParams()['redirect_uri'], |
84 | 'csrfFormElement' => '<input type="hidden" name="' . htmlentities($this->csrfKey) . '" value="' . htmlentities($request->getAttribute($this->csrfKey)) . '" />' |
85 | ])); |
86 | } |
87 | |
88 | public function transformAuthorizationCode(ServerRequestInterface $request, array $code): array { |
89 | // Add any granted scopes from the form to the code. |
90 | $grantedScopes = $request->getParsedBody()['taproot_indieauth_server_scope[]'] ?? []; |
91 | |
92 | // This default implementation naievely accepts any scopes it receives from the form. |
93 | // You may wish to perform some sort of validation. |
94 | $code['scope'] = join(' ', $grantedScopes); |
95 | |
96 | // You may wish to additionally make any other necessary changes to the the code based on |
97 | // the form submission, e.g. if the user set a custom token lifetime, or wanted extra data |
98 | // stored on the token to affect how it behaves. |
99 | return $code; |
100 | } |
101 | |
102 | public function setLogger(LoggerInterface $logger) { |
103 | $this->logger = $logger; |
104 | } |
105 | } |