simplesamlphp /
simplesamlphp-module-webauthn
| 1 | <?php |
||
| 2 | |||
| 3 | declare(strict_types=1); |
||
| 4 | |||
| 5 | namespace SimpleSAML\Module\webauthn\Controller; |
||
| 6 | |||
| 7 | use DateTime; |
||
| 8 | use Exception; |
||
| 9 | use SimpleSAML\Auth; |
||
| 10 | use SimpleSAML\Configuration; |
||
| 11 | use SimpleSAML\Error; |
||
| 12 | use SimpleSAML\HTTP\RunnableResponse; |
||
| 13 | use SimpleSAML\Logger; |
||
| 14 | use SimpleSAML\Module\webauthn\WebAuthn\StaticProcessHelper; |
||
| 15 | use SimpleSAML\Session; |
||
| 16 | use Symfony\Component\HttpFoundation\Request; |
||
| 17 | |||
| 18 | /** |
||
| 19 | * Controller class for the webauthn module. |
||
| 20 | * |
||
| 21 | * This class serves the different views available in the module. |
||
| 22 | * |
||
| 23 | * @package SimpleSAML\Module\webauthn |
||
| 24 | */ |
||
| 25 | class ManageToken |
||
| 26 | { |
||
| 27 | /** @var \SimpleSAML\Auth\State|string */ |
||
| 28 | protected $authState = Auth\State::class; |
||
| 29 | |||
| 30 | /** @var \SimpleSAML\Logger|string */ |
||
| 31 | protected $logger = Logger::class; |
||
| 32 | |||
| 33 | |||
| 34 | /** |
||
| 35 | * Controller constructor. |
||
| 36 | * |
||
| 37 | * It initializes the global configuration and session for the controllers implemented here. |
||
| 38 | * |
||
| 39 | * @param \SimpleSAML\Configuration $config The configuration to use by the controllers. |
||
| 40 | * @param \SimpleSAML\Session $session The session to use by the controllers. |
||
| 41 | * |
||
| 42 | * @throws \Exception |
||
| 43 | */ |
||
| 44 | public function __construct( |
||
| 45 | protected Configuration $config, |
||
| 46 | protected Session $session, |
||
| 47 | ) { |
||
| 48 | } |
||
| 49 | |||
| 50 | |||
| 51 | /** |
||
| 52 | * Inject the \SimpleSAML\Auth\State dependency. |
||
| 53 | * |
||
| 54 | * @param \SimpleSAML\Auth\State $authState |
||
| 55 | */ |
||
| 56 | public function setAuthState(Auth\State $authState): void |
||
| 57 | { |
||
| 58 | $this->authState = $authState; |
||
| 59 | } |
||
| 60 | |||
| 61 | |||
| 62 | /** |
||
| 63 | * Inject the \SimpleSAML\Logger dependency. |
||
| 64 | * |
||
| 65 | * @param \SimpleSAML\Logger $logger |
||
| 66 | */ |
||
| 67 | public function setLogger(Logger $logger): void |
||
| 68 | { |
||
| 69 | $this->logger = $logger; |
||
| 70 | } |
||
| 71 | |||
| 72 | |||
| 73 | /** |
||
| 74 | * @param \Symfony\Component\HttpFoundation\Request $request |
||
| 75 | * @return \SimpleSAML\HTTP\RunnableResponse A Symfony Response-object. |
||
| 76 | */ |
||
| 77 | public function main(Request $request): RunnableResponse |
||
| 78 | { |
||
| 79 | $this->logger::info('FIDO2 - Accessing WebAuthn token management'); |
||
| 80 | |||
| 81 | $stateId = $request->query->get('StateId'); |
||
| 82 | if ($stateId === null) { |
||
| 83 | throw new Error\BadRequest('Missing required StateId query parameter.'); |
||
| 84 | } |
||
| 85 | |||
| 86 | $state = $this->authState::loadState($stateId, 'webauthn:request'); |
||
| 87 | |||
| 88 | $ourState = WebAuthn::workflowStateMachine($state); |
||
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
| 89 | if ($ourState !== WebAuthn::STATE_MGMT) { |
||
| 90 | throw new Exception("Attempt to access the token management page unauthenticated."); |
||
| 91 | } |
||
| 92 | |||
| 93 | switch ($request->request->get('submit')) { |
||
| 94 | case "NEVERMIND": |
||
| 95 | $response = new RunnableResponse([Auth\ProcessingChain::class, 'resumeProcessing'], [$state]); |
||
| 96 | break; |
||
| 97 | case "DELETE": |
||
| 98 | $credId = $request->request->get('credId'); |
||
| 99 | if ($state['FIDO2AuthSuccessful'] == $credId) { |
||
| 100 | throw new Exception("Attempt to delete the currently used credential despite UI preventing this."); |
||
| 101 | } |
||
| 102 | |||
| 103 | $store = $state['webauthn:store']; |
||
| 104 | $store->deleteTokenData($credId); |
||
| 105 | |||
| 106 | if (array_key_exists('Registration', $state)) { |
||
| 107 | foreach ($state['FIDO2Tokens'] as $key => $value) { |
||
| 108 | if ($state['FIDO2Tokens'][$key][0] == $credId) { |
||
| 109 | unset($state['FIDO2Tokens'][$key]); |
||
| 110 | $state['FIDO2Tokens'] = array_values($state['FIDO2Tokens']); |
||
| 111 | break; |
||
| 112 | } |
||
| 113 | } |
||
| 114 | |||
| 115 | $response = new RunnableResponse([StaticProcessHelper::class, 'saveStateAndRedirect'], [&$state]); |
||
| 116 | } else { |
||
| 117 | $response = new RunnableResponse([Auth\ProcessingChain::class, 'resumeProcessing'], [$state]); |
||
| 118 | } |
||
| 119 | break; |
||
| 120 | default: |
||
| 121 | throw new Exception("Unknown submit button state."); |
||
| 122 | } |
||
| 123 | |||
| 124 | $response->setExpires(new DateTime('Thu, 19 Nov 1981 08:52:00 GMT')); |
||
| 125 | $response->setCache([ |
||
| 126 | 'must_revalidate' => true, |
||
| 127 | 'no_cache' => true, |
||
| 128 | 'no_store' => true, |
||
| 129 | 'no_transform' => false, |
||
| 130 | 'public' => false, |
||
| 131 | 'private' => false, |
||
| 132 | ]); |
||
| 133 | |||
| 134 | return $response; |
||
| 135 | } |
||
| 136 | } |
||
| 137 |