diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php index 4b825d0..ea0f86c 100644 --- a/src/Controller/UserController.php +++ b/src/Controller/UserController.php @@ -57,6 +57,130 @@ class UserController implements IAuthenticationRequired return new HtmlContent('account/account', ['user' => $user->toArray()]); } + public function getGoogleConnectRedirect(): IRedirect + { + /** + * @var User $user + */ + $user = \Container::$request->user(); + + $state = bin2hex(random_bytes(16)); + $nonce = bin2hex(random_bytes(16)); + + \Container::$request->session()->set('oauth_state', $state); + \Container::$request->session()->set('oauth_nonce', $nonce); + + $oAuth = new GoogleOAuth(new Request()); + + $url = $oAuth->getDialogUrl( + $state, + \Container::$request->getBase() . \Container::$routeCollection->getRoute('account.googleConnect-confirm')->generateLink(), + $nonce, + $user->getEmail() + ); + + return new Redirect($url, IRedirect::TEMPORARY); + } + + public function getGoogleConnectConfirm(): IContent + { + $defaultError = 'Authentication with Google failed. Please try again!'; + + if (\Container::$request->query('state') !== \Container::$request->session()->get('oauth_state')) { + return new HtmlContent('account/google_connect', ['success' => false, 'error' => $defaultError]); + } + + $oAuth = new GoogleOAuth(new Request()); + $tokenData = $oAuth->getToken( + \Container::$request->query('code'), + \Container::$request->getBase() . \Container::$routeCollection->getRoute('account.googleConnect-confirm')->generateLink() + ); + if (!isset($tokenData['id_token'])) { + return new HtmlContent('account/google_connect', ['success' => false, 'error' => $defaultError]); + } + + $jwtParser = new JwtParser($tokenData['id_token']); + $idToken = $jwtParser->getPayload(); + if ($idToken['nonce'] !== \Container::$request->session()->get('oauth_nonce')) { + return new HtmlContent('account/google_connect', ['success' => false, 'error' => $defaultError]); + } + + $anotherUser = $this->userRepository->getByGoogleSub($idToken['sub']); + if ($anotherUser !== null) { + return new HtmlContent('account/google_connect', [ + 'success' => false, + 'error' => 'This Google account is linked to another account.' + ]); + } + + \Container::$request->session()->set('google_user_data', $idToken); + + /** + * @var User $user + */ + $user = \Container::$request->user(); + + return new HtmlContent('account/google_connect', [ + 'success' => true, + 'googleAccount' => $idToken['email'], + 'userEmail' => $user->getEmail() + ]); + } + + public function connectGoogle(): IContent + { + /** + * @var User $user + */ + $user = \Container::$request->user(); + if (!$user->checkPassword(\Container::$request->post('password'))) { + return new JsonContent([ + 'error' => [ + 'errorText' => 'The given password is wrong.' + ] + ]); + } + + $googleUserData = \Container::$request->session()->get('google_user_data'); + $user->setGoogleSub($googleUserData['sub']); + \Container::$persistentDataManager->saveToDb($user); + + return new JsonContent(['success' => true]); + } + + public function getGoogleDisconnectConfirm(): IContent + { + /** + * @var User $user + */ + $user = \Container::$request->user(); + + return new HtmlContent('account/google_disconnect', [ + 'success' => true, + 'userEmail' => $user->getEmail() + ]); + } + + public function disconnectGoogle(): IContent + { + /** + * @var User $user + */ + $user = \Container::$request->user(); + if (!$user->checkPassword(\Container::$request->post('password'))) { + return new JsonContent([ + 'error' => [ + 'errorText' => 'The given password is wrong.' + ] + ]); + } + + $user->setGoogleSub(null); + \Container::$persistentDataManager->saveToDb($user); + + return new JsonContent(['success' => true]); + } + public function getGoogleAuthenticateRedirect(): IRedirect { /** diff --git a/views/account/account.php b/views/account/account.php index e21ae64..75fa4ec 100644 --- a/views/account/account.php +++ b/views/account/account.php @@ -32,7 +32,14 @@
= $error ?>
+ + + +