/** * Render user initials or an abbreviated name for a given username. If the account was deleted, use the username as fallback. * * @param string $format Supported are "fullFirstName" and "initials" * @return string */ public function render($format = 'initials') { if (!in_array($format, array('fullFirstName', 'initials', 'fullName'))) { throw new \InvalidArgumentException(sprintf('Format "%s" given to history:userInitials(), only supporting "fullFirstName", "initials" and "fullName".', $format), 1415705861); } $accountIdentifier = $this->renderChildren(); // TODO: search by credential source is still needed /* @var $account \TYPO3\Flow\Security\Account */ $account = $this->accountRepository->findOneByAccountIdentifier($accountIdentifier); if ($account === null) { return $accountIdentifier; } /* @var $requestedUser Person */ $requestedUser = $account->getParty(); if ($requestedUser === null || $requestedUser->getName() === null) { return $accountIdentifier; } $currentUser = $this->userService->getBackendUser(); if ($currentUser) { if ($currentUser === $requestedUser) { $translationHelper = new TranslationHelper(); $you = $translationHelper->translateById('you', 'TYPO3.Neos'); } } switch ($format) { case 'initials': return mb_substr($requestedUser->getName()->getFirstName(), 0, 1) . mb_substr($requestedUser->getName()->getLastName(), 0, 1); case 'fullFirstName': return isset($you) ? $you : $requestedUser->getName()->getFirstName() . ' ' . mb_substr($requestedUser->getName()->getLastName(), 0, 1) . '.'; case 'fullName': return isset($you) ? $you : $requestedUser->getName()->getFullName(); } }
/** * Sets isAuthenticated to TRUE for all tokens. * * @param \TYPO3\Flow\Security\Authentication\TokenInterface $authenticationToken The token to be authenticated * @return void * @throws \TYPO3\Flow\Security\Exception\UnsupportedAuthenticationTokenException */ public function authenticate(TokenInterface $authenticationToken) { if (!$authenticationToken instanceof Typo3OrgSsoToken) { throw new UnsupportedAuthenticationTokenException('This provider cannot authenticate the given token.', 1217339840); } /** @var $account \TYPO3\Flow\Security\Account */ $account = null; $credentials = $authenticationToken->getCredentials(); if (is_array($credentials) && isset($credentials['username'])) { $providerName = $this->name; $this->securityContext->withoutAuthorizationChecks(function () use($credentials, $providerName, &$account) { $account = $this->accountRepository->findActiveByAccountIdentifierAndAuthenticationProviderName($credentials['username'], $providerName); }); } if (is_object($account)) { $authenticationData = 'version=' . $credentials['version'] . '&user='******'username'] . '&tpa_id=' . $credentials['tpaId'] . '&expires=' . $credentials['expires'] . '&action=' . $credentials['action'] . '&flags=' . $credentials['flags'] . '&userdata=' . $credentials['userdata']; if ($this->rsaWalletService->verifySignature($authenticationData, $credentials['signature'], $this->options['rsaKeyUuid']) && $credentials['expires'] > time()) { $authenticationToken->setAuthenticationStatus(TokenInterface::AUTHENTICATION_SUCCESSFUL); $authenticationToken->setAccount($account); } else { $authenticationToken->setAuthenticationStatus(TokenInterface::WRONG_CREDENTIALS); } } elseif ($authenticationToken->getAuthenticationStatus() !== TokenInterface::AUTHENTICATION_SUCCESSFUL) { $authenticationToken->setAuthenticationStatus(TokenInterface::NO_CREDENTIALS_GIVEN); } }
/** * @param string $identification */ public function sendResetRequestAction($identification) { $person = NULL; $resetPasswordToken = NULL; if (empty($identifier)) { // $response = new Response(); // $response->setType('error'); // $response->setMessage('No username or e-mail address was given!'); // $this->view->assign('value', $response); } else { $account = $this->accountRepository->findByAccountIdentifierAndAuthenticationProviderName($identifier, 'DefaultProvider'); if ($account !== NULL) { $person = $account->getParty(); $resetPasswordToken = $this->passwordResetService->generateResetPasswordTokenForParty($person, $this->request); } else { $person = $this->userRepository->findByPrimaryElectronicAddress($identifier)->getFirst(); if (is_subclass_of($person, '\\TYPO3\\Party\\Domain\\Model\\AbstractParty')) { $resetPasswordToken = $this->passwordResetService->generateResetPasswordTokenForParty($person, $this->request); } } if ($resetPasswordToken instanceof ResetToken) { $this->emitSendResetRequest(array('controllerContext' => $this->controllerContext, 'resetPasswordToken' => $resetPasswordToken->getToken(), 'recipient' => $person, 'properties' => array('recipient' => $person))); } $this->request->setFormat('json'); $this->redirect('reset', NULL, NULL, array('identifier' => $identifier)); } }
/** * Checks the given token for validity and sets the token authentication status * accordingly (success, wrong credentials or no credentials given). * * @param \TYPO3\Flow\Security\Authentication\TokenInterface $authenticationToken The token to be authenticated * @return void * @throws \TYPO3\Flow\Security\Exception\UnsupportedAuthenticationTokenException */ public function authenticate(TokenInterface $authenticationToken) { if (!$authenticationToken instanceof UsernamePassword) { throw new UnsupportedAuthenticationTokenException('This provider cannot authenticate the given token.', 1217339840); } /** @var $account \TYPO3\Flow\Security\Account */ $account = null; $credentials = $authenticationToken->getCredentials(); if (is_array($credentials) && isset($credentials['username'])) { $providerName = $this->name; $accountRepository = $this->accountRepository; $this->securityContext->withoutAuthorizationChecks(function () use($credentials, $providerName, $accountRepository, &$account) { $account = $accountRepository->findActiveByAccountIdentifierAndAuthenticationProviderName($credentials['username'], $providerName); }); } if (is_object($account)) { if ($this->hashService->validatePassword($credentials['password'], $account->getCredentialsSource())) { $account->authenticationAttempted(TokenInterface::AUTHENTICATION_SUCCESSFUL); $authenticationToken->setAuthenticationStatus(TokenInterface::AUTHENTICATION_SUCCESSFUL); $authenticationToken->setAccount($account); } else { $account->authenticationAttempted(TokenInterface::WRONG_CREDENTIALS); $authenticationToken->setAuthenticationStatus(TokenInterface::WRONG_CREDENTIALS); } $this->accountRepository->update($account); $this->persistenceManager->whitelistObject($account); } elseif ($authenticationToken->getAuthenticationStatus() !== TokenInterface::AUTHENTICATION_SUCCESSFUL) { $authenticationToken->setAuthenticationStatus(TokenInterface::NO_CREDENTIALS_GIVEN); } }
/** * Returns TRUE, if the specified user ($value) does not exist yet. * * If at least one error occurred, the result is FALSE. * * @param mixed $value The value that should be validated * @return void * @throws InvalidSubjectException */ protected function isValid($value) { $account = $this->accountRepository->findByAccountIdentifierAndAuthenticationProviderName($value, 'DefaultProvider'); if ($account instanceof Account) { $this->addError('There is already a user with the email address.', 1325156008); } }
/** * Executed after the page containing the current element has been submitted * * @param \TYPO3\Form\Core\Runtime\FormRuntime $formRuntime * @param $elementValue raw value of the submitted element */ public function onSubmit(\TYPO3\Form\Core\Runtime\FormRuntime $formRuntime, &$elementValue) { $isAccountNameTaken = (bool) $this->accountRepository->findByAccountIdentifierAndAuthenticationProviderName($elementValue, 'DefaultProvider'); if ($isAccountNameTaken) { $processingRule = $this->getRootForm()->getProcessingRule($this->getIdentifier()); $processingRule->getProcessingMessages()->addError(new \TYPO3\Flow\Error\Error('User name is already taken', 1334768053)); } $this->requireIfTriggerIsSet($formRuntime); }
/** * @test */ public function authenticationFailsWithWrongCredentialsInAnUsernamePasswordToken() { $this->mockHashService->expects($this->once())->method('validatePassword')->with('wrong password', '8bf0abbb93000e2e47f0e0a80721e834,80f117a78cff75f3f73793fd02aa9086')->will($this->returnValue(false)); $this->mockAccount->expects($this->once())->method('getCredentialsSource')->will($this->returnValue('8bf0abbb93000e2e47f0e0a80721e834,80f117a78cff75f3f73793fd02aa9086')); $this->mockAccountRepository->expects($this->once())->method('findActiveByAccountIdentifierAndAuthenticationProviderName')->with('admin', 'myProvider')->will($this->returnValue($this->mockAccount)); $this->mockToken->expects($this->once())->method('getCredentials')->will($this->returnValue(array('username' => 'admin', 'password' => 'wrong password'))); $this->mockToken->expects($this->once())->method('setAuthenticationStatus')->with(\TYPO3\Flow\Security\Authentication\TokenInterface::WRONG_CREDENTIALS); $this->persistedUsernamePasswordProvider->authenticate($this->mockToken); }
/** * @Given /^I am logged in as "([^"]*)" with password "([^"]*)"$/ */ public function iAmLoggedInAsUserWithPassword($username, $password) { $user = $this->accountRepository->findByAccountIdentifierAndAuthenticationProviderName($username, 'DefaultProvider'); if (!$user) { $this->flowContext->iRunTheCommand('roketi.panel:setup:createadminuser --username ' . $username . ' --password ' . $password); } $this->visit('/'); $this->fillField('username', $username); $this->fillField('password', $password); $this->pressButton('login'); }
/** * Adds a new account to the system. * * @param string $username The username of the new administrator * @param string $password The password of the new administrator */ public function createAdminUserCommand($username = '', $password = '') { // check if user + password are not empty if ($username == '' || $password == '') { // add a console output $this->outputLine('Either username or password missing, cannot continue.'); return 1; } // let's create the user $account = $this->accountFactory->createAccountWithPassword($username, $password, array('Roketi.Panel:Administrator')); $this->accountRepository->add($account); $this->outputLine('User ' . $username . ' created successfully.'); }
/** * @param RegistrationFlow $value The value that should be validated * @return void * @throws InvalidValidationOptionsException */ protected function isValid($value) { /** @noinspection PhpUndefinedMethodInspection */ $existingAccount = $this->accountRepository->findOneByAccountIdentifier($value->getEmail()); if ($existingAccount) { // todo: error message translatable $this->result->forProperty('email')->addError(new Error('Die Email-Adresse %s wird bereits verwendet!', 1336499566, [$value->getEmail()])); } // If a custom validation service is registered, call its validate method to allow custom validations during registration if ($this->objectManager->isRegistered(RegistrationFlowValidationServiceInterface::class)) { $instance = $this->objectManager->get(RegistrationFlowValidationServiceInterface::class); $instance->validateRegistrationFlow($value, $this); } }
/** * @param string $identifier * @param string $password * @return void */ public function createAction($identifier, $password) { if ($this->accountRepository->countByAccountIdentifier($identifier) == 1 && $this->userRepository->countByUsername($identifier) == 1) { $this->addFlashMessage('Nickname already taken, please choose another one!'); $this->redirect('new'); } else { $account = $this->accountFactory->createAccountWithPassword($identifier, $password); $this->accountRepository->add($account); $user = new User(); $user->setUsername($identifier); $this->userRepository->add($user); $this->addFlashMessage('Account ' . $identifier . ' successful created! You can login now!'); $this->redirect('index', 'Authentication'); } }
/** * @param PersonDto $person * @param NodeInterface $userStorageNode * @param string $dateOfBirth * @param array $password * @param string $recaptcha_challenge_field * @return void * * @throws \Exception * @throws \TYPO3\Flow\Mvc\Exception\ForwardException * @throws \TYPO3\Flow\Persistence\Exception\IllegalObjectTypeException * @throws \TYPO3\Flow\Security\Exception * * @Flow\Validate(argumentName="password", type="\TYPO3\Neos\Validation\Validator\PasswordValidator", options={ "allowEmpty"=0, "minimum"=6, "maximum"=255 }) * @Flow\Validate(argumentName="recaptcha_challenge_field", type="\BuJitsuDo\Authentication\Validation\Validator\CaptchaValidator") * @Flow\Validate(argumentName="person.emailAddress", type="\BuJitsuDo\Authentication\Validation\Validator\AccountDoesNotExistsValidator") */ public function registerAction(PersonDto $person, NodeInterface $userStorageNode, $dateOfBirth = NULL, array $password, $recaptcha_challenge_field = '') { $account = $this->accountFactory->createAccountWithPassword($person->getEmailAddress(), array_shift($password), $this->defaultRoles); $party = $this->objectManager->get('\\TYPO3\\Neos\\Domain\\Model\\User'); if ($dateOfBirth !== NULL) { $date = new \DateTime(); $date->setTimestamp(strtotime($dateOfBirth)); $person->setDateOfBirth($date); } if (!$party instanceof AbstractParty) { throw new \Exception('The configured className did not result in an object that inherits from AbstractParty.', 1397043150); } /** @var $party User */ $party->setName(new PersonName('', $person->getFirstName(), '', $person->getLastName())); $this->partyRepository->add($party); $account->setParty($party); $this->accountRepository->add($account); $this->persistenceManager->persistAll(); $profile = $this->createProfileNode($account, $userStorageNode, $person); if ($profile instanceof NodeInterface) { $this->forward('show', 'Frontend\\Node', 'TYPO3.Neos', ['node' => $profile]); } else { throw new \Exception('No profile node returned', 1239187); } }
/** * @param string $emailAddress * @param string $requirement * * @throws \Exception * * @return string */ public function resetPasswordAction($emailAddress, $requirement = '') { if ($requirement !== '') { throw new \Exception('Bot detection', 12393182738); } $locale = new Locale('nl'); $account = $this->accountRepository->findActiveByAccountIdentifierAndAuthenticationProviderName($emailAddress, 'DefaultProvider'); if ($account instanceof Account) { try { /** @var Person $profile */ $profile = $this->profileService->getProfileNodeOfAccount($account); $password = $this->randomPassword(); $hashedPassword = $this->hashService->hashPassword($password, 'default'); $this->mailerService->sendEmail(array('email' => $emailAddress, 'name' => $profile->getDisplayName()), 'Nieuw wachtwoord', 'Packages/Application/BuJitsuDo.Authentication/Resources/Private/Templates/Email/PasswordReset.html', array('password' => $password, 'profile' => $profile)); $account->setCredentialsSource($hashedPassword); $this->accountRepository->update($account); $this->persistenceManager->persistAll(); } catch (\Exception $exception) { return $exception->getMessage(); } } else { $this->response->setHeader('Notification', $this->translator->translateById('profile.reset.password.response.failure', [], NULL, $locale, 'Main', 'BuJitsuDo.Authentication')); $this->response->setHeader('NotificationType', 'alert'); return ''; } $this->response->setHeader('Notification', $this->translator->translateById('profile.reset.password.response.success', [], NULL, $locale, 'Main', 'BuJitsuDo.Authentication')); $this->response->setHeader('NotificationType', 'success'); return ''; }
/** * @param mixed $value The value that should be validated * @return void * @throws \TYPO3\Flow\Validation\Exception\InvalidSubjectException */ protected function isValid($value) { if (!is_array($value)) { throw new \TYPO3\Flow\Validation\Exception\InvalidSubjectException('The given account identifier was not a string.', 1325155784); } if (empty($value['new'])) { $this->addError('This property is required', 1354192543); } $account = null; if ($value['new'] != $value['old']) { $account = $this->accountRepository->findByAccountIdentifierAndAuthenticationProviderName($value['new'], 'defaultProvider'); } if ($account != null) { $this->addError('The username is already in use.', 9994); } }
/** * Import Bearbeiter table into the FLOW domain_model tabel subugoe_germaniasacra_domain_model_bearbeiter and creates an account for every user * @return int */ private function importAndJoinBearbeiterWithAccount() { /** @var \Doctrine\DBAL\Connection $sqlConnection */ $sqlConnection = $this->entityManager->getConnection(); $sql = 'SELECT ID, Bearbeiter FROM Bearbeiter ORDER BY ID ASC'; $bearbeiters = $sqlConnection->fetchAll($sql); if (isset($bearbeiters) and is_array($bearbeiters)) { $nBearbeiter = 0; foreach ($bearbeiters as $be) { $uid = $be['ID']; $bearbeiter = $be['Bearbeiter']; $userName = $this->createUsername($bearbeiter); $password = $this->createPassword(); $account = $this->accountFactory->createAccountWithPassword($userName, $password, ['Flow.Login:Administrator']); $this->accountRepository->add($account); $bearbeiterObject = new Bearbeiter(); $bearbeiterObject->setUid($uid); $bearbeiterObject->setBearbeiter($bearbeiter); $bearbeiterObject->setAccount($account); $this->bearbeiterRepository->add($bearbeiterObject); $this->persistenceManager->persistAll(); $this->createUsernamePasswordFile($userName, $password, $uid); $nBearbeiter++; } return $nBearbeiter; } }
/** * Checks if the given account is already in the account repository * * @param \TYPO3\Flow\Security\Account $account * @return bool */ public function doesAccountExist(\TYPO3\Flow\Security\Account $account) { $accountIdentifier = $account->getAccountIdentifier(); $authenticationProviderName = $account->getAuthenticationProviderName(); $existingAccount = $this->accountRepository->findByAccountIdentifierAndAuthenticationProviderName($accountIdentifier, $authenticationProviderName); return $existingAccount !== NULL; }
/** * Authenticates against a crowd instance. * * @param \TYPO3\Flow\Security\Authentication\TokenInterface $authenticationToken The token to be authenticated * @return void * @throws \TYPO3\Flow\Security\Exception\UnsupportedAuthenticationTokenException */ public function authenticate(TokenInterface $authenticationToken) { if (!$authenticationToken instanceof UsernamePassword) { throw new UnsupportedAuthenticationTokenException('This provider cannot authenticate the given token.', 1217339845); } $credentials = $authenticationToken->getCredentials(); if (is_array($credentials) && isset($credentials['username']) && isset($credentials['password'])) { $crowdAuthenticationResponse = $this->crowdClient->authenticate($credentials['username'], $credentials['password']); if ($crowdAuthenticationResponse !== NULL) { /** @var $account \TYPO3\Flow\Security\Account */ $account = NULL; $providerName = $this->name; $accountRepository = $this->accountRepository; $this->securityContext->withoutAuthorizationChecks(function () use($credentials, $providerName, $accountRepository, &$account) { $account = $accountRepository->findActiveByAccountIdentifierAndAuthenticationProviderName($credentials['username'], $providerName); }); if ($account === NULL) { $account = new Account(); $account->setAuthenticationProviderName($providerName); $account->setAccountIdentifier($credentials['username']); $this->accountRepository->add($account); } $authenticateRole = $this->policyService->getRole($this->options['authenticateRole']); if ($account->hasRole($authenticateRole) === FALSE) { $account->addRole($authenticateRole); } $crowdUser = $this->partyService->getAssignedPartyOfAccount($account); if ($crowdUser instanceof Person) { if ($crowdUser->getName()->getFirstName() !== $crowdAuthenticationResponse['first-name']) { $crowdUser->getName()->setFirstName($crowdAuthenticationResponse['first-name']); $this->partyRepository->update($crowdUser); } if ($crowdUser->getName()->getLastName() !== $crowdAuthenticationResponse['last-name']) { $crowdUser->getName()->setLastName($crowdAuthenticationResponse['last-name']); $this->partyRepository->update($crowdUser); } if ($crowdUser->getPrimaryElectronicAddress()->getIdentifier() !== $crowdAuthenticationResponse['email']) { $crowdUser->getPrimaryElectronicAddress()->setIdentifier($crowdAuthenticationResponse['email']); $this->partyRepository->update($crowdUser); } } else { $crowdUser = new Person(); $crowdUser->setName(new PersonName('', $crowdAuthenticationResponse['first-name'], '', $crowdAuthenticationResponse['last-name'])); $email = new ElectronicAddress(); $email->setIdentifier($crowdAuthenticationResponse['email']); $email->setType(ElectronicAddress::TYPE_EMAIL); $crowdUser->setPrimaryElectronicAddress($email); $this->partyRepository->add($crowdUser); $this->partyService->assignAccountToParty($account, $crowdUser); } $authenticationToken->setAuthenticationStatus(TokenInterface::AUTHENTICATION_SUCCESSFUL); $authenticationToken->setAccount($account); } else { $authenticationToken->setAuthenticationStatus(TokenInterface::WRONG_CREDENTIALS); } } elseif ($authenticationToken->getAuthenticationStatus() !== TokenInterface::AUTHENTICATION_SUCCESSFUL) { $authenticationToken->setAuthenticationStatus(TokenInterface::NO_CREDENTIALS_GIVEN); } }
/** * Sets a new password for the given user * * @param User $user The user to set the password for * @param string $password A new password * @return void */ public function setUserPassword(User $user, $password) { foreach ($user->getAccounts() as $account) { /** @var Account $account */ $account->setCredentialsSource($this->hashService->hashPassword($password, 'default')); $this->accountRepository->update($account); } }
/** * @return \TYPO3\Flow\Security\Account * @throws Exception * @throws \TYPO3\Flow\Persistence\Exception\IllegalObjectTypeException */ protected function generateTokenAccount() { $account = $this->securityContext->getAccount(); $tokenAccount = $this->accountFactory->createAccountWithPassword($account->getAccountIdentifier(), Algorithms::generateRandomString(25), array_keys($account->getRoles()), $this->apiToken->getAuthenticationProviderName()); $this->accountRepository->add($tokenAccount); $this->persistenceManager->persistAll(); return $tokenAccount; }
/** * @param TokenInterface $foreignAccountToken * @param AbstractClientToken $possibleOAuthTokenAuthenticatedWithoutParty */ public function setPartyOfAuthenticatedTokenAndAttachToAccountFor(TokenInterface $foreignAccountToken, AbstractClientToken $possibleOAuthTokenAuthenticatedWithoutParty) { $oauthAccount = $possibleOAuthTokenAuthenticatedWithoutParty->getAccount(); // TODO: this must be properly specifiable (the Roles to add) #$oauthAccount->setRoles(); $this->partyService->assignAccountToParty($oauthAccount, $this->partyService->getAssignedPartyOfAccount($foreignAccountToken)); $this->accountRepository->update($oauthAccount); }
/** * Deactivates the given user * * @param User $user The user to deactivate * @return void * @api */ public function deactivateUser(User $user) { foreach ($user->getAccounts() as $account) { /** @var Account $account */ $account->setExpirationDate($this->now); $this->accountRepository->update($account); } $this->emitUserDeactivated($user); }
/** * Tries to authenticate the given token. Sets isAuthenticated to TRUE if authentication succeeded. * * @param \TYPO3\Flow\Security\Authentication\TokenInterface $authenticationToken The token to be authenticated * @throws \TYPO3\Flow\Security\Exception\UnsupportedAuthenticationTokenException * @return void */ public function authenticate(\TYPO3\Flow\Security\Authentication\TokenInterface $authenticationToken) { if (!$authenticationToken instanceof OpauthToken) { throw new \TYPO3\Flow\Security\Exception\UnsupportedAuthenticationTokenException('This provider cannot authenticate the given token.', 1381598908); } $response = $this->opauth->getResponse(); if ($response !== NULL && $response->isAuthenticationSucceeded()) { $accountIdentifier = $this->accountService->createAccountIdentifier($response); $authenticationProviderName = $this->name; $account = $this->accountRepository->findByAccountIdentifierAndAuthenticationProviderName($accountIdentifier, $authenticationProviderName); if ($account !== NULL) { $authenticationToken->setAccount($account); $authenticationToken->setAuthenticationStatus(\TYPO3\Flow\Security\Authentication\TokenInterface::AUTHENTICATION_SUCCESSFUL); } } else { $authenticationToken->setAuthenticationStatus(\TYPO3\Flow\Security\Authentication\TokenInterface::NO_CREDENTIALS_GIVEN); } }
/** * @param \DLigo\Animaltool\Domain\Model\User $user * @return void */ public function deleteAction(User $user) { foreach ($user->getAccounts() as $account) { $this->accountRepository->remove($account); } $this->userRepository->remove($user); $this->addFlashMessage('Deleted a user.', '', \TYPO3\Flow\Error\Message::SEVERITY_OK, array(), 'flash.user.delete'); $this->redirect('index'); }
/** * Persists new Account. * * @param Account $account * * @return void */ public function finalizePersistingNewUser(Account $account) { $party = $account->getParty(); if ($party instanceof AbstractParty) { $this->partyRepository->add($party); } $this->accountRepository->add($account); $this->persistenceManager->persistAll(); }
/** * Tries to authenticate the given token. Sets isAuthenticated to TRUE if authentication succeeded. * * @param TokenInterface $authenticationToken The token to be authenticated * @throws \TYPO3\Flow\Security\Exception\UnsupportedAuthenticationTokenException * @return void */ public function authenticate(TokenInterface $authenticationToken) { if (!$authenticationToken instanceof AbstractClientToken) { throw new UnsupportedAuthenticationTokenException('This provider cannot authenticate the given token.', 1383754993); } $credentials = $authenticationToken->getCredentials(); // Inspect the received access token as documented in https://developers.facebook.com/docs/facebook-login/login-flow-for-web-no-jssdk/ $tokenInformation = $this->facebookTokenEndpoint->requestValidatedTokenInformation($credentials['accessToken']); if ($tokenInformation === FALSE) { $authenticationToken->setAuthenticationStatus(TokenInterface::WRONG_CREDENTIALS); return; } // Check if the permitted scopes suffice: $necessaryScopes = $this->options['scopes']; $scopesHavingPermissionFor = $tokenInformation['scopes']; $requiredButNotPermittedScopes = array_diff($necessaryScopes, $scopesHavingPermissionFor); if (count($requiredButNotPermittedScopes) > 0) { $authenticationToken->setAuthenticationStatus(TokenInterface::WRONG_CREDENTIALS); $this->securityLogger->log('The permitted scopes do not satisfy the required once.', LOG_NOTICE, array('necessaryScopes' => $necessaryScopes, 'allowedScopes' => $scopesHavingPermissionFor)); return; } // From here, we surely know the user is considered authenticated against the remote service, // yet to check if there is an immanent account present. $authenticationToken->setAuthenticationStatus(TokenInterface::AUTHENTICATION_SUCCESSFUL); /** @var $account \TYPO3\Flow\Security\Account */ $account = NULL; $providerName = $this->name; $accountRepository = $this->accountRepository; $this->securityContext->withoutAuthorizationChecks(function () use($tokenInformation, $providerName, $accountRepository, &$account) { $account = $accountRepository->findByAccountIdentifierAndAuthenticationProviderName($tokenInformation['user_id'], $providerName); }); if ($account === NULL) { $account = new Account(); $account->setAccountIdentifier($tokenInformation['user_id']); $account->setAuthenticationProviderName($providerName); $this->accountRepository->add($account); } $authenticationToken->setAccount($account); // request long-live token and attach that to the account $longLivedToken = $this->facebookTokenEndpoint->requestLongLivedToken($credentials['accessToken']); $account->setCredentialsSource($longLivedToken); $this->accountRepository->update($account); }
/** * @dataProvider personsDataProvider * @test */ public function personsAndAccountPersistingAndRetrievingWorksCorrectly($firstName, $middleName, $lastName, $emailAddress) { $person = new Domain\Model\Person(); $person->setName(new Domain\Model\PersonName('', $firstName, $middleName, $lastName)); $electronicAddress = new Domain\Model\ElectronicAddress(); $electronicAddress->setType(Domain\Model\ElectronicAddress::TYPE_EMAIL); $electronicAddress->setIdentifier($emailAddress); $person->setPrimaryElectronicAddress($electronicAddress); $account = $this->accountFactory->createAccountWithPassword($emailAddress, $this->persistenceManager->getIdentifierByObject($person)); $this->accountRepository->add($account); $person->addAccount($account); $this->partyRepository->add($person); $this->persistenceManager->persistAll(); $this->assertEquals(1, $this->partyRepository->countAll()); $this->persistenceManager->clearState(); $foundPerson = $this->partyRepository->findByIdentifier($this->persistenceManager->getIdentifierByObject($person)); $this->assertEquals($foundPerson->getName()->getFullName(), $person->getName()->getFullName()); $this->assertEquals($foundPerson->getName()->getFullName(), $firstName . ' ' . $middleName . ' ' . $lastName); $this->assertEquals($foundPerson->getPrimaryElectronicAddress()->getIdentifier(), $emailAddress); }
/** * Tries to authenticate the given token. Sets isAuthenticated to TRUE if authentication succeeded. * * @param TokenInterface $authenticationToken The token to be authenticated * @throws \TYPO3\Flow\Security\Exception\UnsupportedAuthenticationTokenException * @return void */ public function authenticate(TokenInterface $authenticationToken) { if (!$authenticationToken instanceof AbstractClientToken) { throw new UnsupportedAuthenticationTokenException('This provider cannot authenticate the given token.', 1383754993); } $credentials = $authenticationToken->getCredentials(); // There is no way to validate the Token or check the scopes at the moment apart from "trying" (and possibly receiving an access denied) // we could check the validity of the Token and the scopes here in the future when Instagram provides that // Only check if an access Token is present at this time and do a single test call if (isset($credentials['accessToken']) && $credentials['accessToken'] !== NULL) { // check if a secure request is possible (https://www.instagram.com/developer/secure-api-requests/) $userInfo = $this->instagramTokenEndpoint->validateSecureRequestCapability($credentials['accessToken']); if ($userInfo === FALSE) { $authenticationToken->setAuthenticationStatus(TokenInterface::WRONG_CREDENTIALS); $this->securityLogger->log('A secure call to the API with the provided accessToken and clientSecret was not possible', LOG_NOTICE); return FALSE; } } else { } // From here, we surely know the user is considered authenticated against the remote service, // yet to check if there is an immanent account present. $authenticationToken->setAuthenticationStatus(TokenInterface::AUTHENTICATION_SUCCESSFUL); /** @var $account \TYPO3\Flow\Security\Account */ $account = NULL; $providerName = $this->name; $accountRepository = $this->accountRepository; $this->securityContext->withoutAuthorizationChecks(function () use($userInfo, $providerName, $accountRepository, &$account) { $account = $accountRepository->findByAccountIdentifierAndAuthenticationProviderName($userInfo['id'], $providerName); }); if ($account === NULL) { $account = new Account(); $account->setAccountIdentifier($userInfo['id']); $account->setAuthenticationProviderName($providerName); $this->accountRepository->add($account); } $authenticationToken->setAccount($account); // the access token is valid for an "undefined time" according to instagram (so we cannot know when the user needs to log in again) $account->setCredentialsSource($credentials['accessToken']); $this->accountRepository->update($account); // check if a user is already attached to this account if ($this->partyService->getAssignedPartyOfAccount($account) === null || count($this->partyService->getAssignedPartyOfAccount($account)) < 1) { $user = $this->userService->getCurrentUser(); if ($user !== null) { $user->addAccount($account); $this->userService->updateUser($user); $this->persistenceManager->whitelistObject($user); } else { $this->securityLogger->logException(new Exception("The InstagramProvider was unable to determine the backend user, make sure the configuration Typo3BackendProvider requestPattern matches the Instagram Controller and the authentication strategy is set to 'atLeastOne' Token")); } } // persistAll is called automatically at the end of this function, account gets whitelisted to allow // persisting for an object thats tinkered with via a GET request $this->persistenceManager->whitelistObject($account); }
/** * save the registration * @param string $name * @param string $pass * @param string $pass2 * @param string $role */ public function createAction($name, $pass, $pass2, $role) { if ($name == '' || strlen($name) < 3) { $this->flashMessageContainer->addMessage(new \TYPO3\Flow\Error\Error('Username too short or empty')); $this->redirect('register', 'Login'); } else { if ($pass == '' || $pass != $pass2) { $this->flashMessageContainer->addMessage(new \TYPO3\Flow\Error\Error('Password too short or does not match')); $this->redirect('register', 'Login'); } else { // create a account with password an add it to the accountRepository $account = $this->accountFactory->createAccountWithPassword($name, $pass, array($role)); $this->accountRepository->add($account); // add a message and redirect to the login form $this->flashMessageContainer->addMessage(new \TYPO3\Flow\Error\Error('Account created. Please login.')); $this->redirect('index'); } } // redirect to the login form $this->redirect('index', 'Login'); }
/** * @param ResetPasswordFlow $resetPasswordFlow */ public function updatePasswordAction(ResetPasswordFlow $resetPasswordFlow) { $account = $this->accountRepository->findActiveByAccountIdentifierAndAuthenticationProviderName($resetPasswordFlow->getEmail(), 'Sandstorm.UserManagement:Login'); if (!$account) { $this->view->assign('accountNotFound', true); return; } $this->view->assign('success', true); $account->setCredentialsSource($resetPasswordFlow->getEncryptedPassword()); $this->accountRepository->update($account); $this->resetPasswordFlowRepository->remove($resetPasswordFlow); }
/** * @test */ public function authenticationWithCorrectCredentialsResetsFailedAuthenticationCount() { $this->authenticationToken->_set('credentials', ['username' => 'username', 'password' => 'wrongPW']); $this->persistedUsernamePasswordProvider->authenticate($this->authenticationToken); $account = $this->accountRepository->findActiveByAccountIdentifierAndAuthenticationProviderName('username', 'myTestProvider'); $this->assertEquals(1, $account->getFailedAuthenticationCount()); $this->authenticationToken->_set('credentials', ['username' => 'username', 'password' => 'password']); $this->persistedUsernamePasswordProvider->authenticate($this->authenticationToken); $account = $this->accountRepository->findActiveByAccountIdentifierAndAuthenticationProviderName('username', 'myTestProvider'); $this->assertEquals(new \DateTime(), $account->getLastSuccessfulAuthenticationDate()); $this->assertEquals(0, $account->getFailedAuthenticationCount()); }