Expanded default authorization view callback, default form template

This commit is contained in:
Barnaby Walters 2021-06-07 01:39:33 +02:00
parent 7442da1ae9
commit 4d3a025296
2 changed files with 119 additions and 9 deletions

View File

@ -59,9 +59,36 @@ class Server {
'csrfKey' => self::DEFAULT_CSRF_KEY,
'logger' => null,
'callbacks' => [
self::CUSTOMIZE_AUTHORIZATION_CODE => function (array $code) { return $code; }, // Default to no-op.
self::CUSTOMIZE_AUTHORIZATION_CODE => function (array $code, ServerRequestInterface $request) {
// Configure the access code based on the authorization form parameters submitted in $request;
// TODO: that, based on the default authorization form.
return $code;
},
self::SHOW_AUTHORIZATION_PAGE => function (ServerRequestInterface $request, array $authenticationResult, string $authenticationRedirect, ?array $clientHApp) {
// TODO: Put the default implementation here.
// Default implementation: show an authorization page. List all requested scopes, as this default
// function has now way of knowing which scopes are supported by the consumer.
$scopes = [];
foreach(explode(' ', $request->getQueryParams()['scope'] ?? '') as $s) {
$scopes[$s] = null; // Ideally there would be a description of the scope here, we dont have one though.
}
$templatePath = __DIR__ . '/templates/default_authorization_page.html.php';
$hApp = [
'name' => M\getProp($clientHApp, 'name'),
'url' => M\getProp($clientHApp, 'url'),
'photo' => M\getProp($clientHApp, 'photo')
];
return new Response(200, ['content-type' => 'text/html'], renderTemplate($templatePath, [
'scopes' => $scopes,
'user' => $authenticationResult,
'formAction' => $authenticationRedirect,
'request' => $request,
'clientHApp' => $hApp,
'clientId' => $request->getQueryParams()['client_id'],
'clientRedirectUri' => $request->getQueryParams()['redirect_uri'],
'csrfFormElement' => '<input type="hidden" name="' . htmlentities($this->csrfKey) . '" value="' . htmlentities($request->getAttribute($this->csrfKey)) . '" />'
]));
},
self::HANDLE_NON_INDIEAUTH_REQUEST => function (ServerRequestInterface $request) { return null; }, // Default to no-op.
],

View File

@ -1,24 +1,107 @@
<?php
/** @var string $authenticationRedirect The URL to POST to to authorize the app, or to set as the redirect URL for a logout action if the user wants to continue as a different user. */
/** @var string $formAction The URL to POST to to authorize the app, or to set as the redirect URL for a logout action if the user wants to continue as a different user. */
/** @var Psr\Http\Message\ServerRequestInterface $request */
/** @var array|null $clientHApp */
/** @var array $me */
/** @var array $user */
/** @var array $scopes */
/** @var string $clientId */
/** @var string $clientRedirectUri */
/** @var string $csrfFormElement A pre-rendered CSRF form element which must be output inside the authorization form. */
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>IndieAuth Authorize</title>
<style>
</style>
</head>
<body>
<form method="post" action="<?= $authenticationRedirect ?>">
<?= $csrfFormElement ?>
<?php if (!is_null($clientHApp)): ?>
<h1>Authorize <?= htmlentities($clientHApp['name']) ?> (<span class="inline-url"><?= $clientId ?></span>)</h1>
<h1>Authorize</h1>
<div class="client-app-details">
<?php if (!is_null($clientHApp['photo'])): ?>
<img class="client-app-photo" src="<?= htmlentities($clientHApp['photo']) ?>" alt="" />
<?php else: ?>
<div class="client-app-photo client-app-photo-placeholder"></div>
<?php endif ?>
<!-- TODO -->
<p class="client-app-name"><?= htmlentities($clientHApp['name']) ?></p>
<p class="client-app-url"><?= htmlentities($clientHApp['url']) ?></p>
</div>
<?php else: ?>
<h1>Authorize <span class="inline-url"><?= $clientId ?></span></h1>
<?php endif ?>
<div class="user-details">
<?php if (!is_null($user['profile'])): ?>
<?php if (!is_null($user['profile']['photo'])): ?>
<img class="user-photo" src="<?= htmlentities($user['profile']['photo']) ?>" alt="" />
<?php else: ?>
<div class="user-photo user-photo-placeholder"></div>
<?php endif ?>
<?php if (!is_null($user['profile']['name'])): ?>
<p class="user-name"><?= htmlentities($user['profile']['name']) ?></p>
<?php endif ?>
<p class="user-me-url"><?= htmlentities($user['me']) ?></p>
<?php else: ?>
<p>User: <span class="inline-url"><?= htmlentities($user['me']) ?></span></p>
<?php endif ?>
<!-- Example! If your server supports multiple users, add a form like this to allow the currently
logged-in user to log out and re-authenticate. In order for the IndieAuth request to proceed
seamlessly, you MUST redirect to $formAction after re-authenticating. For security, all
of the requests involved in the re-authentication SHOULD be CSRF-protected (but youre already
CSRF-protecting your authentication flow… right?)
<form class="logout-form" action="/logout" method="post">
<input type="hidden" name="your_csrf_name" value="your_csrf_token" />
<input type="hidden" name="your_logout_redirect_parameter" value="<?= htmlentities($formAction) ?>" />
<p>Want to log into <span class="inline-url"><?= $clientId ?></span> as another user? <button type="submit">Log out and continue</button></p>
</form>
-->
</div>
<form method="post" action="<?= $formAction ?>">
<?= $csrfFormElement ?>
<div class="scope-section">
<h2>Scope</h2>
<?php if(!empty($scopes)): ?>
<p>The app has requested the following scopes. You may choose which to grant it.</p>
<ul class="scope-list">
<?php foreach ($scopes as $scope => $description): ?>
<li class="scope-list-item">
<label>
<input type="checkbox" name="taproot_indieauth_server_scope[]" value="<?= htmlentities($scope) ?>" />
<p class="scope-name"><?= htmlentities($scope) ?></p>
<?php if (!empty($description)): ?>
<p class="scope-description"><?= htmlentities($description) ?></p>
<?php endif ?>
</label>
</li>
<?php endforeach ?>
</ul>
<?php else: ?>
<p>The app has requested no scopes, and will only be able to confirm that youre logged in as <span class="inline-url"><?= htmlentities($user['me']) ?></span>.</p>
<?php endif ?>
</div>
<div class="submit-section">
<p>After approving, you will be redirected to <span class="inline-url"><?= htmlentities($clientRedirectUri) ?></span>.</p>
<p>
<a class="cancel-link" href="<?= htmlentities($clientId) ?>">Cancel (back to app)</a>
<button type="submit" name="taproot_indieauth_action" value="approve">Authorize</button>
</p>
</div>
</form>
</body>
</html>