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 | } |