This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
indieauth/docs/coverage/Server.php.html
Barnaby Walters 01a15f0b46 Made SingleUserAuth callback set a cookie
So that auth data is preserved across multiple requests.
2021-06-18 16:11:49 +02:00

1086 lines
778 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Code Coverage for /Users/barnabywalters/Documents/Programming/taproot/indieauth/src/Server.php</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="phpunit_css/bootstrap.min.css" rel="stylesheet" type="text/css">
<link href="phpunit_css/octicons.css" rel="stylesheet" type="text/css">
<link href="phpunit_css/style.css" rel="stylesheet" type="text/css">
<link href="phpunit_css/custom.css" rel="stylesheet" type="text/css">
</head>
<body>
<header>
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="index.html">/Users/barnabywalters/Documents/Programming/taproot/indieauth/src</a></li>
<li class="breadcrumb-item active">Server.php</li>
</ol>
</nav>
</div>
</div>
</div>
</header>
<div class="container-fluid">
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<td>&nbsp;</td>
<td colspan="10"><div align="center"><strong>Code Coverage</strong></div></td>
</tr>
<tr>
<td>&nbsp;</td>
<td colspan="3"><div align="center"><strong>Classes and Traits</strong></div></td>
<td colspan="4"><div align="center"><strong>Functions and Methods</strong></div></td>
<td colspan="3"><div align="center"><strong>Lines</strong></div></td>
</tr>
</thead>
<tbody>
<tr>
<td class="danger">Total</td>
<td class="danger big"> <div class="progress">
<div class="progress-bar bg-danger" role="progressbar" aria-valuenow="0.00" aria-valuemin="0" aria-valuemax="100" style="width: 0.00%">
<span class="sr-only">0.00% covered (danger)</span>
</div>
</div>
</td>
<td class="danger small"><div align="right">0.00%</div></td>
<td class="danger small"><div align="right">0&nbsp;/&nbsp;1</div></td>
<td class="warning big"> <div class="progress">
<div class="progress-bar bg-warning" role="progressbar" aria-valuenow="80.00" aria-valuemin="0" aria-valuemax="100" style="width: 80.00%">
<span class="sr-only">80.00% covered (warning)</span>
</div>
</div>
</td>
<td class="warning small"><div align="right">80.00%</div></td>
<td class="warning small"><div align="right">4&nbsp;/&nbsp;5</div></td>
<td class="warning small"><abbr title="Change Risk Anti-Patterns (CRAP) Index">CRAP</abbr></td>
<td class="success big"> <div class="progress">
<div class="progress-bar bg-success" role="progressbar" aria-valuenow="96.69" aria-valuemin="0" aria-valuemax="100" style="width: 96.69%">
<span class="sr-only">96.69% covered (success)</span>
</div>
</div>
</td>
<td class="success small"><div align="right">96.69%</div></td>
<td class="success small"><div align="right">263&nbsp;/&nbsp;272</div></td>
</tr>
<tr>
<td class="danger"><abbr title="Taproot\IndieAuth\Server">Server</abbr></td>
<td class="danger big"> <div class="progress">
<div class="progress-bar bg-danger" role="progressbar" aria-valuenow="0.00" aria-valuemin="0" aria-valuemax="100" style="width: 0.00%">
<span class="sr-only">0.00% covered (danger)</span>
</div>
</div>
</td>
<td class="danger small"><div align="right">0.00%</div></td>
<td class="danger small"><div align="right">0&nbsp;/&nbsp;1</div></td>
<td class="warning big"> <div class="progress">
<div class="progress-bar bg-warning" role="progressbar" aria-valuenow="80.00" aria-valuemin="0" aria-valuemax="100" style="width: 80.00%">
<span class="sr-only">80.00% covered (warning)</span>
</div>
</div>
</td>
<td class="warning small"><div align="right">80.00%</div></td>
<td class="warning small"><div align="right">4&nbsp;/&nbsp;5</div></td>
<td class="warning small">105</td>
<td class="success big"> <div class="progress">
<div class="progress-bar bg-success" role="progressbar" aria-valuenow="96.69" aria-valuemin="0" aria-valuemax="100" style="width: 96.69%">
<span class="sr-only">96.69% covered (success)</span>
</div>
</div>
</td>
<td class="success small"><div align="right">96.69%</div></td>
<td class="success small"><div align="right">263&nbsp;/&nbsp;272</div></td>
</tr>
<tr>
<td class="success" colspan="4">&nbsp;<a href="#201"><abbr title="__construct(array $config)">__construct</abbr></a></td>
<td class="success big"> <div class="progress">
<div class="progress-bar bg-success" role="progressbar" aria-valuenow="100.00" aria-valuemin="0" aria-valuemax="100" style="width: 100.00%">
<span class="sr-only">100.00% covered (success)</span>
</div>
</div>
</td>
<td class="success small"><div align="right">100.00%</div></td>
<td class="success small"><div align="right">1&nbsp;/&nbsp;1</div></td>
<td class="success small">17</td>
<td class="success big"> <div class="progress">
<div class="progress-bar bg-success" role="progressbar" aria-valuenow="100.00" aria-valuemin="0" aria-valuemax="100" style="width: 100.00%">
<span class="sr-only">100.00% covered (success)</span>
</div>
</div>
</td>
<td class="success small"><div align="right">100.00%</div></td>
<td class="success small"><div align="right">46&nbsp;/&nbsp;46</div></td>
</tr>
<tr>
<td class="success" colspan="4">&nbsp;<a href="#299"><abbr title="getTokenStorage(): Taproot\IndieAuth\Storage\TokenStorageInterface">getTokenStorage</abbr></a></td>
<td class="success big"> <div class="progress">
<div class="progress-bar bg-success" role="progressbar" aria-valuenow="100.00" aria-valuemin="0" aria-valuemax="100" style="width: 100.00%">
<span class="sr-only">100.00% covered (success)</span>
</div>
</div>
</td>
<td class="success small"><div align="right">100.00%</div></td>
<td class="success small"><div align="right">1&nbsp;/&nbsp;1</div></td>
<td class="success small">1</td>
<td class="success big"> <div class="progress">
<div class="progress-bar bg-success" role="progressbar" aria-valuenow="100.00" aria-valuemin="0" aria-valuemax="100" style="width: 100.00%">
<span class="sr-only">100.00% covered (success)</span>
</div>
</div>
</td>
<td class="success small"><div align="right">100.00%</div></td>
<td class="success small"><div align="right">1&nbsp;/&nbsp;1</div></td>
</tr>
<tr>
<td class="danger" colspan="4">&nbsp;<a href="#338"><abbr title="handleAuthorizationEndpointRequest(Psr\Http\Message\ServerRequestInterface $request): Psr\Http\Message\ResponseInterface">handleAuthorizationEndpointRequest</abbr></a></td>
<td class="danger big"> <div class="progress">
<div class="progress-bar bg-danger" role="progressbar" aria-valuenow="0.00" aria-valuemin="0" aria-valuemax="100" style="width: 0.00%">
<span class="sr-only">0.00% covered (danger)</span>
</div>
</div>
</td>
<td class="danger small"><div align="right">0.00%</div></td>
<td class="danger small"><div align="right">0&nbsp;/&nbsp;1</div></td>
<td class="danger small">67.70</td>
<td class="success big"> <div class="progress">
<div class="progress-bar bg-success" role="progressbar" aria-valuenow="94.61" aria-valuemin="0" aria-valuemax="100" style="width: 94.61%">
<span class="sr-only">94.61% covered (success)</span>
</div>
</div>
</td>
<td class="success small"><div align="right">94.61%</div></td>
<td class="success small"><div align="right">158&nbsp;/&nbsp;167</div></td>
</tr>
<tr>
<td class="success" colspan="4">&nbsp;<a href="#720"><abbr title="handleTokenEndpointRequest(Psr\Http\Message\ServerRequestInterface $request): Psr\Http\Message\ResponseInterface">handleTokenEndpointRequest</abbr></a></td>
<td class="success big"> <div class="progress">
<div class="progress-bar bg-success" role="progressbar" aria-valuenow="100.00" aria-valuemin="0" aria-valuemax="100" style="width: 100.00%">
<span class="sr-only">100.00% covered (success)</span>
</div>
</div>
</td>
<td class="success small"><div align="right">100.00%</div></td>
<td class="success small"><div align="right">1&nbsp;/&nbsp;1</div></td>
<td class="success small">17</td>
<td class="success big"> <div class="progress">
<div class="progress-bar bg-success" role="progressbar" aria-valuenow="100.00" aria-valuemin="0" aria-valuemax="100" style="width: 100.00%">
<span class="sr-only">100.00% covered (success)</span>
</div>
</div>
</td>
<td class="success small"><div align="right">100.00%</div></td>
<td class="success small"><div align="right">47&nbsp;/&nbsp;47</div></td>
</tr>
<tr>
<td class="success" colspan="4">&nbsp;<a href="#824"><abbr title="handleException(Taproot\IndieAuth\IndieAuthException $exception): Psr\Http\Message\ResponseInterface">handleException</abbr></a></td>
<td class="success big"> <div class="progress">
<div class="progress-bar bg-success" role="progressbar" aria-valuenow="100.00" aria-valuemin="0" aria-valuemax="100" style="width: 100.00%">
<span class="sr-only">100.00% covered (success)</span>
</div>
</div>
</td>
<td class="success small"><div align="right">100.00%</div></td>
<td class="success small"><div align="right">1&nbsp;/&nbsp;1</div></td>
<td class="success small">3</td>
<td class="success big"> <div class="progress">
<div class="progress-bar bg-success" role="progressbar" aria-valuenow="100.00" aria-valuemin="0" aria-valuemax="100" style="width: 100.00%">
<span class="sr-only">100.00% covered (success)</span>
</div>
</div>
</td>
<td class="success small"><div align="right">100.00%</div></td>
<td class="success small"><div align="right">11&nbsp;/&nbsp;11</div></td>
</tr>
</tbody>
</table>
</div>
<table id="code" class="table table-borderless table-condensed">
<tbody>
<tr class=" d-flex"><td class="col-1 text-right"><a id="1" href="#1">1</a></td><td class="col-11 codeLine"><span class="default">&lt;?php&nbsp;</span><span class="keyword">declare</span><span class="keyword">(</span><span class="default">strict_types</span><span class="keyword">=</span><span class="default">1</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="2" href="#2">2</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="3" href="#3">3</a></td><td class="col-11 codeLine"><span class="keyword">namespace</span><span class="default">&nbsp;</span><span class="default">Taproot</span><span class="default">\</span><span class="default">IndieAuth</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="4" href="#4">4</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="5" href="#5">5</a></td><td class="col-11 codeLine"><span class="keyword">use</span><span class="default">&nbsp;</span><span class="default">BadMethodCallException</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="6" href="#6">6</a></td><td class="col-11 codeLine"><span class="keyword">use</span><span class="default">&nbsp;</span><span class="default">BarnabyWalters</span><span class="default">\</span><span class="default">Mf2</span><span class="default">&nbsp;</span><span class="keyword">as</span><span class="default">&nbsp;</span><span class="default">M</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="7" href="#7">7</a></td><td class="col-11 codeLine"><span class="keyword">use</span><span class="default">&nbsp;</span><span class="default">Exception</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="8" href="#8">8</a></td><td class="col-11 codeLine"><span class="keyword">use</span><span class="default">&nbsp;</span><span class="default">GuzzleHttp</span><span class="default">\</span><span class="default">Psr7</span><span class="default">\</span><span class="default">Header</span><span class="default">&nbsp;</span><span class="keyword">as</span><span class="default">&nbsp;</span><span class="default">HeaderParser</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="9" href="#9">9</a></td><td class="col-11 codeLine"><span class="keyword">use</span><span class="default">&nbsp;</span><span class="default">IndieAuth</span><span class="default">\</span><span class="default">Client</span><span class="default">&nbsp;</span><span class="keyword">as</span><span class="default">&nbsp;</span><span class="default">IndieAuthClient</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="10" href="#10">10</a></td><td class="col-11 codeLine"><span class="keyword">use</span><span class="default">&nbsp;</span><span class="default">Mf2</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="11" href="#11">11</a></td><td class="col-11 codeLine"><span class="keyword">use</span><span class="default">&nbsp;</span><span class="default">Nyholm</span><span class="default">\</span><span class="default">Psr7</span><span class="default">\</span><span class="default">Response</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="12" href="#12">12</a></td><td class="col-11 codeLine"><span class="keyword">use</span><span class="default">&nbsp;</span><span class="default">PDO</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="13" href="#13">13</a></td><td class="col-11 codeLine"><span class="keyword">use</span><span class="default">&nbsp;</span><span class="default">Psr</span><span class="default">\</span><span class="default">Http</span><span class="default">\</span><span class="default">Client</span><span class="default">\</span><span class="default">ClientExceptionInterface</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="14" href="#14">14</a></td><td class="col-11 codeLine"><span class="keyword">use</span><span class="default">&nbsp;</span><span class="default">Psr</span><span class="default">\</span><span class="default">Http</span><span class="default">\</span><span class="default">Client</span><span class="default">\</span><span class="default">NetworkExceptionInterface</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="15" href="#15">15</a></td><td class="col-11 codeLine"><span class="keyword">use</span><span class="default">&nbsp;</span><span class="default">Psr</span><span class="default">\</span><span class="default">Http</span><span class="default">\</span><span class="default">Client</span><span class="default">\</span><span class="default">RequestExceptionInterface</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="16" href="#16">16</a></td><td class="col-11 codeLine"><span class="keyword">use</span><span class="default">&nbsp;</span><span class="default">Psr</span><span class="default">\</span><span class="default">Http</span><span class="default">\</span><span class="default">Message</span><span class="default">\</span><span class="default">ResponseInterface</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="17" href="#17">17</a></td><td class="col-11 codeLine"><span class="keyword">use</span><span class="default">&nbsp;</span><span class="default">Psr</span><span class="default">\</span><span class="default">Http</span><span class="default">\</span><span class="default">Message</span><span class="default">\</span><span class="default">ServerRequestInterface</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="18" href="#18">18</a></td><td class="col-11 codeLine"><span class="keyword">use</span><span class="default">&nbsp;</span><span class="default">Psr</span><span class="default">\</span><span class="default">Http</span><span class="default">\</span><span class="default">Server</span><span class="default">\</span><span class="default">MiddlewareInterface</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="19" href="#19">19</a></td><td class="col-11 codeLine"><span class="keyword">use</span><span class="default">&nbsp;</span><span class="default">Psr</span><span class="default">\</span><span class="default">Log</span><span class="default">\</span><span class="default">LoggerInterface</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="20" href="#20">20</a></td><td class="col-11 codeLine"><span class="keyword">use</span><span class="default">&nbsp;</span><span class="default">Psr</span><span class="default">\</span><span class="default">Log</span><span class="default">\</span><span class="default">NullLogger</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="21" href="#21">21</a></td><td class="col-11 codeLine"><span class="keyword">use</span><span class="default">&nbsp;</span><span class="default">Taproot</span><span class="default">\</span><span class="default">IndieAuth</span><span class="default">\</span><span class="default">Callback</span><span class="default">\</span><span class="default">AuthorizationFormInterface</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="22" href="#22">22</a></td><td class="col-11 codeLine"><span class="keyword">use</span><span class="default">&nbsp;</span><span class="default">Taproot</span><span class="default">\</span><span class="default">IndieAuth</span><span class="default">\</span><span class="default">Callback</span><span class="default">\</span><span class="default">DefaultAuthorizationForm</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="23" href="#23">23</a></td><td class="col-11 codeLine"><span class="keyword">use</span><span class="default">&nbsp;</span><span class="default">Taproot</span><span class="default">\</span><span class="default">IndieAuth</span><span class="default">\</span><span class="default">Storage</span><span class="default">\</span><span class="default">TokenStorageInterface</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="24" href="#24">24</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="25" href="#25">25</a></td><td class="col-11 codeLine"><span class="comment">/**</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="26" href="#26">26</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;IndieAuth&nbsp;Server</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="27" href="#27">27</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="28" href="#28">28</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;A&nbsp;PSR-7-compatible&nbsp;implementation&nbsp;of&nbsp;the&nbsp;request-handling&nbsp;logic&nbsp;for&nbsp;IndieAuth&nbsp;authorization&nbsp;endpoints</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="29" href="#29">29</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;and&nbsp;token&nbsp;endpoints.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="30" href="#30">30</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="31" href="#31">31</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;Typical&nbsp;minimal&nbsp;usage&nbsp;looks&nbsp;something&nbsp;like&nbsp;this:</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="32" href="#32">32</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="33" href="#33">33</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Somewhere&nbsp;in&nbsp;your&nbsp;app&nbsp;set-up&nbsp;code:</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="34" href="#34">34</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$server&nbsp;=&nbsp;new&nbsp;Taproot\IndieAuth\Server([</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="35" href="#35">35</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;A&nbsp;secret&nbsp;key,&nbsp;&gt;=&nbsp;64&nbsp;characters&nbsp;long.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="36" href="#36">36</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'secret'&nbsp;=&gt;&nbsp;YOUR_APP_INDIEAUTH_SECRET,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="37" href="#37">37</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="38" href="#38">38</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;A&nbsp;path&nbsp;to&nbsp;store&nbsp;token&nbsp;data,&nbsp;or&nbsp;an&nbsp;object&nbsp;implementing&nbsp;TokenStorageInterface.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="39" href="#39">39</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'tokenStorage'&nbsp;=&gt;&nbsp;'/../data/auth_tokens/',</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="40" href="#40">40</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="41" href="#41">41</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;An&nbsp;authentication&nbsp;callback&nbsp;function,&nbsp;which&nbsp;either&nbsp;returns&nbsp;data&nbsp;about&nbsp;the&nbsp;current&nbsp;user,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="42" href="#42">42</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;or&nbsp;redirects&nbsp;to/implements&nbsp;an&nbsp;authentication&nbsp;flow.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="43" href="#43">43</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'authenticationHandler'&nbsp;=&gt;&nbsp;function&nbsp;(ServerRequestInterface&nbsp;$request,&nbsp;string&nbsp;$authenticationRedirect,&nbsp;?string&nbsp;$normalizedMeUrl)&nbsp;{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="44" href="#44">44</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;If&nbsp;the&nbsp;request&nbsp;is&nbsp;authenticated,&nbsp;return&nbsp;an&nbsp;array&nbsp;with&nbsp;a&nbsp;`me`&nbsp;key&nbsp;containing&nbsp;the</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="45" href="#45">45</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;canonical&nbsp;URL&nbsp;of&nbsp;the&nbsp;currently&nbsp;logged-in&nbsp;user.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="46" href="#46">46</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($userUrl&nbsp;=&nbsp;getLoggedInUserUrl($request))&nbsp;{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="47" href="#47">47</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;['me'&nbsp;=&gt;&nbsp;$userUrl];</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="48" href="#48">48</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="49" href="#49">49</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="50" href="#50">50</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Otherwise,&nbsp;redirect&nbsp;the&nbsp;user&nbsp;to&nbsp;a&nbsp;login&nbsp;page,&nbsp;ensuring&nbsp;that&nbsp;they&nbsp;will&nbsp;be&nbsp;redirected</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="51" href="#51">51</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;back&nbsp;to&nbsp;the&nbsp;IndieAuth&nbsp;flow&nbsp;with&nbsp;query&nbsp;parameters&nbsp;intact&nbsp;once&nbsp;logged&nbsp;in.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="52" href="#52">52</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;Response('302',&nbsp;['Location'&nbsp;=&gt;&nbsp;'https://example.com/login?next='&nbsp;.&nbsp;urlencode($authenticationRedirect)]);</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="53" href="#53">53</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="54" href="#54">54</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]);</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="55" href="#55">55</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="56" href="#56">56</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;In&nbsp;your&nbsp;authorization&nbsp;endpoint&nbsp;route:</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="57" href="#57">57</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$server-&gt;handleAuthorizationEndpointRequest($request);</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="58" href="#58">58</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="59" href="#59">59</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;In&nbsp;your&nbsp;token&nbsp;endpoint&nbsp;route:</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="60" href="#60">60</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$server-&gt;handleTokenEndpointRequest($request);</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="61" href="#61">61</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="62" href="#62">62</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;In&nbsp;another&nbsp;route&nbsp;(e.g.&nbsp;a&nbsp;micropub&nbsp;route),&nbsp;to&nbsp;authenticate&nbsp;the&nbsp;request:</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="63" href="#63">63</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;(assuming&nbsp;$bearerToken&nbsp;is&nbsp;a&nbsp;token&nbsp;parsed&nbsp;from&nbsp;an&nbsp;“Authorization:&nbsp;Bearer&nbsp;XXXXXX”&nbsp;header</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="64" href="#64">64</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;or&nbsp;access_token&nbsp;property&nbsp;from&nbsp;a&nbsp;request&nbsp;body)</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="65" href="#65">65</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($accessToken&nbsp;=&nbsp;$server-&gt;getTokenStorage()-&gt;getAccessToken($bearerToken))&nbsp;{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="66" href="#66">66</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Request&nbsp;is&nbsp;authenticated&nbsp;as&nbsp;$accessToken['me'],&nbsp;and&nbsp;is&nbsp;allowed&nbsp;to</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="67" href="#67">67</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;act&nbsp;according&nbsp;to&nbsp;the&nbsp;scopes&nbsp;listed&nbsp;in&nbsp;$accessToken['scope'].</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="68" href="#68">68</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$scopes&nbsp;=&nbsp;explode('&nbsp;',&nbsp;$accessToken['scope']);</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="69" href="#69">69</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="70" href="#70">70</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="71" href="#71">71</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;Refer&nbsp;to&nbsp;the&nbsp;`__construct`&nbsp;documentation&nbsp;for&nbsp;further&nbsp;configuration&nbsp;options,&nbsp;and&nbsp;to&nbsp;the</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="72" href="#72">72</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;documentation&nbsp;for&nbsp;both&nbsp;handling&nbsp;methods&nbsp;for&nbsp;further&nbsp;documentation&nbsp;about&nbsp;them.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="73" href="#73">73</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="74" href="#74">74</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;@link&nbsp;https://indieauth.spec.indieweb.org/</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="75" href="#75">75</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;@link&nbsp;https://www.rfc-editor.org/rfc/rfc6749.html#section-5.2</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="76" href="#76">76</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;@link&nbsp;https://github.com/indieweb/indieauth-client-php</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="77" href="#77">77</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*&nbsp;@link&nbsp;https://github.com/Zegnat/php-mindee/blob/development/index.php</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="78" href="#78">78</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;*/</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="79" href="#79">79</a></td><td class="col-11 codeLine"><span class="keyword">class</span><span class="default">&nbsp;</span><span class="default">Server</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="80" href="#80">80</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">const</span><span class="default">&nbsp;</span><span class="default">HANDLE_NON_INDIEAUTH_REQUEST</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">'handleNonIndieAuthRequestCallback'</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="81" href="#81">81</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">const</span><span class="default">&nbsp;</span><span class="default">HANDLE_AUTHENTICATION_REQUEST</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">'authenticationHandler'</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="82" href="#82">82</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="83" href="#83">83</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/**</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="84" href="#84">84</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;query&nbsp;string&nbsp;parameter&nbsp;key&nbsp;used&nbsp;for&nbsp;storing&nbsp;the&nbsp;hash&nbsp;used&nbsp;for&nbsp;validating&nbsp;authorization&nbsp;request&nbsp;parameters.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="85" href="#85">85</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="86" href="#86">86</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">const</span><span class="default">&nbsp;</span><span class="default">HASH_QUERY_STRING_KEY</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">'taproot_indieauth_server_hash'</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="87" href="#87">87</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="88" href="#88">88</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/**</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="89" href="#89">89</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;key&nbsp;used&nbsp;to&nbsp;store&nbsp;the&nbsp;CSRF&nbsp;token&nbsp;everywhere&nbsp;its&nbsp;used:&nbsp;Request&nbsp;parameters,&nbsp;Request&nbsp;body,&nbsp;and&nbsp;Cookies.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="90" href="#90">90</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="91" href="#91">91</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">const</span><span class="default">&nbsp;</span><span class="default">DEFAULT_CSRF_KEY</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">'taproot_indieauth_server_csrf'</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="92" href="#92">92</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="93" href="#93">93</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/**</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="94" href="#94">94</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;form&nbsp;data&nbsp;key&nbsp;used&nbsp;for&nbsp;identifying&nbsp;a&nbsp;request&nbsp;as&nbsp;an&nbsp;authorization&nbsp;(consent&nbsp;screen)&nbsp;form&nbsp;submissions.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="95" href="#95">95</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="96" href="#96">96</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">const</span><span class="default">&nbsp;</span><span class="default">APPROVE_ACTION_KEY</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">'taproot_indieauth_action'</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="97" href="#97">97</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="98" href="#98">98</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/**</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="99" href="#99">99</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;form&nbsp;data&nbsp;value&nbsp;used&nbsp;for&nbsp;identifying&nbsp;a&nbsp;request&nbsp;as&nbsp;an&nbsp;authorization&nbsp;(consent&nbsp;screen)&nbsp;form&nbsp;submissions.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="100" href="#100">100</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="101" href="#101">101</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">const</span><span class="default">&nbsp;</span><span class="default">APPROVE_ACTION_VALUE</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">'approve'</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="102" href="#102">102</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="103" href="#103">103</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="default">Storage</span><span class="default">\</span><span class="default">TokenStorageInterface</span><span class="default">&nbsp;</span><span class="default">$tokenStorage</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="104" href="#104">104</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="105" href="#105">105</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="default">AuthorizationFormInterface</span><span class="default">&nbsp;</span><span class="default">$authorizationForm</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="106" href="#106">106</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="107" href="#107">107</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="default">MiddlewareInterface</span><span class="default">&nbsp;</span><span class="default">$csrfMiddleware</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="108" href="#108">108</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="109" href="#109">109</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="default">LoggerInterface</span><span class="default">&nbsp;</span><span class="default">$logger</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="110" href="#110">110</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="111" href="#111">111</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/**&nbsp;@var&nbsp;callable&nbsp;*/</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="112" href="#112">112</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="default">$httpGetWithEffectiveUrl</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="113" href="#113">113</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="114" href="#114">114</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/**&nbsp;@var&nbsp;callable&nbsp;*/</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="115" href="#115">115</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="default">$handleAuthenticationRequestCallback</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="116" href="#116">116</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="117" href="#117">117</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/**&nbsp;@var&nbsp;callable&nbsp;*/</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="118" href="#118">118</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="default">$handleNonIndieAuthRequest</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="119" href="#119">119</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="120" href="#120">120</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="default">string</span><span class="default">&nbsp;</span><span class="default">$exceptionTemplatePath</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="121" href="#121">121</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="122" href="#122">122</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="default">string</span><span class="default">&nbsp;</span><span class="default">$secret</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="123" href="#123">123</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="124" href="#124">124</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="default">bool</span><span class="default">&nbsp;</span><span class="default">$requirePkce</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="125" href="#125">125</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="126" href="#126">126</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/**</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="127" href="#127">127</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Constructor</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="128" href="#128">128</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="129" href="#129">129</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Server&nbsp;instances&nbsp;are&nbsp;configured&nbsp;by&nbsp;passing&nbsp;a&nbsp;config&nbsp;array&nbsp;to&nbsp;the&nbsp;constructor.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="130" href="#130">130</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="131" href="#131">131</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;following&nbsp;keys&nbsp;are&nbsp;required:</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="132" href="#132">132</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="133" href="#133">133</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;`authenticationHandler`:&nbsp;a&nbsp;callable&nbsp;with&nbsp;the&nbsp;signature</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="134" href="#134">134</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;`function&nbsp;(ServerRequestInterface&nbsp;$request,&nbsp;string&nbsp;$authenticationRedirect,&nbsp;?string&nbsp;$normalizedMeUrl):&nbsp;array|ResponseInterface`.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="135" href="#135">135</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;This&nbsp;function&nbsp;is&nbsp;called&nbsp;on&nbsp;IndieAuth&nbsp;authorization&nbsp;requests,&nbsp;after&nbsp;validating&nbsp;the&nbsp;query&nbsp;parameters.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="136" href="#136">136</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="137" href="#137">137</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;It&nbsp;should&nbsp;check&nbsp;to&nbsp;see&nbsp;if&nbsp;$request&nbsp;is&nbsp;authenticated,&nbsp;then:</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="138" href="#138">138</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;If&nbsp;it&nbsp;is&nbsp;authenticated,&nbsp;return&nbsp;an&nbsp;array&nbsp;which&nbsp;MUST&nbsp;have&nbsp;a&nbsp;`me`&nbsp;key,&nbsp;mapping&nbsp;to&nbsp;the&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="139" href="#139">139</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;canonical&nbsp;URL&nbsp;of&nbsp;the&nbsp;currently&nbsp;logged-in&nbsp;user.&nbsp;It&nbsp;may&nbsp;additionally&nbsp;have&nbsp;a&nbsp;`profile`&nbsp;key.&nbsp;These</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="140" href="#140">140</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;keys&nbsp;will&nbsp;be&nbsp;stored&nbsp;in&nbsp;the&nbsp;authorization&nbsp;code&nbsp;and&nbsp;sent&nbsp;to&nbsp;the&nbsp;client,&nbsp;if&nbsp;successful.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="141" href="#141">141</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;If&nbsp;it&nbsp;is&nbsp;not&nbsp;authenticated,&nbsp;either&nbsp;present&nbsp;or&nbsp;redirect&nbsp;to&nbsp;an&nbsp;authentication&nbsp;flow.&nbsp;This&nbsp;flow&nbsp;MUST</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="142" href="#142">142</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;redirect&nbsp;the&nbsp;logged-in&nbsp;used&nbsp;back&nbsp;to&nbsp;`$authenticationRedirect`.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="143" href="#143">143</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="144" href="#144">144</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;If&nbsp;the&nbsp;request&nbsp;has&nbsp;a&nbsp;valid&nbsp;`me`&nbsp;parameter,&nbsp;the&nbsp;canonicalized&nbsp;version&nbsp;of&nbsp;it&nbsp;is&nbsp;passed&nbsp;as</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="145" href="#145">145</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;`$normalizedMeUrl`.&nbsp;Otherwise,&nbsp;this&nbsp;parameter&nbsp;is&nbsp;null.&nbsp;This&nbsp;parameter&nbsp;can&nbsp;optionally&nbsp;be&nbsp;used&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="146" href="#146">146</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;as&nbsp;a&nbsp;suggestion&nbsp;for&nbsp;which&nbsp;user&nbsp;to&nbsp;log&nbsp;in&nbsp;as&nbsp;in&nbsp;a&nbsp;multi-user&nbsp;authentication&nbsp;flow,&nbsp;but&nbsp;should&nbsp;NOT</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="147" href="#147">147</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;be&nbsp;considered&nbsp;valid&nbsp;data.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="148" href="#148">148</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="149" href="#149">149</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;If&nbsp;redirecting&nbsp;to&nbsp;an&nbsp;existing&nbsp;authentication&nbsp;flow,&nbsp;this&nbsp;callable&nbsp;can&nbsp;usually&nbsp;be&nbsp;implemented&nbsp;as&nbsp;a</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="150" href="#150">150</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;closure.&nbsp;The&nbsp;callable&nbsp;may&nbsp;also&nbsp;implement&nbsp;its&nbsp;own&nbsp;authentication&nbsp;logic.&nbsp;For&nbsp;an&nbsp;example,&nbsp;see&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="151" href="#151">151</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;`Callback\SingleUserPasswordAuthenticationCallback`.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="152" href="#152">152</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;`secret`:&nbsp;A&nbsp;cryptographically&nbsp;random&nbsp;string&nbsp;with&nbsp;a&nbsp;minimum&nbsp;length&nbsp;of&nbsp;64&nbsp;characters.&nbsp;Used</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="153" href="#153">153</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;to&nbsp;hash&nbsp;and&nbsp;subsequently&nbsp;verify&nbsp;request&nbsp;query&nbsp;parameters&nbsp;which&nbsp;get&nbsp;passed&nbsp;around.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="154" href="#154">154</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;`tokenStorage`:&nbsp;Either&nbsp;an&nbsp;object&nbsp;implementing&nbsp;`Storage\TokenStorageInterface`,&nbsp;or&nbsp;a&nbsp;string&nbsp;path,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="155" href="#155">155</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;which&nbsp;will&nbsp;be&nbsp;passed&nbsp;to&nbsp;`Storage\FilesystemJsonStorage`.&nbsp;This&nbsp;object&nbsp;handles&nbsp;persisting&nbsp;authorization</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="156" href="#156">156</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;codes&nbsp;and&nbsp;access&nbsp;tokens,&nbsp;as&nbsp;well&nbsp;as&nbsp;implementation-specific&nbsp;parts&nbsp;of&nbsp;the&nbsp;exchange&nbsp;process&nbsp;which&nbsp;are&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="157" href="#157">157</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;out&nbsp;of&nbsp;the&nbsp;scope&nbsp;of&nbsp;the&nbsp;Server&nbsp;class&nbsp;(e.g.&nbsp;lifetimes&nbsp;and&nbsp;expiry).&nbsp;Refer&nbsp;to&nbsp;the&nbsp;`Storage\TokenStorageInterface`</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="158" href="#158">158</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;documentation&nbsp;for&nbsp;more&nbsp;details.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="159" href="#159">159</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="160" href="#160">160</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;following&nbsp;keys&nbsp;may&nbsp;be&nbsp;required&nbsp;depending&nbsp;on&nbsp;which&nbsp;packages&nbsp;you&nbsp;have&nbsp;installed:</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="161" href="#161">161</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="162" href="#162">162</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;`httpGetWithEffectiveUrl`:&nbsp;must&nbsp;be&nbsp;a&nbsp;callable&nbsp;with&nbsp;the&nbsp;following&nbsp;signature:</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="163" href="#163">163</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;`function&nbsp;(string&nbsp;$url):&nbsp;array&nbsp;[ResponseInterface&nbsp;$response,&nbsp;string&nbsp;$effectiveUrl]`,&nbsp;where&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="164" href="#164">164</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;`$effectiveUrl`&nbsp;is&nbsp;the&nbsp;final&nbsp;URL&nbsp;after&nbsp;following&nbsp;any&nbsp;redirects&nbsp;(unfortunately,&nbsp;neither&nbsp;the&nbsp;PSR-7</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="165" href="#165">165</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;Response&nbsp;nor&nbsp;the&nbsp;PSR-18&nbsp;Client&nbsp;interfaces&nbsp;offer&nbsp;a&nbsp;standard&nbsp;way&nbsp;of&nbsp;getting&nbsp;this&nbsp;very&nbsp;important</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="166" href="#166">166</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;data,&nbsp;hence&nbsp;the&nbsp;unusual&nbsp;return&nbsp;signature).&nbsp;&nbsp;If&nbsp;`guzzlehttp/guzzle`&nbsp;is&nbsp;installed,&nbsp;this&nbsp;parameter</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="167" href="#167">167</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;will&nbsp;be&nbsp;created&nbsp;automatically.&nbsp;Otherwise,&nbsp;the&nbsp;user&nbsp;must&nbsp;provide&nbsp;their&nbsp;own&nbsp;callable.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="168" href="#168">168</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="169" href="#169">169</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;The&nbsp;following&nbsp;keys&nbsp;are&nbsp;optional:</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="170" href="#170">170</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="171" href="#171">171</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;`authorizationForm`:&nbsp;an&nbsp;instance&nbsp;of&nbsp;`AuthorizationFormInterface`.&nbsp;Defaults&nbsp;to&nbsp;`DefaultAuthorizationForm`.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="172" href="#172">172</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;Refer&nbsp;to&nbsp;that&nbsp;implementation&nbsp;if&nbsp;you&nbsp;wish&nbsp;to&nbsp;replace&nbsp;the&nbsp;consent&nbsp;screen/scope&nbsp;choosing/authorization&nbsp;form.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="173" href="#173">173</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;`csrfMiddleware`:&nbsp;an&nbsp;instance&nbsp;of&nbsp;`MiddlewareInterface`,&nbsp;which&nbsp;will&nbsp;be&nbsp;used&nbsp;to&nbsp;CSRF-protect&nbsp;the</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="174" href="#174">174</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;user-facing&nbsp;authorization&nbsp;flow.&nbsp;By&nbsp;default&nbsp;an&nbsp;instance&nbsp;of&nbsp;`DoubleSubmitCookieCsrfMiddleware`.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="175" href="#175">175</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;Refer&nbsp;to&nbsp;that&nbsp;implementation&nbsp;if&nbsp;you&nbsp;want&nbsp;to&nbsp;replace&nbsp;it&nbsp;with&nbsp;your&nbsp;own&nbsp;middleware&nbsp;&nbsp;you&nbsp;will&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="176" href="#176">176</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;likely&nbsp;have&nbsp;to&nbsp;either&nbsp;make&nbsp;sure&nbsp;your&nbsp;middleware&nbsp;sets&nbsp;the&nbsp;same&nbsp;request&nbsp;attribute,&nbsp;or&nbsp;alter&nbsp;your</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="177" href="#177">177</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;templates&nbsp;accordingly.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="178" href="#178">178</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;`exceptionTemplatePath`:&nbsp;string,&nbsp;path&nbsp;to&nbsp;a&nbsp;template&nbsp;which&nbsp;will&nbsp;be&nbsp;used&nbsp;for&nbsp;displaying&nbsp;user-facing</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="179" href="#179">179</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;errors.&nbsp;Defaults&nbsp;to&nbsp;`../templates/default_exception_response.html.php`,&nbsp;refer&nbsp;to&nbsp;that&nbsp;if&nbsp;you&nbsp;wish</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="180" href="#180">180</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;to&nbsp;write&nbsp;your&nbsp;own&nbsp;template.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="181" href="#181">181</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;`handleNonIndieAuthRequestCallback`:&nbsp;A&nbsp;callback&nbsp;with&nbsp;the&nbsp;following&nbsp;signature:</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="182" href="#182">182</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;`function&nbsp;(ServerRequestInterface&nbsp;$request):&nbsp;?ResponseInterface`&nbsp;which&nbsp;will&nbsp;be&nbsp;called&nbsp;if&nbsp;the</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="183" href="#183">183</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;authorization&nbsp;endpoint&nbsp;gets&nbsp;a&nbsp;request&nbsp;which&nbsp;is&nbsp;not&nbsp;identified&nbsp;as&nbsp;an&nbsp;IndieAuth&nbsp;request&nbsp;or&nbsp;authorization</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="184" href="#184">184</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;form&nbsp;submission&nbsp;request.&nbsp;You&nbsp;could&nbsp;use&nbsp;this&nbsp;to&nbsp;handle&nbsp;various&nbsp;requests&nbsp;e.g.&nbsp;client-side&nbsp;requests</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="185" href="#185">185</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;made&nbsp;by&nbsp;your&nbsp;authentication&nbsp;or&nbsp;authorization&nbsp;pages,&nbsp;if&nbsp;its&nbsp;not&nbsp;convenient&nbsp;to&nbsp;put&nbsp;them&nbsp;elsewhere.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="186" href="#186">186</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;Returning&nbsp;`null`&nbsp;will&nbsp;result&nbsp;in&nbsp;a&nbsp;standard&nbsp;`invalid_request`&nbsp;error&nbsp;being&nbsp;returned.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="187" href="#187">187</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;`logger`:&nbsp;An&nbsp;instance&nbsp;of&nbsp;`LoggerInterface`.&nbsp;Will&nbsp;be&nbsp;used&nbsp;for&nbsp;internal&nbsp;logging,&nbsp;and&nbsp;will&nbsp;also&nbsp;be&nbsp;set</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="188" href="#188">188</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;as&nbsp;the&nbsp;logger&nbsp;for&nbsp;any&nbsp;objects&nbsp;passed&nbsp;in&nbsp;config&nbsp;which&nbsp;implement&nbsp;`LoggerAwareInterface`.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="189" href="#189">189</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;`requirePKCE`:&nbsp;bool,&nbsp;default&nbsp;true.&nbsp;Setting&nbsp;this&nbsp;to&nbsp;`false`&nbsp;allows&nbsp;requests&nbsp;which&nbsp;dont&nbsp;provide&nbsp;PKCE</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="190" href="#190">190</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;parameters&nbsp;(code_challenge,&nbsp;code_challenge_method,&nbsp;code_verifier),&nbsp;under&nbsp;the&nbsp;following&nbsp;conditions:</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="191" href="#191">191</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;If&nbsp;any&nbsp;of&nbsp;the&nbsp;PKCE&nbsp;parameters&nbsp;are&nbsp;present&nbsp;in&nbsp;an&nbsp;authorization&nbsp;code&nbsp;request,&nbsp;all&nbsp;must&nbsp;be&nbsp;present</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="192" href="#192">192</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;valid.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="193" href="#193">193</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;If&nbsp;an&nbsp;authorization&nbsp;code&nbsp;request&nbsp;lacks&nbsp;PKCE&nbsp;parameters,&nbsp;the&nbsp;created&nbsp;auth&nbsp;code&nbsp;can&nbsp;only&nbsp;be&nbsp;exchanged</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="194" href="#194">194</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;by&nbsp;an&nbsp;exchange&nbsp;request&nbsp;without&nbsp;parameters.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="195" href="#195">195</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;If&nbsp;authorization&nbsp;codes&nbsp;are&nbsp;stored&nbsp;without&nbsp;PKCE&nbsp;parameters,&nbsp;and&nbsp;then&nbsp;`requirePKCE`&nbsp;is&nbsp;set&nbsp;to&nbsp;`true`,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="196" href="#196">196</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;these&nbsp;old&nbsp;authorization&nbsp;codes&nbsp;will&nbsp;no&nbsp;longer&nbsp;be&nbsp;redeemable.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="197" href="#197">197</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="198" href="#198">198</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;array&nbsp;$config&nbsp;An&nbsp;array&nbsp;of&nbsp;configuration&nbsp;variables</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="199" href="#199">199</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;self</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="200" href="#200">200</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="201" href="#201">201</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">__construct</span><span class="keyword">(</span><span class="keyword">array</span><span class="default">&nbsp;</span><span class="default">$config</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 202" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="202" href="#202">202</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$config</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">array_merge</span><span class="keyword">(</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 203" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="203" href="#203">203</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'csrfMiddleware'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">Middleware</span><span class="default">\</span><span class="default">DoubleSubmitCookieCsrfMiddleware</span><span class="keyword">(</span><span class="default">self</span><span class="default">::</span><span class="default">DEFAULT_CSRF_KEY</span><span class="keyword">)</span><span class="keyword">,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="204" href="#204">204</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'logger'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">null</span><span class="keyword">,</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 205" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="205" href="#205">205</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">self</span><span class="default">::</span><span class="default">HANDLE_NON_INDIEAUTH_REQUEST</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">ServerRequestInterface</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span><span class="default">&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">null</span><span class="keyword">;</span><span class="default">&nbsp;</span><span class="keyword">}</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="comment">//&nbsp;Default&nbsp;to&nbsp;no-op.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="206" href="#206">206</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'tokenStorage'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">null</span><span class="keyword">,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="207" href="#207">207</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'httpGetWithEffectiveUrl'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">null</span><span class="keyword">,</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 208" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="208" href="#208">208</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'authorizationForm'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">DefaultAuthorizationForm</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="209" href="#209">209</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'exceptionTemplatePath'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">__DIR__</span><span class="default">&nbsp;</span><span class="keyword">.</span><span class="default">&nbsp;</span><span class="default">'/../templates/default_exception_response.html.php'</span><span class="keyword">,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="210" href="#210">210</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'requirePKCE'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">true</span><span class="keyword">,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="211" href="#211">211</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$config</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="212" href="#212">212</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 213" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="213" href="#213">213</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">requirePkce</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$config</span><span class="keyword">[</span><span class="default">'requirePKCE'</span><span class="keyword">]</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="214" href="#214">214</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 215" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="215" href="#215">215</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="default">is_string</span><span class="keyword">(</span><span class="default">$config</span><span class="keyword">[</span><span class="default">'exceptionTemplatePath'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 216" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="216" href="#216">216</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">BadMethodCallException</span><span class="keyword">(</span><span class="default">&quot;\$config['exceptionTemplatePath']&nbsp;must&nbsp;be&nbsp;a&nbsp;string&nbsp;(path).&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="217" href="#217">217</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 218" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="218" href="#218">218</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">exceptionTemplatePath</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$config</span><span class="keyword">[</span><span class="default">'exceptionTemplatePath'</span><span class="keyword">]</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="219" href="#219">219</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 220" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="220" href="#220">220</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$secret</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$config</span><span class="keyword">[</span><span class="default">'secret'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="default">??</span><span class="default">&nbsp;</span><span class="default">''</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 221" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="221" href="#221">221</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="default">is_string</span><span class="keyword">(</span><span class="default">$secret</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">||</span><span class="default">&nbsp;</span><span class="default">strlen</span><span class="keyword">(</span><span class="default">$secret</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">&lt;</span><span class="default">&nbsp;</span><span class="default">64</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 222" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="222" href="#222">222</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">BadMethodCallException</span><span class="keyword">(</span><span class="default">&quot;\$config['secret']&nbsp;must&nbsp;be&nbsp;a&nbsp;string&nbsp;with&nbsp;a&nbsp;minimum&nbsp;length&nbsp;of&nbsp;64&nbsp;characters.&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="223" href="#223">223</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 224" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="224" href="#224">224</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">secret</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$secret</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="225" href="#225">225</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 226" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="226" href="#226">226</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="default">is_null</span><span class="keyword">(</span><span class="default">$config</span><span class="keyword">[</span><span class="default">'logger'</span><span class="keyword">]</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">&amp;&amp;</span><span class="default">&nbsp;</span><span class="keyword">!</span><span class="default">$config</span><span class="keyword">[</span><span class="default">'logger'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="keyword">instanceof</span><span class="default">&nbsp;</span><span class="default">LoggerInterface</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 227" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="227" href="#227">227</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">BadMethodCallException</span><span class="keyword">(</span><span class="default">&quot;\$config['logger']&nbsp;must&nbsp;be&nbsp;an&nbsp;instance&nbsp;of&nbsp;\\Psr\\Log\\LoggerInterface&nbsp;or&nbsp;null.&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="228" href="#228">228</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 229" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="229" href="#229">229</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$config</span><span class="keyword">[</span><span class="default">'logger'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="default">??</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">NullLogger</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="230" href="#230">230</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 231" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="231" href="#231">231</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="keyword">(</span><span class="default">array_key_exists</span><span class="keyword">(</span><span class="default">self</span><span class="default">::</span><span class="default">HANDLE_AUTHENTICATION_REQUEST</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$config</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">and</span><span class="default">&nbsp;</span><span class="default">is_callable</span><span class="keyword">(</span><span class="default">$config</span><span class="keyword">[</span><span class="default">self</span><span class="default">::</span><span class="default">HANDLE_AUTHENTICATION_REQUEST</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 232" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="232" href="#232">232</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">BadMethodCallException</span><span class="keyword">(</span><span class="default">'$callbacks[\''</span><span class="default">&nbsp;</span><span class="keyword">.</span><span class="default">&nbsp;</span><span class="default">self</span><span class="default">::</span><span class="default">HANDLE_AUTHENTICATION_REQUEST</span><span class="default">&nbsp;</span><span class="keyword">.</span><span class="default">'\']&nbsp;must&nbsp;be&nbsp;present&nbsp;and&nbsp;callable.'</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="233" href="#233">233</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 234" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="234" href="#234">234</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">handleAuthenticationRequestCallback</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$config</span><span class="keyword">[</span><span class="default">self</span><span class="default">::</span><span class="default">HANDLE_AUTHENTICATION_REQUEST</span><span class="keyword">]</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="235" href="#235">235</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 236" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="236" href="#236">236</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="default">is_callable</span><span class="keyword">(</span><span class="default">$config</span><span class="keyword">[</span><span class="default">self</span><span class="default">::</span><span class="default">HANDLE_NON_INDIEAUTH_REQUEST</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 237" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="237" href="#237">237</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">BadMethodCallException</span><span class="keyword">(</span><span class="default">&quot;\$config['&quot;</span><span class="default">&nbsp;</span><span class="keyword">.</span><span class="default">&nbsp;</span><span class="default">self</span><span class="default">::</span><span class="default">HANDLE_NON_INDIEAUTH_REQUEST</span><span class="default">&nbsp;</span><span class="keyword">.</span><span class="default">&nbsp;</span><span class="default">&quot;']&nbsp;must&nbsp;be&nbsp;callable&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="238" href="#238">238</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 239" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="239" href="#239">239</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">handleNonIndieAuthRequest</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$config</span><span class="keyword">[</span><span class="default">self</span><span class="default">::</span><span class="default">HANDLE_NON_INDIEAUTH_REQUEST</span><span class="keyword">]</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="240" href="#240">240</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 241" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="241" href="#241">241</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$tokenStorage</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$config</span><span class="keyword">[</span><span class="default">'tokenStorage'</span><span class="keyword">]</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 242" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="242" href="#242">242</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="default">$tokenStorage</span><span class="default">&nbsp;</span><span class="keyword">instanceof</span><span class="default">&nbsp;</span><span class="default">Storage</span><span class="default">\</span><span class="default">TokenStorageInterface</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="31 tests cover line 243" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="243" href="#243">243</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">is_string</span><span class="keyword">(</span><span class="default">$tokenStorage</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="244" href="#244">244</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Create&nbsp;a&nbsp;default&nbsp;access&nbsp;token&nbsp;storage&nbsp;with&nbsp;a&nbsp;TTL&nbsp;of&nbsp;7&nbsp;days.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="31 tests cover line 245" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="245" href="#245">245</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$tokenStorage</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">Storage</span><span class="default">\</span><span class="default">FilesystemJsonStorage</span><span class="keyword">(</span><span class="default">$tokenStorage</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">secret</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="246" href="#246">246</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="default">&nbsp;</span><span class="keyword">else</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 247" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="247" href="#247">247</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">BadMethodCallException</span><span class="keyword">(</span><span class="default">&quot;\$config['tokenStorage']&nbsp;parameter&nbsp;must&nbsp;be&nbsp;either&nbsp;a&nbsp;string&nbsp;(path)&nbsp;or&nbsp;an&nbsp;instance&nbsp;of&nbsp;Taproot\IndieAuth\TokenStorageInterface.&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="248" href="#248">248</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="249" href="#249">249</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 250" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="250" href="#250">250</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">trySetLogger</span><span class="keyword">(</span><span class="default">$tokenStorage</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 251" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="251" href="#251">251</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">tokenStorage</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$tokenStorage</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="252" href="#252">252</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 253" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="253" href="#253">253</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$csrfMiddleware</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$config</span><span class="keyword">[</span><span class="default">'csrfMiddleware'</span><span class="keyword">]</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 254" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="254" href="#254">254</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="default">$csrfMiddleware</span><span class="default">&nbsp;</span><span class="keyword">instanceof</span><span class="default">&nbsp;</span><span class="default">MiddlewareInterface</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 255" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="255" href="#255">255</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">BadMethodCallException</span><span class="keyword">(</span><span class="default">&quot;\$config['csrfMiddleware']&nbsp;must&nbsp;be&nbsp;null&nbsp;or&nbsp;implement&nbsp;MiddlewareInterface.&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="256" href="#256">256</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 257" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="257" href="#257">257</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">trySetLogger</span><span class="keyword">(</span><span class="default">$csrfMiddleware</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 258" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="258" href="#258">258</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">csrfMiddleware</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$csrfMiddleware</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="259" href="#259">259</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 260" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="260" href="#260">260</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$httpGetWithEffectiveUrl</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$config</span><span class="keyword">[</span><span class="default">'httpGetWithEffectiveUrl'</span><span class="keyword">]</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 261" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="261" href="#261">261</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">is_null</span><span class="keyword">(</span><span class="default">$httpGetWithEffectiveUrl</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="21 tests cover line 262" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="262" href="#262">262</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">class_exists</span><span class="keyword">(</span><span class="default">'\GuzzleHttp\Client'</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="21 tests cover line 263" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="263" href="#263">263</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$httpGetWithEffectiveUrl</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">string</span><span class="default">&nbsp;</span><span class="default">$uri</span><span class="keyword">)</span><span class="keyword">:</span><span class="default">&nbsp;</span><span class="keyword">array</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="264" href="#264">264</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;This&nbsp;code&nbsp;cant&nbsp;be&nbsp;tested,&nbsp;ignore&nbsp;it&nbsp;for&nbsp;coverage&nbsp;purposes.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="265" href="#265">265</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;@codeCoverageIgnoreStart</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="266" href="#266">266</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$resp</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">\</span><span class="default">GuzzleHttp</span><span class="default">\</span><span class="default">Client</span><span class="keyword">(</span><span class="keyword">[</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="267" href="#267">267</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">\</span><span class="default">GuzzleHttp</span><span class="default">\</span><span class="default">RequestOptions</span><span class="default">::</span><span class="default">ALLOW_REDIRECTS</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="keyword">[</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="268" href="#268">268</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'max'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">10</span><span class="keyword">,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="269" href="#269">269</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'strict'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">true</span><span class="keyword">,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="270" href="#270">270</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'referer'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">true</span><span class="keyword">,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="271" href="#271">271</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'track_redirects'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">true</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="272" href="#272">272</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="273" href="#273">273</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">-&gt;</span><span class="default">get</span><span class="keyword">(</span><span class="default">$uri</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="274" href="#274">274</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="275" href="#275">275</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$rdh</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$resp</span><span class="default">-&gt;</span><span class="default">getHeader</span><span class="keyword">(</span><span class="default">'X-Guzzle-Redirect-History'</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="276" href="#276">276</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$effectiveUrl</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="keyword">empty</span><span class="keyword">(</span><span class="default">$rdh</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">?</span><span class="default">&nbsp;</span><span class="default">$uri</span><span class="default">&nbsp;</span><span class="keyword">:</span><span class="default">&nbsp;</span><span class="default">array_values</span><span class="keyword">(</span><span class="default">$rdh</span><span class="keyword">)</span><span class="keyword">[</span><span class="default">count</span><span class="keyword">(</span><span class="default">$rdh</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">-</span><span class="default">&nbsp;</span><span class="default">1</span><span class="keyword">]</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="277" href="#277">277</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="278" href="#278">278</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">$resp</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$effectiveUrl</span><span class="keyword">]</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="279" href="#279">279</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="280" href="#280">280</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="default">&nbsp;</span><span class="keyword">else</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="281" href="#281">281</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">BadMethodCallException</span><span class="keyword">(</span><span class="default">&quot;\$config['httpGetWithEffectiveUrl']&nbsp;was&nbsp;not&nbsp;provided,&nbsp;and&nbsp;guzzlehttp/guzzle&nbsp;was&nbsp;not&nbsp;installed.&nbsp;Either&nbsp;require&nbsp;guzzlehttp/guzzle,&nbsp;or&nbsp;provide&nbsp;a&nbsp;valid&nbsp;callable.&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="282" href="#282">282</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;@codeCoverageIgnoreEnd</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="283" href="#283">283</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="284" href="#284">284</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="default">&nbsp;</span><span class="keyword">else</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="12 tests cover line 285" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="285" href="#285">285</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="default">is_callable</span><span class="keyword">(</span><span class="default">$httpGetWithEffectiveUrl</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 286" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="286" href="#286">286</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">BadMethodCallException</span><span class="keyword">(</span><span class="default">&quot;\$config['httpGetWithEffectiveUrl']&nbsp;must&nbsp;be&nbsp;callable.&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="287" href="#287">287</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="288" href="#288">288</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 289" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="289" href="#289">289</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">trySetLogger</span><span class="keyword">(</span><span class="default">$httpGetWithEffectiveUrl</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 290" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="290" href="#290">290</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">httpGetWithEffectiveUrl</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$httpGetWithEffectiveUrl</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="291" href="#291">291</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="32 tests cover line 292" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="292" href="#292">292</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="default">$config</span><span class="keyword">[</span><span class="default">'authorizationForm'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="keyword">instanceof</span><span class="default">&nbsp;</span><span class="default">AuthorizationFormInterface</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 293" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidConfigRaisesException&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="293" href="#293">293</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">BadMethodCallException</span><span class="keyword">(</span><span class="default">&quot;When&nbsp;provided,&nbsp;\$config['authorizationForm']&nbsp;must&nbsp;implement&nbsp;Taproot\IndieAuth\Callback\AuthorizationForm.&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="294" href="#294">294</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="31 tests cover line 295" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="295" href="#295">295</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">authorizationForm</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$config</span><span class="keyword">[</span><span class="default">'authorizationForm'</span><span class="keyword">]</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="31 tests cover line 296" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="296" href="#296">296</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">trySetLogger</span><span class="keyword">(</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">authorizationForm</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="31 tests cover line 297" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="297" href="#297">297</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="298" href="#298">298</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="299" href="#299">299</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">getTokenStorage</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">:</span><span class="default">&nbsp;</span><span class="default">TokenStorageInterface</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 300" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="300" href="#300">300</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">tokenStorage</span><span class="keyword">;</span></td></tr>
<tr class="warning d-flex"><td class="col-1 text-right"><a id="301" href="#301">301</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="302" href="#302">302</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="303" href="#303">303</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/**</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="304" href="#304">304</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Handle&nbsp;Authorization&nbsp;Endpoint&nbsp;Request</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="305" href="#305">305</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="306" href="#306">306</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;This&nbsp;method&nbsp;handles&nbsp;all&nbsp;requests&nbsp;to&nbsp;your&nbsp;authorization&nbsp;endpoint,&nbsp;passing&nbsp;execution&nbsp;off&nbsp;to</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="307" href="#307">307</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;other&nbsp;callbacks&nbsp;when&nbsp;necessary.&nbsp;The&nbsp;logical&nbsp;flow&nbsp;can&nbsp;be&nbsp;summarised&nbsp;as&nbsp;follows:</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="308" href="#308">308</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="309" href="#309">309</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;If&nbsp;this&nbsp;request&nbsp;an&nbsp;**auth&nbsp;code&nbsp;exchange&nbsp;for&nbsp;profile&nbsp;information**,&nbsp;validate&nbsp;the&nbsp;request</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="310" href="#310">310</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;and&nbsp;return&nbsp;a&nbsp;response&nbsp;or&nbsp;error&nbsp;response.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="311" href="#311">311</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;Otherwise,&nbsp;proceed,&nbsp;wrapping&nbsp;all&nbsp;execution&nbsp;in&nbsp;CSRF-protection&nbsp;middleware.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="312" href="#312">312</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;Validate&nbsp;the&nbsp;requests&nbsp;indieauth&nbsp;authorization&nbsp;code&nbsp;request&nbsp;parameters,&nbsp;returning&nbsp;an&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="313" href="#313">313</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;error&nbsp;response&nbsp;if&nbsp;any&nbsp;are&nbsp;missing&nbsp;or&nbsp;invalid.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="314" href="#314">314</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;Call&nbsp;the&nbsp;authentication&nbsp;callback</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="315" href="#315">315</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;If&nbsp;the&nbsp;callback&nbsp;returned&nbsp;an&nbsp;instance&nbsp;of&nbsp;ResponseInterface,&nbsp;the&nbsp;user&nbsp;is&nbsp;not&nbsp;currently</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="316" href="#316">316</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logged&nbsp;in.&nbsp;Return&nbsp;the&nbsp;Response,&nbsp;which&nbsp;will&nbsp;presumably&nbsp;start&nbsp;an&nbsp;authentication&nbsp;flow.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="317" href="#317">317</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Otherwise,&nbsp;the&nbsp;callback&nbsp;returned&nbsp;information&nbsp;about&nbsp;the&nbsp;currently&nbsp;logged-in&nbsp;user.&nbsp;Continue.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="318" href="#318">318</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;If&nbsp;this&nbsp;request&nbsp;is&nbsp;an&nbsp;authorization&nbsp;form&nbsp;submission,&nbsp;validate&nbsp;the&nbsp;data,&nbsp;store&nbsp;and&nbsp;authorization</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="319" href="#319">319</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;code&nbsp;and&nbsp;return&nbsp;a&nbsp;redirect&nbsp;response&nbsp;to&nbsp;the&nbsp;client&nbsp;redirect_uri&nbsp;with&nbsp;code&nbsp;data.&nbsp;On&nbsp;an&nbsp;error,&nbsp;return</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="320" href="#320">320</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;an&nbsp;appropriate&nbsp;error&nbsp;response.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="321" href="#321">321</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;Otherwise,&nbsp;fetch&nbsp;the&nbsp;client_id,&nbsp;parse&nbsp;app&nbsp;data&nbsp;if&nbsp;present,&nbsp;validate&nbsp;the&nbsp;`redirect_uri`&nbsp;and&nbsp;present</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="322" href="#322">322</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;the&nbsp;authorization&nbsp;form/consent&nbsp;screen&nbsp;to&nbsp;the&nbsp;user.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="323" href="#323">323</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;If&nbsp;none&nbsp;of&nbsp;the&nbsp;above&nbsp;apply,&nbsp;try&nbsp;calling&nbsp;the&nbsp;non-indieauth&nbsp;request&nbsp;handler.&nbsp;If&nbsp;it&nbsp;returns&nbsp;a&nbsp;Response,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="324" href="#324">324</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;return&nbsp;that,&nbsp;otherwise&nbsp;return&nbsp;an&nbsp;error&nbsp;response.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="325" href="#325">325</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="326" href="#326">326</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;This&nbsp;route&nbsp;should&nbsp;NOT&nbsp;be&nbsp;wrapped&nbsp;in&nbsp;additional&nbsp;CSRF-protection,&nbsp;due&nbsp;to&nbsp;the&nbsp;need&nbsp;to&nbsp;handle&nbsp;API&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="327" href="#327">327</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;POST&nbsp;requests&nbsp;from&nbsp;the&nbsp;client.&nbsp;Make&nbsp;sure&nbsp;you&nbsp;call&nbsp;it&nbsp;from&nbsp;a&nbsp;route&nbsp;which&nbsp;is&nbsp;excluded&nbsp;from&nbsp;any</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="328" href="#328">328</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;CSRF-protection&nbsp;you&nbsp;might&nbsp;be&nbsp;using.&nbsp;To&nbsp;customise&nbsp;the&nbsp;CSRF&nbsp;protection&nbsp;used&nbsp;internally,&nbsp;refer&nbsp;to&nbsp;the</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="329" href="#329">329</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;`__construct`&nbsp;config&nbsp;array&nbsp;documentation&nbsp;for&nbsp;the&nbsp;`csrfMiddleware`&nbsp;key.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="330" href="#330">330</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="331" href="#331">331</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Most&nbsp;user-facing&nbsp;errors&nbsp;are&nbsp;thrown&nbsp;as&nbsp;instances&nbsp;of&nbsp;`IndieAuthException`,&nbsp;which&nbsp;are&nbsp;passed&nbsp;off&nbsp;to</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="332" href="#332">332</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;`handleException`&nbsp;to&nbsp;be&nbsp;turned&nbsp;into&nbsp;an&nbsp;instance&nbsp;of&nbsp;`ResponseInterface`.&nbsp;If&nbsp;you&nbsp;want&nbsp;to&nbsp;customise</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="333" href="#333">333</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;error&nbsp;behaviour,&nbsp;one&nbsp;way&nbsp;to&nbsp;do&nbsp;so&nbsp;is&nbsp;to&nbsp;subclass&nbsp;`Server`&nbsp;and&nbsp;override&nbsp;that&nbsp;method.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="334" href="#334">334</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="335" href="#335">335</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;ServerRequestInterface&nbsp;$request</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="336" href="#336">336</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;ResponseInterface</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="337" href="#337">337</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="338" href="#338">338</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">handleAuthorizationEndpointRequest</span><span class="keyword">(</span><span class="default">ServerRequestInterface</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">:</span><span class="default">&nbsp;</span><span class="default">ResponseInterface</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="28 tests cover line 339" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="339" href="#339">339</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">info</span><span class="keyword">(</span><span class="default">'Handling&nbsp;an&nbsp;IndieAuth&nbsp;Authorization&nbsp;Endpoint&nbsp;request.'</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="340" href="#340">340</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="341" href="#341">341</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;If&nbsp;its&nbsp;a&nbsp;profile&nbsp;information&nbsp;request:</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="28 tests cover line 342" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="342" href="#342">342</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">isIndieAuthAuthorizationCodeRedeemingRequest</span><span class="keyword">(</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="7 tests cover line 343" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="343" href="#343">343</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">info</span><span class="keyword">(</span><span class="default">'Handling&nbsp;a&nbsp;request&nbsp;to&nbsp;redeem&nbsp;an&nbsp;authorization&nbsp;code&nbsp;for&nbsp;profile&nbsp;information.'</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="344" href="#344">344</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="7 tests cover line 345" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="345" href="#345">345</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$bodyParams</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="default">-&gt;</span><span class="default">getParsedBody</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="346" href="#346">346</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="7 tests cover line 347" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="347" href="#347">347</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="keyword">isset</span><span class="keyword">(</span><span class="default">$bodyParams</span><span class="keyword">[</span><span class="default">'code'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 348" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="348" href="#348">348</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">warning</span><span class="keyword">(</span><span class="default">'The&nbsp;exchange&nbsp;request&nbsp;was&nbsp;missing&nbsp;the&nbsp;code&nbsp;parameter.&nbsp;Returning&nbsp;an&nbsp;error&nbsp;response.'</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 349" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="349" href="#349">349</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">Response</span><span class="keyword">(</span><span class="default">400</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'content-type'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'application/json'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">json_encode</span><span class="keyword">(</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 350" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="350" href="#350">350</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'error'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'invalid_request'</span><span class="keyword">,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="351" href="#351">351</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'error_description'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'The&nbsp;code&nbsp;parameter&nbsp;was&nbsp;missing.'</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="352" href="#352">352</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="353" href="#353">353</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="354" href="#354">354</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="355" href="#355">355</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Attempt&nbsp;to&nbsp;internally&nbsp;exchange&nbsp;the&nbsp;provided&nbsp;auth&nbsp;code&nbsp;for&nbsp;an&nbsp;access&nbsp;token.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="356" href="#356">356</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;We&nbsp;do&nbsp;this&nbsp;before&nbsp;anything&nbsp;else&nbsp;so&nbsp;that&nbsp;the&nbsp;auth&nbsp;code&nbsp;is&nbsp;invalidated&nbsp;as&nbsp;soon&nbsp;as&nbsp;the&nbsp;request&nbsp;starts,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="357" href="#357">357</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;and&nbsp;the&nbsp;resulting&nbsp;access&nbsp;token&nbsp;is&nbsp;revoked&nbsp;if&nbsp;we&nbsp;encounter&nbsp;an&nbsp;error.&nbsp;This&nbsp;ends&nbsp;up&nbsp;providing&nbsp;a&nbsp;simpler</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="358" href="#358">358</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;and&nbsp;more&nbsp;flexible&nbsp;interface&nbsp;for&nbsp;TokenStorage&nbsp;implementors.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="359" href="#359">359</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="360" href="#360">360</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Call&nbsp;the&nbsp;token&nbsp;exchange&nbsp;method,&nbsp;passing&nbsp;in&nbsp;a&nbsp;callback&nbsp;which&nbsp;performs&nbsp;additional&nbsp;validation</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="361" href="#361">361</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;on&nbsp;the&nbsp;auth&nbsp;code&nbsp;before&nbsp;it&nbsp;gets&nbsp;exchanged.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="6 tests cover line 362" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="362" href="#362">362</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$tokenData</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">tokenStorage</span><span class="default">-&gt;</span><span class="default">exchangeAuthCodeForAccessToken</span><span class="keyword">(</span><span class="default">$bodyParams</span><span class="keyword">[</span><span class="default">'code'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">array</span><span class="default">&nbsp;</span><span class="default">$authCode</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">use</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">$request</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$bodyParams</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="363" href="#363">363</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Verify&nbsp;that&nbsp;all&nbsp;required&nbsp;parameters&nbsp;are&nbsp;included.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="6 tests cover line 364" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="364" href="#364">364</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$requiredParameters</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">requirePkce</span><span class="default">&nbsp;</span><span class="default">or</span><span class="default">&nbsp;</span><span class="keyword">!</span><span class="keyword">empty</span><span class="keyword">(</span><span class="default">$authCode</span><span class="keyword">[</span><span class="default">'code_challenge'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">?</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'client_id'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">'redirect_uri'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">'code_verifier'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="keyword">:</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'client_id'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">'redirect_uri'</span><span class="keyword">]</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="6 tests cover line 365" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="365" href="#365">365</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$missingRequiredParameters</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">array_filter</span><span class="keyword">(</span><span class="default">$requiredParameters</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">$p</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">use</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">$bodyParams</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="6 tests cover line 366" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="366" href="#366">366</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="keyword">!</span><span class="default">array_key_exists</span><span class="keyword">(</span><span class="default">$p</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$bodyParams</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">||</span><span class="default">&nbsp;</span><span class="keyword">empty</span><span class="keyword">(</span><span class="default">$bodyParams</span><span class="keyword">[</span><span class="default">$p</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="6 tests cover line 367" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="367" href="#367">367</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="6 tests cover line 368" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="368" href="#368">368</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="keyword">empty</span><span class="keyword">(</span><span class="default">$missingRequiredParameters</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 369" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="369" href="#369">369</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">warning</span><span class="keyword">(</span><span class="default">'The&nbsp;exchange&nbsp;request&nbsp;was&nbsp;missing&nbsp;required&nbsp;parameters.&nbsp;Returning&nbsp;an&nbsp;error&nbsp;response.'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'missing'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$missingRequiredParameters</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 370" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="370" href="#370">370</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INVALID_REQUEST</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="371" href="#371">371</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="372" href="#372">372</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="373" href="#373">373</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Verify&nbsp;that&nbsp;it&nbsp;was&nbsp;issued&nbsp;for&nbsp;the&nbsp;same&nbsp;client_id&nbsp;and&nbsp;redirect_uri</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="5 tests cover line 374" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="374" href="#374">374</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">$authCode</span><span class="keyword">[</span><span class="default">'client_id'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="default">!==</span><span class="default">&nbsp;</span><span class="default">$bodyParams</span><span class="keyword">[</span><span class="default">'client_id'</span><span class="keyword">]</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="5 tests cover line 375" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="375" href="#375">375</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">||</span><span class="default">&nbsp;</span><span class="default">$authCode</span><span class="keyword">[</span><span class="default">'redirect_uri'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="default">!==</span><span class="default">&nbsp;</span><span class="default">$bodyParams</span><span class="keyword">[</span><span class="default">'redirect_uri'</span><span class="keyword">]</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 376" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="376" href="#376">376</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">error</span><span class="keyword">(</span><span class="default">&quot;The&nbsp;provided&nbsp;client_id&nbsp;and/or&nbsp;redirect_uri&nbsp;did&nbsp;not&nbsp;match&nbsp;those&nbsp;stored&nbsp;in&nbsp;the&nbsp;token.&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 377" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="377" href="#377">377</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INVALID_GRANT</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="378" href="#378">378</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="379" href="#379">379</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="380" href="#380">380</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;If&nbsp;the&nbsp;auth&nbsp;code&nbsp;was&nbsp;requested&nbsp;with&nbsp;no&nbsp;code_challenge,&nbsp;but&nbsp;the&nbsp;exchange&nbsp;request&nbsp;provides&nbsp;a&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="381" href="#381">381</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;code_verifier,&nbsp;return&nbsp;an&nbsp;error.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="5 tests cover line 382" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="382" href="#382">382</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="keyword">empty</span><span class="keyword">(</span><span class="default">$bodyParams</span><span class="keyword">[</span><span class="default">'code_verifier'</span><span class="keyword">]</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">&amp;&amp;</span><span class="default">&nbsp;</span><span class="keyword">empty</span><span class="keyword">(</span><span class="default">$authCode</span><span class="keyword">[</span><span class="default">'code_challenge'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 383" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="383" href="#383">383</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">error</span><span class="keyword">(</span><span class="default">&quot;A&nbsp;code_verifier&nbsp;was&nbsp;provided&nbsp;when&nbsp;trying&nbsp;to&nbsp;exchange&nbsp;an&nbsp;auth&nbsp;code&nbsp;requested&nbsp;without&nbsp;a&nbsp;code_challenge.&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 384" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="384" href="#384">384</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INVALID_GRANT</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="385" href="#385">385</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="386" href="#386">386</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 387" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="387" href="#387">387</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">requirePkce</span><span class="default">&nbsp;</span><span class="default">or</span><span class="default">&nbsp;</span><span class="keyword">!</span><span class="keyword">empty</span><span class="keyword">(</span><span class="default">$authCode</span><span class="keyword">[</span><span class="default">'code_challenge'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="388" href="#388">388</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Check&nbsp;that&nbsp;the&nbsp;supplied&nbsp;code_verifier&nbsp;hashes&nbsp;to&nbsp;the&nbsp;stored&nbsp;code_challenge</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="389" href="#389">389</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;TODO:&nbsp;support&nbsp;method&nbsp;=&nbsp;plain&nbsp;as&nbsp;well&nbsp;as&nbsp;S256.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 390" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="390" href="#390">390</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="default">hash_equals</span><span class="keyword">(</span><span class="default">$authCode</span><span class="keyword">[</span><span class="default">'code_challenge'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">generatePKCECodeChallenge</span><span class="keyword">(</span><span class="default">$bodyParams</span><span class="keyword">[</span><span class="default">'code_verifier'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 391" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="391" href="#391">391</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">error</span><span class="keyword">(</span><span class="default">&quot;The&nbsp;provided&nbsp;code_verifier&nbsp;did&nbsp;not&nbsp;hash&nbsp;to&nbsp;the&nbsp;stored&nbsp;code_challenge&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 392" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="392" href="#392">392</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INVALID_GRANT</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="393" href="#393">393</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="394" href="#394">394</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="395" href="#395">395</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="396" href="#396">396</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Check&nbsp;that&nbsp;this&nbsp;token&nbsp;either&nbsp;grants&nbsp;at&nbsp;most&nbsp;the&nbsp;profile&nbsp;scope.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 397" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="397" href="#397">397</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$requestedScopes</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">array_filter</span><span class="keyword">(</span><span class="default">explode</span><span class="keyword">(</span><span class="default">'&nbsp;'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$authCode</span><span class="keyword">[</span><span class="default">'scope'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="default">??</span><span class="default">&nbsp;</span><span class="default">''</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 398" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="398" href="#398">398</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="keyword">empty</span><span class="keyword">(</span><span class="default">$requestedScopes</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">&amp;&amp;</span><span class="default">&nbsp;</span><span class="default">$requestedScopes</span><span class="default">&nbsp;</span><span class="default">!=</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'profile'</span><span class="keyword">]</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 399" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="399" href="#399">399</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">error</span><span class="keyword">(</span><span class="default">&quot;An&nbsp;exchange&nbsp;request&nbsp;for&nbsp;a&nbsp;token&nbsp;granting&nbsp;scopes&nbsp;other&nbsp;than&nbsp;“profile”&nbsp;was&nbsp;sent&nbsp;to&nbsp;the&nbsp;authorization&nbsp;endpoint.&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 400" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="400" href="#400">400</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INVALID_GRANT</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="401" href="#401">401</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="6 tests cover line 402" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="402" href="#402">402</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 403" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="403" href="#403">403</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="default">&nbsp;</span><span class="keyword">catch</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="404" href="#404">404</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;If&nbsp;an&nbsp;exception&nbsp;was&nbsp;thrown,&nbsp;return&nbsp;a&nbsp;corresponding&nbsp;error&nbsp;response.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 405" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="405" href="#405">405</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">Response</span><span class="keyword">(</span><span class="default">400</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'content-type'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'application/json'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">json_encode</span><span class="keyword">(</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 406" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="406" href="#406">406</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'error'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="default">-&gt;</span><span class="default">getInfo</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">[</span><span class="default">'error'</span><span class="keyword">]</span><span class="keyword">,</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 407" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeFailsForTokensWithInvalidScope&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="407" href="#407">407</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'error_description'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="default">-&gt;</span><span class="default">getMessage</span><span class="keyword">(</span><span class="keyword">)</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="408" href="#408">408</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="409" href="#409">409</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="410" href="#410">410</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 411" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="411" href="#411">411</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">is_null</span><span class="keyword">(</span><span class="default">$tokenData</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 412" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="412" href="#412">412</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">error</span><span class="keyword">(</span><span class="default">'Attempting&nbsp;to&nbsp;exchange&nbsp;an&nbsp;auth&nbsp;code&nbsp;for&nbsp;a&nbsp;token&nbsp;resulted&nbsp;in&nbsp;null.'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$bodyParams</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 413" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="413" href="#413">413</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">Response</span><span class="keyword">(</span><span class="default">400</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'content-type'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'application/json'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">json_encode</span><span class="keyword">(</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 414" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="414" href="#414">414</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'error'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'invalid_grant'</span><span class="keyword">,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="415" href="#415">415</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'error_description'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'The&nbsp;provided&nbsp;credentials&nbsp;were&nbsp;not&nbsp;valid.'</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="416" href="#416">416</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="417" href="#417">417</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="418" href="#418">418</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="419" href="#419">419</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;TODO:&nbsp;return&nbsp;an&nbsp;error&nbsp;if&nbsp;the&nbsp;token&nbsp;doesnt&nbsp;contain&nbsp;a&nbsp;me&nbsp;key.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="420" href="#420">420</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="421" href="#421">421</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;If&nbsp;everything&nbsp;checked&nbsp;out,&nbsp;return&nbsp;{&quot;me&quot;:&nbsp;&quot;https://example.com&quot;}&nbsp;response</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 422" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="422" href="#422">422</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">Response</span><span class="keyword">(</span><span class="default">200</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 423" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="423" href="#423">423</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'content-type'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'application/json'</span><span class="keyword">,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="424" href="#424">424</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'cache-control'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'no-store'</span><span class="keyword">,</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 425" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="425" href="#425">425</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">json_encode</span><span class="keyword">(</span><span class="default">array_filter</span><span class="keyword">(</span><span class="default">$tokenData</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">string</span><span class="default">&nbsp;</span><span class="default">$k</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="426" href="#426">426</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Prevent&nbsp;codes&nbsp;exchanged&nbsp;at&nbsp;the&nbsp;authorization&nbsp;endpoint&nbsp;from&nbsp;returning&nbsp;any&nbsp;information&nbsp;other&nbsp;than</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="427" href="#427">427</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;me&nbsp;and&nbsp;profile.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 428" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="428" href="#428">428</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">in_array</span><span class="keyword">(</span><span class="default">$k</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'me'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">'profile'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 429" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthEndpointTokenExchangeReturnsCorrectResponseForValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="429" href="#429">429</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">ARRAY_FILTER_USE_KEY</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="430" href="#430">430</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="431" href="#431">431</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="432" href="#432">432</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Because&nbsp;the&nbsp;special&nbsp;case&nbsp;above&nbsp;isnt&nbsp;allowed&nbsp;to&nbsp;be&nbsp;CSRF-protected,&nbsp;we&nbsp;have&nbsp;to&nbsp;do&nbsp;some&nbsp;rather&nbsp;silly</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="433" href="#433">433</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;closure&nbsp;gymnastics&nbsp;here&nbsp;to&nbsp;selectively-CSRF-protect&nbsp;requests&nbsp;which&nbsp;do&nbsp;need&nbsp;it.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="22 tests cover line 434" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="434" href="#434">434</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">csrfMiddleware</span><span class="default">-&gt;</span><span class="default">process</span><span class="keyword">(</span><span class="default">$request</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">Middleware</span><span class="default">\</span><span class="default">ClosureRequestHandler</span><span class="keyword">(</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">ServerRequestInterface</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="435" href="#435">435</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Wrap&nbsp;the&nbsp;entire&nbsp;user-facing&nbsp;handler&nbsp;in&nbsp;a&nbsp;try/catch&nbsp;block&nbsp;which&nbsp;catches&nbsp;any&nbsp;exception,&nbsp;converts&nbsp;it</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="436" href="#436">436</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;to&nbsp;IndieAuthException&nbsp;if&nbsp;necessary,&nbsp;then&nbsp;passes&nbsp;it&nbsp;to&nbsp;$this-&gt;handleException()&nbsp;to&nbsp;be&nbsp;turned&nbsp;into&nbsp;a</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="437" href="#437">437</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;response.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="438" href="#438">438</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="22 tests cover line 439" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="439" href="#439">439</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$queryParams</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="default">-&gt;</span><span class="default">getQueryParams</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="440" href="#440">440</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="441" href="#441">441</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/**&nbsp;@var&nbsp;ResponseInterface|null&nbsp;$clientIdResponse&nbsp;*/</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="442" href="#442">442</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/**&nbsp;@var&nbsp;string|null&nbsp;$clientIdEffectiveUrl&nbsp;*/</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="443" href="#443">443</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/**&nbsp;@var&nbsp;array|null&nbsp;$clientIdMf2&nbsp;*/</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="22 tests cover line 444" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="444" href="#444">444</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">list</span><span class="keyword">(</span><span class="default">$clientIdResponse</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$clientIdEffectiveUrl</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$clientIdMf2</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">null</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">null</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">null</span><span class="keyword">]</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="445" href="#445">445</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="446" href="#446">446</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;If&nbsp;this&nbsp;is&nbsp;an&nbsp;authorization&nbsp;or&nbsp;approval&nbsp;request&nbsp;(allowing&nbsp;POST&nbsp;requests&nbsp;as&nbsp;well&nbsp;to&nbsp;accommodate&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="447" href="#447">447</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;approval&nbsp;requests&nbsp;and&nbsp;custom&nbsp;auth&nbsp;form&nbsp;submission.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="22 tests cover line 448" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="448" href="#448">448</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">isIndieAuthAuthorizationRequest</span><span class="keyword">(</span><span class="default">$request</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'get'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">'post'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="20 tests cover line 449" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="449" href="#449">449</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">info</span><span class="keyword">(</span><span class="default">'Handling&nbsp;an&nbsp;authorization&nbsp;request'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'method'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="default">-&gt;</span><span class="default">getMethod</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="450" href="#450">450</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="451" href="#451">451</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Validate&nbsp;the&nbsp;Client&nbsp;ID.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="20 tests cover line 452" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="452" href="#452">452</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="keyword">isset</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'client_id'</span><span class="keyword">]</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">||</span><span class="default">&nbsp;</span><span class="default">false</span><span class="default">&nbsp;</span><span class="default">===</span><span class="default">&nbsp;</span><span class="default">filter_var</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'client_id'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">FILTER_VALIDATE_URL</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">||</span><span class="default">&nbsp;</span><span class="keyword">!</span><span class="default">isClientIdentifier</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'client_id'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 453" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="453" href="#453">453</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">warning</span><span class="keyword">(</span><span class="default">&quot;The&nbsp;client_id&nbsp;provided&nbsp;in&nbsp;an&nbsp;authorization&nbsp;request&nbsp;was&nbsp;not&nbsp;valid.&quot;</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 454" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="454" href="#454">454</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INVALID_CLIENT_ID</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="455" href="#455">455</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="456" href="#456">456</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="457" href="#457">457</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Validate&nbsp;the&nbsp;redirect&nbsp;URI.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="20 tests cover line 458" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="458" href="#458">458</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="keyword">isset</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'redirect_uri'</span><span class="keyword">]</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">||</span><span class="default">&nbsp;</span><span class="default">false</span><span class="default">&nbsp;</span><span class="default">===</span><span class="default">&nbsp;</span><span class="default">filter_var</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'redirect_uri'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">FILTER_VALIDATE_URL</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 459" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="459" href="#459">459</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">warning</span><span class="keyword">(</span><span class="default">&quot;The&nbsp;client_id&nbsp;provided&nbsp;in&nbsp;an&nbsp;authorization&nbsp;request&nbsp;was&nbsp;not&nbsp;valid.&quot;</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 460" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="460" href="#460">460</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INVALID_REDIRECT_URI</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="461" href="#461">461</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="462" href="#462">462</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="463" href="#463">463</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;How&nbsp;most&nbsp;errors&nbsp;are&nbsp;handled&nbsp;depends&nbsp;on&nbsp;whether&nbsp;or&nbsp;not&nbsp;the&nbsp;request&nbsp;has&nbsp;a&nbsp;valid&nbsp;redirect_uri.&nbsp;In</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="464" href="#464">464</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;order&nbsp;to&nbsp;know&nbsp;that,&nbsp;we&nbsp;need&nbsp;to&nbsp;also&nbsp;validate,&nbsp;fetch&nbsp;and&nbsp;parse&nbsp;the&nbsp;client_id.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="465" href="#465">465</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;If&nbsp;the&nbsp;request&nbsp;lacks&nbsp;a&nbsp;hash,&nbsp;or&nbsp;if&nbsp;the&nbsp;provided&nbsp;hash&nbsp;was&nbsp;invalid,&nbsp;perform&nbsp;the&nbsp;validation.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="19 tests cover line 466" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="466" href="#466">466</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$currentRequestHash</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">hashAuthorizationRequestParameters</span><span class="keyword">(</span><span class="default">$request</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">secret</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">null</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">null</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">requirePkce</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="19 tests cover line 467" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="467" href="#467">467</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="keyword">isset</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">self</span><span class="default">::</span><span class="default">HASH_QUERY_STRING_KEY</span><span class="keyword">]</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">or</span><span class="default">&nbsp;</span><span class="default">is_null</span><span class="keyword">(</span><span class="default">$currentRequestHash</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">or</span><span class="default">&nbsp;</span><span class="keyword">!</span><span class="default">hash_equals</span><span class="keyword">(</span><span class="default">$currentRequestHash</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">self</span><span class="default">::</span><span class="default">HASH_QUERY_STRING_KEY</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="468" href="#468">468</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="469" href="#469">469</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;All&nbsp;we&nbsp;need&nbsp;to&nbsp;know&nbsp;at&nbsp;this&nbsp;stage&nbsp;is&nbsp;whether&nbsp;the&nbsp;redirect_uri&nbsp;is&nbsp;valid.&nbsp;If&nbsp;it</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="470" href="#470">470</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;sufficiently&nbsp;matches&nbsp;the&nbsp;client_id,&nbsp;we&nbsp;dont&nbsp;(yet)&nbsp;need&nbsp;to&nbsp;fetch&nbsp;the&nbsp;client_id.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="16 tests cover line 471" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="471" href="#471">471</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="default">urlComponentsMatch</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'client_id'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'redirect_uri'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">PHP_URL_SCHEME</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">PHP_URL_HOST</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">PHP_URL_PORT</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="472" href="#472">472</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;If&nbsp;we&nbsp;do&nbsp;need&nbsp;to&nbsp;fetch&nbsp;the&nbsp;client_id,&nbsp;store&nbsp;the&nbsp;response&nbsp;and&nbsp;effective&nbsp;URL&nbsp;in&nbsp;variables</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="473" href="#473">473</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;we&nbsp;defined&nbsp;earlier,&nbsp;so&nbsp;theyre&nbsp;available&nbsp;to&nbsp;the&nbsp;approval&nbsp;request&nbsp;code&nbsp;path,&nbsp;which&nbsp;additionally</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="474" href="#474">474</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;needs&nbsp;to&nbsp;parse&nbsp;client_id&nbsp;for&nbsp;h-app&nbsp;markup.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="475" href="#475">475</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 476" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="476" href="#476">476</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">list</span><span class="keyword">(</span><span class="default">$clientIdResponse</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$clientIdEffectiveUrl</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">call_user_func</span><span class="keyword">(</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">httpGetWithEffectiveUrl</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'client_id'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 477" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="477" href="#477">477</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$clientIdMf2</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">Mf2</span><span class="default">\</span><span class="default">parse</span><span class="keyword">(</span><span class="default">(string)</span><span class="default">&nbsp;</span><span class="default">$clientIdResponse</span><span class="default">-&gt;</span><span class="default">getBody</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$clientIdEffectiveUrl</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="danger d-flex"><td class="col-1 text-right"><a id="478" href="#478">478</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="default">&nbsp;</span><span class="keyword">catch</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">ClientExceptionInterface</span><span class="default">&nbsp;</span><span class="keyword">|</span><span class="default">&nbsp;</span><span class="default">RequestExceptionInterface</span><span class="default">&nbsp;</span><span class="keyword">|</span><span class="default">&nbsp;</span><span class="default">NetworkExceptionInterface</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="danger d-flex"><td class="col-1 text-right"><a id="479" href="#479">479</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">error</span><span class="keyword">(</span><span class="default">&quot;Caught&nbsp;an&nbsp;HTTP&nbsp;exception&nbsp;while&nbsp;trying&nbsp;to&nbsp;fetch&nbsp;the&nbsp;client_id.&nbsp;Returning&nbsp;an&nbsp;error&nbsp;response.&quot;</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span></td></tr>
<tr class="danger d-flex"><td class="col-1 text-right"><a id="480" href="#480">480</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'client_id'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'client_id'</span><span class="keyword">]</span><span class="keyword">,</span></td></tr>
<tr class="danger d-flex"><td class="col-1 text-right"><a id="481" href="#481">481</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'exception'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="default">-&gt;</span><span class="default">__toString</span><span class="keyword">(</span><span class="keyword">)</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="482" href="#482">482</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="483" href="#483">483</a></td><td class="col-11 codeLine"></td></tr>
<tr class="danger d-flex"><td class="col-1 text-right"><a id="484" href="#484">484</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">HTTP_EXCEPTION_FETCHING_CLIENT_ID</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="danger d-flex"><td class="col-1 text-right"><a id="485" href="#485">485</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="default">&nbsp;</span><span class="keyword">catch</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">Exception</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="danger d-flex"><td class="col-1 text-right"><a id="486" href="#486">486</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">error</span><span class="keyword">(</span><span class="default">&quot;Caught&nbsp;an&nbsp;unknown&nbsp;exception&nbsp;while&nbsp;trying&nbsp;to&nbsp;fetch&nbsp;the&nbsp;client_id.&nbsp;Returning&nbsp;an&nbsp;error&nbsp;response.&quot;</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span></td></tr>
<tr class="danger d-flex"><td class="col-1 text-right"><a id="487" href="#487">487</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'exception'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="default">-&gt;</span><span class="default">__toString</span><span class="keyword">(</span><span class="keyword">)</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="488" href="#488">488</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="489" href="#489">489</a></td><td class="col-11 codeLine"></td></tr>
<tr class="danger d-flex"><td class="col-1 text-right"><a id="490" href="#490">490</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INTERNAL_EXCEPTION_FETCHING_CLIENT_ID</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="491" href="#491">491</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="492" href="#492">492</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="493" href="#493">493</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Search&nbsp;for&nbsp;all&nbsp;link@rel=redirect_uri&nbsp;at&nbsp;the&nbsp;client_id.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 494" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="494" href="#494">494</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$clientIdRedirectUris</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="keyword">]</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 495" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="495" href="#495">495</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">array_key_exists</span><span class="keyword">(</span><span class="default">'redirect_uri'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$clientIdMf2</span><span class="keyword">[</span><span class="default">'rels'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 496" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="496" href="#496">496</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$clientIdRedirectUris</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">array_merge</span><span class="keyword">(</span><span class="default">$clientIdRedirectUris</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$clientIdMf2</span><span class="keyword">[</span><span class="default">'rels'</span><span class="keyword">]</span><span class="keyword">[</span><span class="default">'redirect_uri'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="497" href="#497">497</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="498" href="#498">498</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 499" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="499" href="#499">499</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">foreach</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">HeaderParser</span><span class="default">::</span><span class="default">parse</span><span class="keyword">(</span><span class="default">$clientIdResponse</span><span class="default">-&gt;</span><span class="default">getHeader</span><span class="keyword">(</span><span class="default">'Link'</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">as</span><span class="default">&nbsp;</span><span class="default">$link</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 500" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="500" href="#500">500</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">array_key_exists</span><span class="keyword">(</span><span class="default">'rel'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$link</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">&amp;&amp;</span><span class="default">&nbsp;</span><span class="default">mb_strpos</span><span class="keyword">(</span><span class="string">&quot;</span><span class="string">&nbsp;</span><span class="string">{</span><span class="string">$link</span><span class="keyword">[</span><span class="string">'rel'</span><span class="keyword">]</span><span class="keyword">}</span><span class="string">&nbsp;</span><span class="string">&quot;</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">&quot;&nbsp;redirect_uri&nbsp;&quot;</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">!==</span><span class="default">&nbsp;</span><span class="default">false</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="501" href="#501">501</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Strip&nbsp;off&nbsp;the&nbsp;&lt;&nbsp;&gt;&nbsp;which&nbsp;surround&nbsp;the&nbsp;link&nbsp;URL&nbsp;for&nbsp;some&nbsp;reason.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 502" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="502" href="#502">502</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$clientIdRedirectUris</span><span class="keyword">[</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">substr</span><span class="keyword">(</span><span class="default">$link</span><span class="keyword">[</span><span class="default">0</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">1</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">strlen</span><span class="keyword">(</span><span class="default">$link</span><span class="keyword">[</span><span class="default">0</span><span class="keyword">]</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">-</span><span class="default">&nbsp;</span><span class="default">2</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="503" href="#503">503</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="504" href="#504">504</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="505" href="#505">505</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="506" href="#506">506</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;If&nbsp;the&nbsp;authority&nbsp;of&nbsp;the&nbsp;redirect_uri&nbsp;does&nbsp;not&nbsp;match&nbsp;the&nbsp;client_id,&nbsp;or&nbsp;exactly&nbsp;match&nbsp;one&nbsp;of&nbsp;their&nbsp;redirect&nbsp;URLs,&nbsp;return&nbsp;an&nbsp;error.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 507" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="507" href="#507">507</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="default">in_array</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'redirect_uri'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$clientIdRedirectUris</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 508" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="508" href="#508">508</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">warning</span><span class="keyword">(</span><span class="default">&quot;The&nbsp;provided&nbsp;redirect_uri&nbsp;did&nbsp;not&nbsp;match&nbsp;either&nbsp;the&nbsp;client_id,&nbsp;nor&nbsp;the&nbsp;discovered&nbsp;redirect&nbsp;URIs.&quot;</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 509" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="509" href="#509">509</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'provided_redirect_uri'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'redirect_uri'</span><span class="keyword">]</span><span class="keyword">,</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 510" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="510" href="#510">510</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'provided_client_id'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'client_id'</span><span class="keyword">]</span><span class="keyword">,</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 511" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="511" href="#511">511</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'discovered_redirect_uris'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$clientIdRedirectUris</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="512" href="#512">512</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="513" href="#513">513</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 514" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="514" href="#514">514</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INVALID_REDIRECT_URI</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="515" href="#515">515</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="516" href="#516">516</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="517" href="#517">517</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="518" href="#518">518</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="519" href="#519">519</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;From&nbsp;now&nbsp;on,&nbsp;we&nbsp;can&nbsp;assume&nbsp;that&nbsp;redirect_uri&nbsp;is&nbsp;valid.&nbsp;Any&nbsp;IndieAuth-related&nbsp;errors&nbsp;should&nbsp;be</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="520" href="#520">520</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;reported&nbsp;by&nbsp;redirecting&nbsp;to&nbsp;redirect_uri&nbsp;with&nbsp;error&nbsp;parameters.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="521" href="#521">521</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="522" href="#522">522</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Validate&nbsp;the&nbsp;state&nbsp;parameter.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="17 tests cover line 523" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="523" href="#523">523</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="keyword">isset</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'state'</span><span class="keyword">]</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">or</span><span class="default">&nbsp;</span><span class="keyword">!</span><span class="default">isValidState</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'state'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 524" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="524" href="#524">524</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">warning</span><span class="keyword">(</span><span class="default">&quot;The&nbsp;state&nbsp;provided&nbsp;in&nbsp;an&nbsp;authorization&nbsp;request&nbsp;was&nbsp;not&nbsp;valid.&quot;</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 525" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="525" href="#525">525</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INVALID_STATE</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="526" href="#526">526</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="527" href="#527">527</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;From&nbsp;now&nbsp;on,&nbsp;any&nbsp;redirect&nbsp;error&nbsp;responses&nbsp;should&nbsp;include&nbsp;the&nbsp;state&nbsp;parameter.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="528" href="#528">528</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;This&nbsp;is&nbsp;handled&nbsp;automatically&nbsp;in&nbsp;`handleException()`&nbsp;and&nbsp;is&nbsp;only&nbsp;noted&nbsp;here</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="529" href="#529">529</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;for&nbsp;reference.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="530" href="#530">530</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="531" href="#531">531</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;If&nbsp;either&nbsp;PKCE&nbsp;parameter&nbsp;is&nbsp;present,&nbsp;validate&nbsp;both.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="17 tests cover line 532" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="532" href="#532">532</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">isset</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'code_challenge'</span><span class="keyword">]</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">or</span><span class="default">&nbsp;</span><span class="keyword">isset</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'code_challenge_method'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="15 tests cover line 533" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="533" href="#533">533</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="keyword">isset</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'code_challenge'</span><span class="keyword">]</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">or</span><span class="default">&nbsp;</span><span class="keyword">!</span><span class="default">isValidCodeChallenge</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'code_challenge'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 534" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="534" href="#534">534</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">warning</span><span class="keyword">(</span><span class="default">&quot;The&nbsp;code_challenge&nbsp;provided&nbsp;in&nbsp;an&nbsp;authorization&nbsp;request&nbsp;was&nbsp;not&nbsp;valid.&quot;</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 535" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="535" href="#535">535</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INVALID_CODE_CHALLENGE</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="536" href="#536">536</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="537" href="#537">537</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="14 tests cover line 538" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="538" href="#538">538</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="keyword">isset</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'code_challenge_method'</span><span class="keyword">]</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">or</span><span class="default">&nbsp;</span><span class="keyword">!</span><span class="default">in_array</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'code_challenge_method'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'S256'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">'plain'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 539" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="539" href="#539">539</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">error</span><span class="keyword">(</span><span class="default">&quot;The&nbsp;code_challenge_method&nbsp;parameter&nbsp;was&nbsp;missing&nbsp;or&nbsp;invalid.&quot;</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="14 tests cover line 540" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="540" href="#540">540</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INVALID_CODE_CHALLENGE</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="541" href="#541">541</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="542" href="#542">542</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="default">&nbsp;</span><span class="keyword">else</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="543" href="#543">543</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;If&nbsp;neither&nbsp;PKCE&nbsp;parameter&nbsp;is&nbsp;defined,&nbsp;and&nbsp;PKCE&nbsp;is&nbsp;required,&nbsp;throw&nbsp;an&nbsp;error.&nbsp;Otherwise,&nbsp;proceed.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 544" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="544" href="#544">544</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">requirePkce</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 545" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="545" href="#545">545</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">warning</span><span class="keyword">(</span><span class="default">&quot;PKCE&nbsp;is&nbsp;required,&nbsp;and&nbsp;both&nbsp;code_challenge&nbsp;and&nbsp;code_challenge_method&nbsp;were&nbsp;missing.&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 546" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="546" href="#546">546</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INVALID_REQUEST_REDIRECT</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="547" href="#547">547</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="548" href="#548">548</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="549" href="#549">549</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="550" href="#550">550</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Validate&nbsp;the&nbsp;scope&nbsp;parameter,&nbsp;if&nbsp;provided.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="14 tests cover line 551" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="551" href="#551">551</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">array_key_exists</span><span class="keyword">(</span><span class="default">'scope'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">&amp;&amp;</span><span class="default">&nbsp;</span><span class="keyword">!</span><span class="default">isValidScope</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'scope'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 552" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="552" href="#552">552</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">warning</span><span class="keyword">(</span><span class="default">&quot;The&nbsp;scope&nbsp;provided&nbsp;in&nbsp;an&nbsp;authorization&nbsp;request&nbsp;was&nbsp;not&nbsp;valid.&quot;</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 553" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="553" href="#553">553</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INVALID_SCOPE</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="554" href="#554">554</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="555" href="#555">555</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="556" href="#556">556</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Normalise&nbsp;the&nbsp;me&nbsp;parameter,&nbsp;if&nbsp;it&nbsp;exists.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="13 tests cover line 557" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="557" href="#557">557</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">array_key_exists</span><span class="keyword">(</span><span class="default">'me'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 558" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="558" href="#558">558</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'me'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">IndieAuthClient</span><span class="default">::</span><span class="default">normalizeMeURL</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'me'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="559" href="#559">559</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;If&nbsp;the&nbsp;me&nbsp;parameter&nbsp;is&nbsp;not&nbsp;a&nbsp;valid&nbsp;profile&nbsp;URL,&nbsp;ignore&nbsp;it.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 560" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="560" href="#560">560</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">false</span><span class="default">&nbsp;</span><span class="default">===</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'me'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="default">||</span><span class="default">&nbsp;</span><span class="keyword">!</span><span class="default">isProfileUrl</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'me'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 561" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="561" href="#561">561</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'me'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">null</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="562" href="#562">562</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="563" href="#563">563</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="564" href="#564">564</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="565" href="#565">565</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Build&nbsp;a&nbsp;URL&nbsp;containing&nbsp;the&nbsp;indieauth&nbsp;authorization&nbsp;request&nbsp;parameters,&nbsp;hashing&nbsp;them</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="566" href="#566">566</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;to&nbsp;protect&nbsp;them&nbsp;from&nbsp;being&nbsp;changed.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="567" href="#567">567</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Make&nbsp;a&nbsp;hash&nbsp;of&nbsp;the&nbsp;protected&nbsp;indieauth-specific&nbsp;parameters.&nbsp;If&nbsp;PKCE&nbsp;is&nbsp;in&nbsp;use,&nbsp;include&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="568" href="#568">568</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;the&nbsp;PKCE&nbsp;parameters&nbsp;in&nbsp;the&nbsp;hash.&nbsp;Otherwise,&nbsp;leave&nbsp;them&nbsp;out.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="13 tests cover line 569" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="569" href="#569">569</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$hash</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">hashAuthorizationRequestParameters</span><span class="keyword">(</span><span class="default">$request</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">secret</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">null</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">null</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">requirePkce</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="570" href="#570">570</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Operate&nbsp;on&nbsp;a&nbsp;copy&nbsp;of&nbsp;$queryParams,&nbsp;otherwise&nbsp;requests&nbsp;will&nbsp;always&nbsp;have&nbsp;a&nbsp;valid&nbsp;hash!</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="13 tests cover line 571" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="571" href="#571">571</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$redirectQueryParams</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="13 tests cover line 572" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="572" href="#572">572</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$redirectQueryParams</span><span class="keyword">[</span><span class="default">self</span><span class="default">::</span><span class="default">HASH_QUERY_STRING_KEY</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$hash</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="13 tests cover line 573" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="573" href="#573">573</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$authenticationRedirect</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="default">-&gt;</span><span class="default">getUri</span><span class="keyword">(</span><span class="keyword">)</span><span class="default">-&gt;</span><span class="default">withQuery</span><span class="keyword">(</span><span class="default">buildQueryString</span><span class="keyword">(</span><span class="default">$redirectQueryParams</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">-&gt;</span><span class="default">__toString</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="574" href="#574">574</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="575" href="#575">575</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;User-facing&nbsp;requests&nbsp;always&nbsp;start&nbsp;by&nbsp;calling&nbsp;the&nbsp;authentication&nbsp;request&nbsp;callback.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="13 tests cover line 576" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="576" href="#576">576</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">info</span><span class="keyword">(</span><span class="default">'Calling&nbsp;handle_authentication_request&nbsp;callback'</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="13 tests cover line 577" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="577" href="#577">577</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$authenticationResult</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">call_user_func</span><span class="keyword">(</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">handleAuthenticationRequestCallback</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$authenticationRedirect</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'me'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="default">??</span><span class="default">&nbsp;</span><span class="default">null</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="578" href="#578">578</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="579" href="#579">579</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;If&nbsp;the&nbsp;authentication&nbsp;handler&nbsp;returned&nbsp;a&nbsp;Response,&nbsp;return&nbsp;that&nbsp;as-is.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="13 tests cover line 580" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="580" href="#580">580</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">$authenticationResult</span><span class="default">&nbsp;</span><span class="keyword">instanceof</span><span class="default">&nbsp;</span><span class="default">ResponseInterface</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 581" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="581" href="#581">581</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">$authenticationResult</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="12 tests cover line 582" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="582" href="#582">582</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="default">&nbsp;</span><span class="keyword">elseif</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">is_array</span><span class="keyword">(</span><span class="default">$authenticationResult</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="583" href="#583">583</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Check&nbsp;the&nbsp;resulting&nbsp;array&nbsp;for&nbsp;errors.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="11 tests cover line 584" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="584" href="#584">584</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="default">array_key_exists</span><span class="keyword">(</span><span class="default">'me'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$authenticationResult</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 585" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="585" href="#585">585</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">error</span><span class="keyword">(</span><span class="default">'The&nbsp;handle_authentication_request&nbsp;callback&nbsp;returned&nbsp;an&nbsp;array&nbsp;with&nbsp;no&nbsp;me&nbsp;key.'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'array'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$authenticationResult</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 586" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="586" href="#586">586</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">AUTHENTICATION_CALLBACK_MISSING_ME_PARAM</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="587" href="#587">587</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="588" href="#588">588</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="589" href="#589">589</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;If&nbsp;this&nbsp;is&nbsp;a&nbsp;POST&nbsp;request&nbsp;sent&nbsp;from&nbsp;the&nbsp;authorization&nbsp;(i.e.&nbsp;scope-choosing)&nbsp;form:</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="10 tests cover line 590" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="590" href="#590">590</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">isAuthorizationApprovalRequest</span><span class="keyword">(</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="591" href="#591">591</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Authorization&nbsp;approval&nbsp;requests&nbsp;MUST&nbsp;include&nbsp;a&nbsp;hash&nbsp;protecting&nbsp;the&nbsp;sensitive&nbsp;IndieAuth</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="592" href="#592">592</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;authorization&nbsp;request&nbsp;parameters&nbsp;from&nbsp;being&nbsp;changed,&nbsp;e.g.&nbsp;by&nbsp;a&nbsp;malicious&nbsp;script&nbsp;which</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="593" href="#593">593</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;found&nbsp;its&nbsp;way&nbsp;onto&nbsp;the&nbsp;authorization&nbsp;form.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="5 tests cover line 594" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="594" href="#594">594</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="default">array_key_exists</span><span class="keyword">(</span><span class="default">self</span><span class="default">::</span><span class="default">HASH_QUERY_STRING_KEY</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 595" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="595" href="#595">595</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">warning</span><span class="keyword">(</span><span class="default">&quot;An&nbsp;authorization&nbsp;approval&nbsp;request&nbsp;did&nbsp;not&nbsp;have&nbsp;a&nbsp;&quot;</span><span class="default">&nbsp;</span><span class="keyword">.</span><span class="default">&nbsp;</span><span class="default">self</span><span class="default">::</span><span class="default">HASH_QUERY_STRING_KEY</span><span class="default">&nbsp;</span><span class="keyword">.</span><span class="default">&nbsp;</span><span class="default">&quot;&nbsp;parameter.&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 596" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="596" href="#596">596</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">AUTHORIZATION_APPROVAL_REQUEST_MISSING_HASH</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="597" href="#597">597</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="598" href="#598">598</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 599" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="599" href="#599">599</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$expectedHash</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">hashAuthorizationRequestParameters</span><span class="keyword">(</span><span class="default">$request</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">secret</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">null</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">null</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">requirePkce</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 600" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="600" href="#600">600</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="keyword">isset</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">self</span><span class="default">::</span><span class="default">HASH_QUERY_STRING_KEY</span><span class="keyword">]</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">or</span><span class="default">&nbsp;</span><span class="default">is_null</span><span class="keyword">(</span><span class="default">$expectedHash</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">or</span><span class="default">&nbsp;</span><span class="keyword">!</span><span class="default">hash_equals</span><span class="keyword">(</span><span class="default">$expectedHash</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">self</span><span class="default">::</span><span class="default">HASH_QUERY_STRING_KEY</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 601" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="601" href="#601">601</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">warning</span><span class="keyword">(</span><span class="default">&quot;The&nbsp;hash&nbsp;provided&nbsp;in&nbsp;the&nbsp;URL&nbsp;was&nbsp;invalid!&quot;</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 602" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="602" href="#602">602</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'expected'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$expectedHash</span><span class="keyword">,</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 603" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="603" href="#603">603</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'actual'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">self</span><span class="default">::</span><span class="default">HASH_QUERY_STRING_KEY</span><span class="keyword">]</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="604" href="#604">604</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 605" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="605" href="#605">605</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">AUTHORIZATION_APPROVAL_REQUEST_INVALID_HASH</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="606" href="#606">606</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="607" href="#607">607</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="608" href="#608">608</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Assemble&nbsp;the&nbsp;data&nbsp;for&nbsp;the&nbsp;authorization&nbsp;code,&nbsp;store&nbsp;it&nbsp;somewhere&nbsp;persistent.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 609" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="609" href="#609">609</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$code</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">array_merge</span><span class="keyword">(</span><span class="default">$authenticationResult</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 610" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="610" href="#610">610</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'client_id'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'client_id'</span><span class="keyword">]</span><span class="keyword">,</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 611" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="611" href="#611">611</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'redirect_uri'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'redirect_uri'</span><span class="keyword">]</span><span class="keyword">,</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 612" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="612" href="#612">612</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'state'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'state'</span><span class="keyword">]</span><span class="keyword">,</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 613" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="613" href="#613">613</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'code_challenge'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'code_challenge'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="default">??</span><span class="default">&nbsp;</span><span class="default">null</span><span class="keyword">,</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 614" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="614" href="#614">614</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'code_challenge_method'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'code_challenge_method'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="default">??</span><span class="default">&nbsp;</span><span class="default">null</span><span class="keyword">,</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 615" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="615" href="#615">615</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'requested_scope'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'scope'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="default">??</span><span class="default">&nbsp;</span><span class="default">''</span><span class="keyword">,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="616" href="#616">616</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="617" href="#617">617</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="618" href="#618">618</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Pass&nbsp;it&nbsp;to&nbsp;the&nbsp;auth&nbsp;code&nbsp;customisation&nbsp;callback.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 619" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="619" href="#619">619</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$code</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">authorizationForm</span><span class="default">-&gt;</span><span class="default">transformAuthorizationCode</span><span class="keyword">(</span><span class="default">$request</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$code</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="620" href="#620">620</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="621" href="#621">621</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Store&nbsp;the&nbsp;authorization&nbsp;code.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 622" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="622" href="#622">622</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$authCode</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">tokenStorage</span><span class="default">-&gt;</span><span class="default">createAuthCode</span><span class="keyword">(</span><span class="default">$code</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 623" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="623" href="#623">623</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">is_null</span><span class="keyword">(</span><span class="default">$authCode</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="624" href="#624">624</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;If&nbsp;saving&nbsp;the&nbsp;authorization&nbsp;code&nbsp;failed&nbsp;silently,&nbsp;there&nbsp;isnt&nbsp;much&nbsp;we&nbsp;can&nbsp;do&nbsp;about&nbsp;it,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="625" href="#625">625</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;but&nbsp;should&nbsp;at&nbsp;least&nbsp;log&nbsp;and&nbsp;return&nbsp;an&nbsp;error.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 626" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="626" href="#626">626</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">error</span><span class="keyword">(</span><span class="default">&quot;Saving&nbsp;the&nbsp;authorization&nbsp;code&nbsp;failed&nbsp;and&nbsp;returned&nbsp;false&nbsp;without&nbsp;raising&nbsp;an&nbsp;exception.&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 627" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="627" href="#627">627</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INTERNAL_ERROR_REDIRECT</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="628" href="#628">628</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="629" href="#629">629</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="630" href="#630">630</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Return&nbsp;a&nbsp;redirect&nbsp;to&nbsp;the&nbsp;client&nbsp;app.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 631" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="631" href="#631">631</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">Response</span><span class="keyword">(</span><span class="default">302</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 632" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="632" href="#632">632</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'Location'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">appendQueryParams</span><span class="keyword">(</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'redirect_uri'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 633" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="633" href="#633">633</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'code'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$authCode</span><span class="keyword">,</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 634" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="634" href="#634">634</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'state'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$code</span><span class="keyword">[</span><span class="default">'state'</span><span class="keyword">]</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="635" href="#635">635</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">,</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 636" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="636" href="#636">636</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'Cache-control'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'no-cache'</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="637" href="#637">637</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="638" href="#638">638</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="639" href="#639">639</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="640" href="#640">640</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Otherwise,&nbsp;the&nbsp;user&nbsp;is&nbsp;authenticated&nbsp;and&nbsp;needs&nbsp;to&nbsp;authorize&nbsp;the&nbsp;client&nbsp;app&nbsp;+&nbsp;choose&nbsp;scopes.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="641" href="#641">641</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="642" href="#642">642</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Fetch&nbsp;the&nbsp;client_id&nbsp;URL&nbsp;to&nbsp;find&nbsp;information&nbsp;about&nbsp;the&nbsp;client&nbsp;to&nbsp;present&nbsp;to&nbsp;the&nbsp;user.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="643" href="#643">643</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;TODO:&nbsp;in&nbsp;order&nbsp;to&nbsp;comply&nbsp;with&nbsp;https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2.1,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="644" href="#644">644</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;it&nbsp;may&nbsp;be&nbsp;necessary&nbsp;to&nbsp;do&nbsp;this&nbsp;before&nbsp;returning&nbsp;any&nbsp;other&nbsp;kind&nbsp;of&nbsp;error&nbsp;response,&nbsp;as,&nbsp;per</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="645" href="#645">645</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;the&nbsp;spec,&nbsp;errors&nbsp;should&nbsp;only&nbsp;be&nbsp;shown&nbsp;to&nbsp;the&nbsp;user&nbsp;if&nbsp;the&nbsp;client_id&nbsp;and&nbsp;redirect_uri&nbsp;parameters</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="646" href="#646">646</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;are&nbsp;missing&nbsp;or&nbsp;invalid.&nbsp;Otherwise,&nbsp;they&nbsp;should&nbsp;be&nbsp;sent&nbsp;back&nbsp;to&nbsp;the&nbsp;client&nbsp;with&nbsp;an&nbsp;error</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="647" href="#647">647</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;redirect&nbsp;response.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="5 tests cover line 648" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="648" href="#648">648</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">is_null</span><span class="keyword">(</span><span class="default">$clientIdResponse</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">||</span><span class="default">&nbsp;</span><span class="default">is_null</span><span class="keyword">(</span><span class="default">$clientIdEffectiveUrl</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">||</span><span class="default">&nbsp;</span><span class="default">is_null</span><span class="keyword">(</span><span class="default">$clientIdMf2</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="649" href="#649">649</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="650" href="#650">650</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/**&nbsp;@var&nbsp;ResponseInterface&nbsp;$clientIdResponse&nbsp;*/</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 651" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="651" href="#651">651</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">list</span><span class="keyword">(</span><span class="default">$clientIdResponse</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$clientIdEffectiveUrl</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">call_user_func</span><span class="keyword">(</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">httpGetWithEffectiveUrl</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'client_id'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 652" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="652" href="#652">652</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$clientIdMf2</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">Mf2</span><span class="default">\</span><span class="default">parse</span><span class="keyword">(</span><span class="default">(string)</span><span class="default">&nbsp;</span><span class="default">$clientIdResponse</span><span class="default">-&gt;</span><span class="default">getBody</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$clientIdEffectiveUrl</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 653" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="653" href="#653">653</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="default">&nbsp;</span><span class="keyword">catch</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">ClientExceptionInterface</span><span class="default">&nbsp;</span><span class="keyword">|</span><span class="default">&nbsp;</span><span class="default">RequestExceptionInterface</span><span class="default">&nbsp;</span><span class="keyword">|</span><span class="default">&nbsp;</span><span class="default">NetworkExceptionInterface</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 654" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="654" href="#654">654</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">error</span><span class="keyword">(</span><span class="default">&quot;Caught&nbsp;an&nbsp;HTTP&nbsp;exception&nbsp;while&nbsp;trying&nbsp;to&nbsp;fetch&nbsp;the&nbsp;client_id.&nbsp;Returning&nbsp;an&nbsp;error&nbsp;response.&quot;</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 655" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="655" href="#655">655</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'client_id'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'client_id'</span><span class="keyword">]</span><span class="keyword">,</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 656" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="656" href="#656">656</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'exception'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="default">-&gt;</span><span class="default">__toString</span><span class="keyword">(</span><span class="keyword">)</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="657" href="#657">657</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="658" href="#658">658</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="659" href="#659">659</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;At&nbsp;this&nbsp;point&nbsp;in&nbsp;the&nbsp;flow,&nbsp;weve&nbsp;already&nbsp;guaranteed&nbsp;that&nbsp;the&nbsp;redirect_uri&nbsp;is&nbsp;valid,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="660" href="#660">660</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;so&nbsp;in&nbsp;theory&nbsp;we&nbsp;should&nbsp;report&nbsp;these&nbsp;errors&nbsp;by&nbsp;redirecting&nbsp;there.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 661" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="661" href="#661">661</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INTERNAL_ERROR_REDIRECT</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 662" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="662" href="#662">662</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="default">&nbsp;</span><span class="keyword">catch</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">Exception</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 663" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="663" href="#663">663</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">error</span><span class="keyword">(</span><span class="default">&quot;Caught&nbsp;an&nbsp;unknown&nbsp;exception&nbsp;while&nbsp;trying&nbsp;to&nbsp;fetch&nbsp;the&nbsp;client_id.&nbsp;Returning&nbsp;an&nbsp;error&nbsp;response.&quot;</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 664" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="664" href="#664">664</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'exception'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="default">-&gt;</span><span class="default">__toString</span><span class="keyword">(</span><span class="keyword">)</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="665" href="#665">665</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="666" href="#666">666</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 667" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="667" href="#667">667</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INTERNAL_ERROR_REDIRECT</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="668" href="#668">668</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="669" href="#669">669</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="670" href="#670">670</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="671" href="#671">671</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Search&nbsp;for&nbsp;an&nbsp;h-app&nbsp;with&nbsp;u-url&nbsp;matching&nbsp;the&nbsp;client_id.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 672" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="672" href="#672">672</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$clientHApps</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">M</span><span class="default">\</span><span class="default">findMicroformatsByProperty</span><span class="keyword">(</span><span class="default">M</span><span class="default">\</span><span class="default">findMicroformatsByType</span><span class="keyword">(</span><span class="default">$clientIdMf2</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">'h-app'</span><span class="keyword">)</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">'url'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$queryParams</span><span class="keyword">[</span><span class="default">'client_id'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 673" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="673" href="#673">673</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$clientHApp</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="keyword">empty</span><span class="keyword">(</span><span class="default">$clientHApps</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">?</span><span class="default">&nbsp;</span><span class="default">null</span><span class="default">&nbsp;</span><span class="keyword">:</span><span class="default">&nbsp;</span><span class="default">$clientHApps</span><span class="keyword">[</span><span class="default">0</span><span class="keyword">]</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="674" href="#674">674</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="675" href="#675">675</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Present&nbsp;the&nbsp;authorization&nbsp;UI.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 676" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="676" href="#676">676</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">authorizationForm</span><span class="default">-&gt;</span><span class="default">showForm</span><span class="keyword">(</span><span class="default">$request</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$authenticationResult</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$authenticationRedirect</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$clientHApp</span><span class="keyword">)</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 677" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="677" href="#677">677</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">-&gt;</span><span class="default">withAddedHeader</span><span class="keyword">(</span><span class="default">'Cache-control'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">'no-cache'</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="678" href="#678">678</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="679" href="#679">679</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="680" href="#680">680</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="681" href="#681">681</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;If&nbsp;the&nbsp;request&nbsp;isnt&nbsp;an&nbsp;IndieAuth&nbsp;Authorization&nbsp;or&nbsp;Code-redeeming&nbsp;request,&nbsp;its&nbsp;either&nbsp;an&nbsp;invalid</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="682" href="#682">682</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;request&nbsp;or&nbsp;something&nbsp;to&nbsp;do&nbsp;with&nbsp;a&nbsp;custom&nbsp;auth&nbsp;handler&nbsp;(e.g.&nbsp;sending&nbsp;a&nbsp;one-time&nbsp;code&nbsp;in&nbsp;an&nbsp;email.)</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 683" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="683" href="#683">683</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$nonIndieAuthRequestResult</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">call_user_func</span><span class="keyword">(</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">handleNonIndieAuthRequest</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 684" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="684" href="#684">684</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">$nonIndieAuthRequestResult</span><span class="default">&nbsp;</span><span class="keyword">instanceof</span><span class="default">&nbsp;</span><span class="default">ResponseInterface</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 685" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="685" href="#685">685</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">$nonIndieAuthRequestResult</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="686" href="#686">686</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="default">&nbsp;</span><span class="keyword">else</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="687" href="#687">687</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;In&nbsp;this&nbsp;code&nbsp;path&nbsp;we&nbsp;have&nbsp;not&nbsp;validated&nbsp;the&nbsp;redirect_uri,&nbsp;so&nbsp;show&nbsp;a&nbsp;regular&nbsp;error&nbsp;page</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="688" href="#688">688</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;rather&nbsp;than&nbsp;returning&nbsp;a&nbsp;redirect&nbsp;error.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 689" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="689" href="#689">689</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INTERNAL_ERROR</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="690" href="#690">690</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="14 tests cover line 691" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="691" href="#691">691</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="default">&nbsp;</span><span class="keyword">catch</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="692" href="#692">692</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;All&nbsp;IndieAuthExceptions&nbsp;will&nbsp;already&nbsp;have&nbsp;been&nbsp;logged.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="14 tests cover line 693" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="693" href="#693">693</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">handleException</span><span class="keyword">(</span><span class="default">$e</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 694" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="694" href="#694">694</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="default">&nbsp;</span><span class="keyword">catch</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">Exception</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="695" href="#695">695</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Unknown&nbsp;exceptions&nbsp;will&nbsp;not&nbsp;have&nbsp;been&nbsp;logged;&nbsp;do&nbsp;so&nbsp;now.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 696" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="696" href="#696">696</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">error</span><span class="keyword">(</span><span class="string">&quot;</span><span class="string">Caught&nbsp;unknown&nbsp;exception:&nbsp;</span><span class="string">{</span><span class="string">$e</span><span class="keyword">}</span><span class="string">&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 697" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="697" href="#697">697</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">handleException</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">0</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="698" href="#698">698</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="22 tests cover line 699" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testUnauthenticatedRequestReturnsAuthenticationResponse&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdSufficientlyMatchesRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkHeaderRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsAuthorizationFormIfClientIdExactlyMatchesParsedLinkElementRedirectUri&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testFindsFirstHAppExactlyMatchingClientId&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testValidApprovalRequestIsHandledCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testResponseReturnedFromNonIndieAuthRequestHandler&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="699" href="#699">699</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">;</span><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class="warning d-flex"><td class="col-1 text-right"><a id="700" href="#700">700</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="701" href="#701">701</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="702" href="#702">702</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/**</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="703" href="#703">703</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Handle&nbsp;Token&nbsp;Endpoint&nbsp;Request</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="704" href="#704">704</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="705" href="#705">705</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Handles&nbsp;requests&nbsp;to&nbsp;the&nbsp;IndieAuth&nbsp;token&nbsp;endpoint.&nbsp;The&nbsp;logical&nbsp;flow&nbsp;can&nbsp;be&nbsp;summarised&nbsp;as&nbsp;follows:</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="706" href="#706">706</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="707" href="#707">707</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;Check&nbsp;that&nbsp;the&nbsp;request&nbsp;is&nbsp;a&nbsp;code&nbsp;redeeming&nbsp;request.&nbsp;Return&nbsp;an&nbsp;error&nbsp;if&nbsp;not.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="708" href="#708">708</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;Ensure&nbsp;that&nbsp;all&nbsp;required&nbsp;parameters&nbsp;are&nbsp;present.&nbsp;Return&nbsp;an&nbsp;error&nbsp;if&nbsp;not.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="709" href="#709">709</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;Attempt&nbsp;to&nbsp;exchange&nbsp;the&nbsp;`code`&nbsp;parameter&nbsp;for&nbsp;an&nbsp;access&nbsp;token.&nbsp;Return&nbsp;an&nbsp;error&nbsp;if&nbsp;it&nbsp;fails.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="710" href="#710">710</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;Make&nbsp;sure&nbsp;the&nbsp;client_id&nbsp;and&nbsp;redirect_uri&nbsp;request&nbsp;parameters&nbsp;match&nbsp;those&nbsp;stored&nbsp;in&nbsp;the&nbsp;auth&nbsp;code.&nbsp;If&nbsp;not,&nbsp;revoke&nbsp;the&nbsp;access&nbsp;token&nbsp;and&nbsp;return&nbsp;an&nbsp;error.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="711" href="#711">711</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;Make&nbsp;sure&nbsp;the&nbsp;provided&nbsp;code_verifier&nbsp;hashes&nbsp;to&nbsp;the&nbsp;code_challenge&nbsp;stored&nbsp;in&nbsp;the&nbsp;auth&nbsp;code.&nbsp;If&nbsp;not,&nbsp;revoke&nbsp;the&nbsp;access&nbsp;token&nbsp;and&nbsp;return&nbsp;an&nbsp;error.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="712" href="#712">712</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;Make&nbsp;sure&nbsp;the&nbsp;granted&nbsp;scope&nbsp;stored&nbsp;in&nbsp;the&nbsp;auth&nbsp;code&nbsp;is&nbsp;not&nbsp;empty.&nbsp;If&nbsp;it&nbsp;is,&nbsp;revoke&nbsp;the&nbsp;access&nbsp;token&nbsp;and&nbsp;return&nbsp;an&nbsp;error.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="713" href="#713">713</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;*&nbsp;Otherwise,&nbsp;return&nbsp;a&nbsp;success&nbsp;response&nbsp;containing&nbsp;information&nbsp;about&nbsp;the&nbsp;issued&nbsp;access&nbsp;token.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="714" href="#714">714</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="715" href="#715">715</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;This&nbsp;method&nbsp;must&nbsp;NOT&nbsp;be&nbsp;CSRF-protected&nbsp;as&nbsp;it&nbsp;accepts&nbsp;external&nbsp;requests&nbsp;from&nbsp;client&nbsp;apps.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="716" href="#716">716</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="717" href="#717">717</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;ServerRequestInterface&nbsp;$request</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="718" href="#718">718</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;ResponseInterface</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="719" href="#719">719</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="720" href="#720">720</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">handleTokenEndpointRequest</span><span class="keyword">(</span><span class="default">ServerRequestInterface</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">:</span><span class="default">&nbsp;</span><span class="default">ResponseInterface</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="8 tests cover line 721" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="721" href="#721">721</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">isIndieAuthAuthorizationCodeRedeemingRequest</span><span class="keyword">(</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="7 tests cover line 722" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="722" href="#722">722</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">info</span><span class="keyword">(</span><span class="default">'Handling&nbsp;a&nbsp;request&nbsp;to&nbsp;redeem&nbsp;an&nbsp;authorization&nbsp;code&nbsp;for&nbsp;profile&nbsp;information.'</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="723" href="#723">723</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="7 tests cover line 724" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="724" href="#724">724</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$bodyParams</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="default">-&gt;</span><span class="default">getParsedBody</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="725" href="#725">725</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="7 tests cover line 726" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="726" href="#726">726</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="keyword">isset</span><span class="keyword">(</span><span class="default">$bodyParams</span><span class="keyword">[</span><span class="default">'code'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 727" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="727" href="#727">727</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">warning</span><span class="keyword">(</span><span class="default">'The&nbsp;exchange&nbsp;request&nbsp;was&nbsp;missing&nbsp;the&nbsp;code&nbsp;parameter.&nbsp;Returning&nbsp;an&nbsp;error&nbsp;response.'</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 728" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="728" href="#728">728</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">Response</span><span class="keyword">(</span><span class="default">400</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'content-type'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'application/json'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">json_encode</span><span class="keyword">(</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 729" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfCodeParameterIsMissing&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="729" href="#729">729</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'error'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'invalid_request'</span><span class="keyword">,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="730" href="#730">730</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'error_description'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'The&nbsp;code&nbsp;parameter&nbsp;was&nbsp;missing.'</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="731" href="#731">731</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="732" href="#732">732</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="733" href="#733">733</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="734" href="#734">734</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Attempt&nbsp;to&nbsp;internally&nbsp;exchange&nbsp;the&nbsp;provided&nbsp;auth&nbsp;code&nbsp;for&nbsp;an&nbsp;access&nbsp;token.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="735" href="#735">735</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;We&nbsp;do&nbsp;this&nbsp;before&nbsp;anything&nbsp;else&nbsp;so&nbsp;that&nbsp;the&nbsp;auth&nbsp;code&nbsp;is&nbsp;invalidated&nbsp;as&nbsp;soon&nbsp;as&nbsp;the&nbsp;request&nbsp;starts,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="736" href="#736">736</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;and&nbsp;the&nbsp;resulting&nbsp;access&nbsp;token&nbsp;is&nbsp;revoked&nbsp;if&nbsp;we&nbsp;encounter&nbsp;an&nbsp;error.&nbsp;This&nbsp;ends&nbsp;up&nbsp;providing&nbsp;a&nbsp;simpler</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="737" href="#737">737</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;and&nbsp;more&nbsp;flexible&nbsp;interface&nbsp;for&nbsp;TokenStorage&nbsp;implementors.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="738" href="#738">738</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="739" href="#739">739</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Call&nbsp;the&nbsp;token&nbsp;exchange&nbsp;method,&nbsp;passing&nbsp;in&nbsp;a&nbsp;callback&nbsp;which&nbsp;performs&nbsp;additional&nbsp;validation</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="740" href="#740">740</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;on&nbsp;the&nbsp;auth&nbsp;code&nbsp;before&nbsp;it&nbsp;gets&nbsp;exchanged.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="6 tests cover line 741" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="741" href="#741">741</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$tokenData</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">tokenStorage</span><span class="default">-&gt;</span><span class="default">exchangeAuthCodeForAccessToken</span><span class="keyword">(</span><span class="default">$bodyParams</span><span class="keyword">[</span><span class="default">'code'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">array</span><span class="default">&nbsp;</span><span class="default">$authCode</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">use</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">$request</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$bodyParams</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="742" href="#742">742</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Verify&nbsp;that&nbsp;all&nbsp;required&nbsp;parameters&nbsp;are&nbsp;included.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="6 tests cover line 743" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="743" href="#743">743</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$requiredParameters</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">requirePkce</span><span class="default">&nbsp;</span><span class="default">or</span><span class="default">&nbsp;</span><span class="keyword">!</span><span class="keyword">empty</span><span class="keyword">(</span><span class="default">$authCode</span><span class="keyword">[</span><span class="default">'code_challenge'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">?</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'client_id'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">'redirect_uri'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">'code_verifier'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="keyword">:</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'client_id'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">'redirect_uri'</span><span class="keyword">]</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="6 tests cover line 744" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="744" href="#744">744</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$missingRequiredParameters</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">array_filter</span><span class="keyword">(</span><span class="default">$requiredParameters</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">$p</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">use</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">$bodyParams</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="6 tests cover line 745" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="745" href="#745">745</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="keyword">!</span><span class="default">array_key_exists</span><span class="keyword">(</span><span class="default">$p</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$bodyParams</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">||</span><span class="default">&nbsp;</span><span class="keyword">empty</span><span class="keyword">(</span><span class="default">$bodyParams</span><span class="keyword">[</span><span class="default">$p</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="6 tests cover line 746" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="746" href="#746">746</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="6 tests cover line 747" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="747" href="#747">747</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="keyword">empty</span><span class="keyword">(</span><span class="default">$missingRequiredParameters</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 748" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="748" href="#748">748</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">warning</span><span class="keyword">(</span><span class="default">'The&nbsp;exchange&nbsp;request&nbsp;was&nbsp;missing&nbsp;required&nbsp;parameters.&nbsp;Returning&nbsp;an&nbsp;error&nbsp;response.'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'missing'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$missingRequiredParameters</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 749" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="749" href="#749">749</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INVALID_REQUEST</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="750" href="#750">750</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="751" href="#751">751</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="752" href="#752">752</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Verify&nbsp;that&nbsp;it&nbsp;was&nbsp;issued&nbsp;for&nbsp;the&nbsp;same&nbsp;client_id&nbsp;and&nbsp;redirect_uri</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="5 tests cover line 753" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="753" href="#753">753</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">$authCode</span><span class="keyword">[</span><span class="default">'client_id'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="default">!==</span><span class="default">&nbsp;</span><span class="default">$bodyParams</span><span class="keyword">[</span><span class="default">'client_id'</span><span class="keyword">]</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="5 tests cover line 754" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="754" href="#754">754</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">||</span><span class="default">&nbsp;</span><span class="default">$authCode</span><span class="keyword">[</span><span class="default">'redirect_uri'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="default">!==</span><span class="default">&nbsp;</span><span class="default">$bodyParams</span><span class="keyword">[</span><span class="default">'redirect_uri'</span><span class="keyword">]</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 755" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="755" href="#755">755</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">error</span><span class="keyword">(</span><span class="default">&quot;The&nbsp;provided&nbsp;client_id&nbsp;and/or&nbsp;redirect_uri&nbsp;did&nbsp;not&nbsp;match&nbsp;those&nbsp;stored&nbsp;in&nbsp;the&nbsp;token.&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 756" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="756" href="#756">756</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INVALID_GRANT</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="757" href="#757">757</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="758" href="#758">758</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="759" href="#759">759</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;If&nbsp;the&nbsp;auth&nbsp;code&nbsp;was&nbsp;requested&nbsp;with&nbsp;no&nbsp;code_challenge,&nbsp;but&nbsp;the&nbsp;exchange&nbsp;request&nbsp;provides&nbsp;a&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="760" href="#760">760</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;code_verifier,&nbsp;return&nbsp;an&nbsp;error.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="5 tests cover line 761" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="761" href="#761">761</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="keyword">empty</span><span class="keyword">(</span><span class="default">$bodyParams</span><span class="keyword">[</span><span class="default">'code_verifier'</span><span class="keyword">]</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">&amp;&amp;</span><span class="default">&nbsp;</span><span class="keyword">empty</span><span class="keyword">(</span><span class="default">$authCode</span><span class="keyword">[</span><span class="default">'code_challenge'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 762" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="762" href="#762">762</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">error</span><span class="keyword">(</span><span class="default">&quot;A&nbsp;code_verifier&nbsp;was&nbsp;provided&nbsp;when&nbsp;trying&nbsp;to&nbsp;exchange&nbsp;an&nbsp;auth&nbsp;code&nbsp;requested&nbsp;without&nbsp;a&nbsp;code_challenge.&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 763" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="763" href="#763">763</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INVALID_GRANT</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="764" href="#764">764</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="765" href="#765">765</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 766" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="766" href="#766">766</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">requirePkce</span><span class="default">&nbsp;</span><span class="default">or</span><span class="default">&nbsp;</span><span class="keyword">!</span><span class="keyword">empty</span><span class="keyword">(</span><span class="default">$authCode</span><span class="keyword">[</span><span class="default">'code_challenge'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="767" href="#767">767</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Check&nbsp;that&nbsp;the&nbsp;supplied&nbsp;code_verifier&nbsp;hashes&nbsp;to&nbsp;the&nbsp;stored&nbsp;code_challenge</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="768" href="#768">768</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;TODO:&nbsp;support&nbsp;method&nbsp;=&nbsp;plain&nbsp;as&nbsp;well&nbsp;as&nbsp;S256.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 769" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="769" href="#769">769</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">!</span><span class="default">hash_equals</span><span class="keyword">(</span><span class="default">$authCode</span><span class="keyword">[</span><span class="default">'code_challenge'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">generatePKCECodeChallenge</span><span class="keyword">(</span><span class="default">$bodyParams</span><span class="keyword">[</span><span class="default">'code_verifier'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 770" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="770" href="#770">770</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">error</span><span class="keyword">(</span><span class="default">&quot;The&nbsp;provided&nbsp;code_verifier&nbsp;did&nbsp;not&nbsp;hash&nbsp;to&nbsp;the&nbsp;stored&nbsp;code_challenge&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 771" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="771" href="#771">771</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INVALID_GRANT</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="772" href="#772">772</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="773" href="#773">773</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="774" href="#774">774</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="775" href="#775">775</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Check&nbsp;that&nbsp;scope&nbsp;is&nbsp;not&nbsp;empty.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 776" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="776" href="#776">776</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="keyword">empty</span><span class="keyword">(</span><span class="default">$authCode</span><span class="keyword">[</span><span class="default">'scope'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 777" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="777" href="#777">777</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">error</span><span class="keyword">(</span><span class="default">&quot;An&nbsp;exchange&nbsp;request&nbsp;for&nbsp;a&nbsp;token&nbsp;with&nbsp;an&nbsp;empty&nbsp;scope&nbsp;was&nbsp;sent&nbsp;to&nbsp;the&nbsp;token&nbsp;endpoint.&quot;</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 778" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="778" href="#778">778</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">create</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INVALID_GRANT</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$request</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="779" href="#779">779</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="6 tests cover line 780" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="780" href="#780">780</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 781" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="781" href="#781">781</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="default">&nbsp;</span><span class="keyword">catch</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="782" href="#782">782</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;If&nbsp;an&nbsp;exception&nbsp;was&nbsp;thrown,&nbsp;return&nbsp;a&nbsp;corresponding&nbsp;error&nbsp;response.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 783" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="783" href="#783">783</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">Response</span><span class="keyword">(</span><span class="default">400</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'content-type'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'application/json'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">json_encode</span><span class="keyword">(</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 784" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="784" href="#784">784</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'error'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="default">-&gt;</span><span class="default">getInfo</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">[</span><span class="default">'error'</span><span class="keyword">]</span><span class="keyword">,</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="4 tests cover line 785" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorsIfParametersAreMissing&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorIfAccessCodeGrantsNoScopes&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatAuthCodeWithoutPkceCannotBeExchangedWithCodeVerifierBothExchangeEndpoints&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="785" href="#785">785</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'error_description'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$e</span><span class="default">-&gt;</span><span class="default">getMessage</span><span class="keyword">(</span><span class="keyword">)</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="786" href="#786">786</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="787" href="#787">787</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="788" href="#788">788</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="3 tests cover line 789" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="789" href="#789">789</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">is_null</span><span class="keyword">(</span><span class="default">$tokenData</span><span class="keyword">)</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 790" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="790" href="#790">790</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">logger</span><span class="default">-&gt;</span><span class="default">error</span><span class="keyword">(</span><span class="default">'Attempting&nbsp;to&nbsp;exchange&nbsp;an&nbsp;auth&nbsp;code&nbsp;for&nbsp;a&nbsp;token&nbsp;resulted&nbsp;in&nbsp;null.'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$bodyParams</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 791" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="791" href="#791">791</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">Response</span><span class="keyword">(</span><span class="default">400</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'content-type'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'application/json'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">json_encode</span><span class="keyword">(</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 792" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testExchangeFlowsReturnErrorOnInvalidParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="792" href="#792">792</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'error'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'invalid_grant'</span><span class="keyword">,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="793" href="#793">793</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'error_description'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'The&nbsp;provided&nbsp;credentials&nbsp;were&nbsp;not&nbsp;valid.'</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="794" href="#794">794</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="795" href="#795">795</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="796" href="#796">796</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="797" href="#797">797</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;TODO:&nbsp;return&nbsp;an&nbsp;error&nbsp;if&nbsp;the&nbsp;token&nbsp;doesnt&nbsp;contain&nbsp;a&nbsp;me&nbsp;key.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="798" href="#798">798</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="799" href="#799">799</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;If&nbsp;everything&nbsp;checked&nbsp;out,&nbsp;return&nbsp;{&quot;me&quot;:&nbsp;&quot;https://example.com&quot;}&nbsp;response</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 800" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="800" href="#800">800</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">Response</span><span class="keyword">(</span><span class="default">200</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 801" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="801" href="#801">801</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'content-type'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'application/json'</span><span class="keyword">,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="802" href="#802">802</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'cache-control'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'no-store'</span><span class="keyword">,</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 803" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="803" href="#803">803</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">json_encode</span><span class="keyword">(</span><span class="default">array_merge</span><span class="keyword">(</span><span class="keyword">[</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="804" href="#804">804</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Ensure&nbsp;that&nbsp;the&nbsp;token_type&nbsp;key&nbsp;is&nbsp;present,&nbsp;if&nbsp;tokenStorage&nbsp;doesnt&nbsp;include&nbsp;it.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 805" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="805" href="#805">805</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'token_type'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'Bearer'</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 806" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="806" href="#806">806</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">array_filter</span><span class="keyword">(</span><span class="default">$tokenData</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">string</span><span class="default">&nbsp;</span><span class="default">$k</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="807" href="#807">807</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;We&nbsp;should&nbsp;be&nbsp;able&nbsp;to&nbsp;trust&nbsp;the&nbsp;return&nbsp;data&nbsp;from&nbsp;tokenStorage,&nbsp;but&nbsp;theres&nbsp;no&nbsp;harm&nbsp;in</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="808" href="#808">808</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;preventing&nbsp;code_challenges&nbsp;from&nbsp;leaking,&nbsp;per&nbsp;OAuth2.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 809" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="809" href="#809">809</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="keyword">!</span><span class="default">in_array</span><span class="keyword">(</span><span class="default">$k</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'code_challenge'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">'code_challenge_method'</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="2 tests cover line 810" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsAccessTokenOnValidRequest&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatRequestsWithoutPkceWorkCorrectlyWithBothExchangeFlows&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="810" href="#810">810</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">ARRAY_FILTER_USE_KEY</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="811" href="#811">811</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="812" href="#812">812</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 813" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="813" href="#813">813</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">Response</span><span class="keyword">(</span><span class="default">400</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'content-type'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'application/json'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">json_encode</span><span class="keyword">(</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="1 test covers line 814" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testTokenEndpointReturnsErrorOnNonIndieauthRequest&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="814" href="#814">814</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'error'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'invalid_request'</span><span class="keyword">,</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="815" href="#815">815</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'error_description'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'Request&nbsp;to&nbsp;token&nbsp;endpoint&nbsp;was&nbsp;not&nbsp;a&nbsp;valid&nbsp;code&nbsp;exchange&nbsp;request.'</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="816" href="#816">816</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class="warning d-flex"><td class="col-1 text-right"><a id="817" href="#817">817</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="818" href="#818">818</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="819" href="#819">819</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/**</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="820" href="#820">820</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Handle&nbsp;Exception</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="821" href="#821">821</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="822" href="#822">822</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Turns&nbsp;an&nbsp;instance&nbsp;of&nbsp;`IndieAuthException`&nbsp;into&nbsp;an&nbsp;appropriate&nbsp;instance&nbsp;of&nbsp;`ResponseInterface`.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="823" href="#823">823</a></td><td class="col-11 codeLine"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="824" href="#824">824</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">handleException</span><span class="keyword">(</span><span class="default">IndieAuthException</span><span class="default">&nbsp;</span><span class="default">$exception</span><span class="keyword">)</span><span class="keyword">:</span><span class="default">&nbsp;</span><span class="default">ResponseInterface</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="14 tests cover line 825" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="825" href="#825">825</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$exceptionData</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$exception</span><span class="default">-&gt;</span><span class="default">getInfo</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="826" href="#826">826</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="14 tests cover line 827" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="827" href="#827">827</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">$exceptionData</span><span class="keyword">[</span><span class="default">'statusCode'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="default">==</span><span class="default">&nbsp;</span><span class="default">302</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="828" href="#828">828</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;This&nbsp;exception&nbsp;is&nbsp;handled&nbsp;by&nbsp;redirecting&nbsp;to&nbsp;the&nbsp;redirect_uri&nbsp;with&nbsp;error&nbsp;parameters.</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="829" href="#829">829</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$redirectQueryParams</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="9 tests cover line 830" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="830" href="#830">830</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'error'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$exceptionData</span><span class="keyword">[</span><span class="default">'error'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="default">??</span><span class="default">&nbsp;</span><span class="default">'invalid_request'</span><span class="keyword">,</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="9 tests cover line 831" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="831" href="#831">831</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'error_description'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">(string)</span><span class="default">&nbsp;</span><span class="default">$exception</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="832" href="#832">832</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="833" href="#833">833</a></td><td class="col-11 codeLine"></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="834" href="#834">834</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;If&nbsp;the&nbsp;state&nbsp;parameter&nbsp;was&nbsp;valid,&nbsp;include&nbsp;it&nbsp;in&nbsp;the&nbsp;error&nbsp;redirect.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="9 tests cover line 835" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="835" href="#835">835</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span class="default">&nbsp;</span><span class="keyword">(</span><span class="default">$exception</span><span class="default">-&gt;</span><span class="default">getCode</span><span class="keyword">(</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="default">!==</span><span class="default">&nbsp;</span><span class="default">IndieAuthException</span><span class="default">::</span><span class="default">INVALID_STATE</span><span class="keyword">)</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="9 tests cover line 836" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="836" href="#836">836</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$redirectQueryParams</span><span class="keyword">[</span><span class="default">'state'</span><span class="keyword">]</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="default">$exception</span><span class="default">-&gt;</span><span class="default">getRequest</span><span class="keyword">(</span><span class="keyword">)</span><span class="default">-&gt;</span><span class="default">getQueryParams</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">[</span><span class="default">'state'</span><span class="keyword">]</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="837" href="#837">837</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="838" href="#838">838</a></td><td class="col-11 codeLine"></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="9 tests cover line 839" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="839" href="#839">839</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">Response</span><span class="keyword">(</span><span class="default">$exceptionData</span><span class="keyword">[</span><span class="default">'statusCode'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="9 tests cover line 840" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testRequestsMissingBothPkceParametersReturnsError&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testInvalidStateCodeChallengeOrScopeReturnErrorRedirects&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsServerErrorIfAuthenticationResultHasNoMeKey&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnErrorIfFetchingClientIdThrowsException&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasNoHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfApprovalRequestHasInvalidHash&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsInternalServerErrorIfAuthCodeCannotBeStored&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testBackCompatNonPkceRequestMustLackBothPkceParameters&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="840" href="#840">840</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'Location'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">appendQueryParams</span><span class="keyword">(</span><span class="default">(string)</span><span class="default">&nbsp;</span><span class="default">$exception</span><span class="default">-&gt;</span><span class="default">getRequest</span><span class="keyword">(</span><span class="keyword">)</span><span class="default">-&gt;</span><span class="default">getQueryParams</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">[</span><span class="default">'redirect_uri'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">$redirectQueryParams</span><span class="keyword">)</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="841" href="#841">841</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="842" href="#842">842</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><span class="default">&nbsp;</span><span class="keyword">else</span><span class="default">&nbsp;</span><span class="keyword">{</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="843" href="#843">843</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;This&nbsp;exception&nbsp;should&nbsp;be&nbsp;shown&nbsp;to&nbsp;the&nbsp;user.</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="6 tests cover line 844" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="844" href="#844">844</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">Response</span><span class="keyword">(</span><span class="default">$exception</span><span class="default">-&gt;</span><span class="default">getStatusCode</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span><span class="default">'content-type'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">'text/html'</span><span class="keyword">]</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="default">renderTemplate</span><span class="keyword">(</span><span class="default">$this</span><span class="default">-&gt;</span><span class="default">exceptionTemplatePath</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="keyword">[</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="6 tests cover line 845" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="845" href="#845">845</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'request'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$exception</span><span class="default">-&gt;</span><span class="default">getRequest</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">,</span></td></tr>
<tr class="covered-by-large-tests popin d-flex"><td data-title="6 tests cover line 846" data-content="&lt;ul&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationEndpointReturnsErrorOnMissingParameter&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testAuthorizationRequestWithInvalidClientIdOrRedirectUriShowsErrorToUser&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testHandlesValidAndInvalidMeUrlsCorrectly&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdWithNoParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testReturnsErrorIfRedirectUriDoesntMatchClientIdOrParsedRedirectUris&lt;/li&gt;&lt;li class=&quot;covered-by-large-tests&quot;&gt;Taproot\IndieAuth\Test\ServerTest::testNonIndieAuthRequestWithDefaultHandlerReturnsError&lt;/li&gt;&lt;/ul&gt;" data-placement="top" data-html="true" class="col-1 text-right"><a id="846" href="#846">846</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">'exception'</span><span class="default">&nbsp;</span><span class="default">=&gt;</span><span class="default">&nbsp;</span><span class="default">$exception</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="847" href="#847">847</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">]</span><span class="keyword">)</span><span class="keyword">)</span><span class="keyword">;</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="848" href="#848">848</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class="warning d-flex"><td class="col-1 text-right"><a id="849" href="#849">849</a></td><td class="col-11 codeLine"><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span></td></tr>
<tr class=" d-flex"><td class="col-1 text-right"><a id="850" href="#850">850</a></td><td class="col-11 codeLine"><span class="keyword">}</span></td></tr>
</tbody>
</table>
<footer>
<hr/>
<h4>Legend</h4>
<p><span class="success"><strong>Executed</strong></span><span class="danger"><strong>Not Executed</strong></span><span class="warning"><strong>Dead Code</strong></span></p>
<p>
<small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage 9.2.6</a> using <a href="https://secure.php.net/" target="_top">PHP 7.4.19</a> with <a href="https://xdebug.org/">Xdebug 3.0.4</a> and <a href="https://phpunit.de/">PHPUnit 9.5.5</a> at Fri Jun 18 14:09:49 UTC 2021.</small>
</p>
<a title="Back to the top" id="toplink" href="#">
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M12 11L6 5l-6 6h12z"/></svg>
</a>
</footer>
</div>
<script src="phpunit_js/jquery.min.js" type="text/javascript"></script>
<script src="phpunit_js/popper.min.js" type="text/javascript"></script>
<script src="phpunit_js/bootstrap.min.js" type="text/javascript"></script>
<script src="phpunit_js/file.js" type="text/javascript"></script>
</body>
</html>