tfa = $tfa; $this->trustedFactory = $trustedFactory; $this->dateTime = $dateTime; $this->remoteAddress = $remoteAddress; $this->session = $session; $this->trustedResourceModel = $trustedResourceModel; $this->cookieManager = $cookieManager; $this->sessionManager = $sessionManager; $this->cookieMetadataFactory = $cookieMdFactory; $this->encoder = $encoder; $this->decoder = $decoder; $this->trustedRepository = $trustedRepository; } /** * Get current user * @return User|null */ private function getUser() { return $this->session->getUser(); } /** * Get device name * @return string */ private function getDeviceName() { $browser = parse_user_agent(); return $browser['platform'] . ' ' . $browser['browser'] . ' ' . $browser['version']; } /** * Get token collection from cookie * @return array */ private function getTokenCollection() { try { return $this->decoder->decode( $this->cookieManager->getCookie(TrustedManagerInterface::TRUSTED_DEVICE_COOKIE) ); } catch (\Exception $e) { return []; } } /** * Send token as cookie * @param string $token * @throws \Magento\Framework\Exception\InputException * @throws \Magento\Framework\Stdlib\Cookie\CookieSizeLimitReachedException * @throws \Magento\Framework\Stdlib\Cookie\FailureToSendException */ private function sendTokenCookie($token) { $user = $this->getUser(); $tokenCollection = $this->getTokenCollection(); // Enable cookie $cookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata() ->setDurationOneYear() ->setHttpOnly(true) ->setPath($this->sessionManager->getCookiePath()) ->setDomain($this->sessionManager->getCookieDomain()); $tokenCollection[$user->getUserName()] = $token; $this->cookieManager->setPublicCookie( TrustedManagerInterface::TRUSTED_DEVICE_COOKIE, $this->encoder->encode($tokenCollection), $cookieMetadata ); } /** * Rotate secret trust token * @return void * @throws \Exception * @throws \Magento\Framework\Exception\InputException * @throws \Magento\Framework\Stdlib\Cookie\CookieSizeLimitReachedException * @throws \Magento\Framework\Stdlib\Cookie\FailureToSendException */ public function rotateTrustedDeviceToken() { $user = $this->getUser(); $tokenCollection = $this->getTokenCollection(); if (isset($tokenCollection[$user->getUserName()])) { $token = $tokenCollection[$user->getUserName()]; /** @var $trustEntry Trusted */ $trustEntry = $this->trustedFactory->create(); $this->trustedResourceModel->load($trustEntry, $token, 'token'); if ($trustEntry->getId() && ($trustEntry->getUserId() == $user->getId())) { $token = sha1(uniqid(time())); $trustEntry->setToken($token); $this->trustedResourceModel->save($trustEntry); $this->sendTokenCookie($token); } } } /** * Return true if device is trusted * @return bool */ public function isTrustedDevice() { if ($this->isTrustedDevice === null) { // Must cache this ina single session to avoid rotation issues $user = $this->getUser(); $tokenCollection = $this->getTokenCollection(); if (isset($tokenCollection[$user->getUserName()])) { $token = $tokenCollection[$user->getUserName()]; /** @var $trustEntry Trusted */ $trustEntry = $this->trustedFactory->create(); $this->trustedResourceModel->load($trustEntry, $token, 'token'); $this->isTrustedDevice = $trustEntry->getId() && ($trustEntry->getUserId() == $user->getId()); } else { $this->isTrustedDevice = false; } } return $this->isTrustedDevice; } /** * Revoke trusted device * @param int $tokenId * @return bool */ public function revokeTrustedDevice($tokenId) { $token = $this->trustedRepository->getById($tokenId); $this->trustedRepository->delete($token); return true; } /** * Trust a device * @param $providerCode * @param RequestInterface $request * @return boolean * @throws \Exception * @throws \Magento\Framework\Exception\InputException * @throws \Magento\Framework\Stdlib\Cookie\CookieSizeLimitReachedException * @throws \Magento\Framework\Stdlib\Cookie\FailureToSendException */ public function handleTrustDeviceRequest($providerCode, RequestInterface $request) { if ($provider = $this->tfa->getProvider($providerCode)) { if ($provider->isTrustedDevicesAllowed() && $request->getParam('tfa_trust_device') && ($request->getParam('tfa_trust_device') != "false") // u2fkey submit translates into a string ) { $token = sha1(uniqid(time())); /** @var $trustEntry Trusted */ $trustEntry = $this->trustedFactory->create(); $trustEntry ->setToken($token) ->setDateTime($this->dateTime->date()) ->setUserId($this->getUser()->getId()) ->setLastIp($this->remoteAddress->getRemoteAddress()) ->setDeviceName($this->getDeviceName()) ->setUserAgent($request->getServer('HTTP_USER_AGENT')); $this->trustedResourceModel->save($trustEntry); $this->sendTokenCookie($token); return true; } } return false; } }