/** * @test */ public function getAssignedPartyOfAccountCachesParty() { $this->mockPersistenceManager->expects($this->any())->method('getIdentifierByObject')->will($this->returnValue('723e3913-f803-42c8-a44c-fd7115f555c3')); $this->mockPartyRepository->expects($this->once())->method('findOneHavingAccount')->with($this->account)->will($this->returnValue($this->party)); $this->party->addAccount($this->account); $assignedParty = $this->partyService->getAssignedPartyOfAccount($this->account); $this->assertSame($this->party, $assignedParty); $assignedParty = $this->partyService->getAssignedPartyOfAccount($this->account); $this->assertSame($this->party, $assignedParty); }
/** * Retrieves an existing user by the given username * * @param string $username The username * @param string $authenticationProviderName Name of the authentication provider to use. Example: "Typo3BackendProvider" * @return User The user, or null if the user does not exist * @throws Exception * @api */ public function getUser($username, $authenticationProviderName = null) { if ($authenticationProviderName !== null && isset($this->runtimeUserCache['a_' . $authenticationProviderName][$username])) { return $this->runtimeUserCache['a_' . $authenticationProviderName][$username]; } elseif (isset($this->runtimeUserCache['u_' . $username])) { return $this->runtimeUserCache['u_' . $username]; } $account = $this->accountRepository->findByAccountIdentifierAndAuthenticationProviderName($username, $authenticationProviderName ?: $this->defaultAuthenticationProviderName); if (!$account instanceof Account) { return null; } $user = $this->partyService->getAssignedPartyOfAccount($account); if (!$user instanceof User) { throw new Exception(sprintf('Unexpected user type "%s". An account with the identifier "%s" exists, but the corresponding party is not a Neos User.', get_class($user), $username), 1422270948); } if ($authenticationProviderName !== null) { if (!isset($this->runtimeUserCache['a_' . $authenticationProviderName])) { $this->runtimeUserCache['a_' . $authenticationProviderName] = []; } $this->runtimeUserCache['a_' . $authenticationProviderName][$username] = $user; } else { $this->runtimeUserCache['u_' . $username] = $user; } return $user; }
/** * 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); } }
/** * This returns the (first) *authenticated* OAuth token which doesn't have a party attached. * *@return AbstractClientToken */ public function getChargedAuthenticatedTokenHavingPartyAttached() { /** @var $token AbstractClientToken */ foreach ((array) $this->securityContext->getAuthenticationTokensOfType($this->getTokenClassName()) as $token) { if ($token->getAuthenticationStatus() === TokenInterface::AUTHENTICATION_SUCCESSFUL && ($token->getAccount() !== NULL || $this->partyService->getAssignedPartyOfAccount($token->getAccount()) !== NULL)) { return $token; } } return NULL; }
/** * 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); }
/** * @param string $sso * @param string $sig * @return void * @Flow\SkipCsrfProtection */ public function authenticateDiscourseUserAction($sso = '', $sig = '') { if ($sso === '' && $sig === '') { $argumentsOfInterceptedRequest = $this->securityContext->getInterceptedRequest()->getArguments(); if (!isset($argumentsOfInterceptedRequest['sso']) || !isset($argumentsOfInterceptedRequest['sig'])) { return 'This page needs to be called with valid sso and sig arguments from crowd!'; } $sso = $argumentsOfInterceptedRequest['sso']; $sig = $argumentsOfInterceptedRequest['sig']; } if (hash_hmac('sha256', $sso, $this->ssoSecret) === $sig) { parse_str(base64_decode($sso), $incomingPayload); $currentAccount = $this->securityContext->getAccount(); /** @var Person $crowdUser */ $crowdUser = $this->partyService->getAssignedPartyOfAccount($currentAccount); $outgoingPayload = base64_encode(http_build_query(array('nonce' => $incomingPayload['nonce'], 'email' => $crowdUser->getPrimaryElectronicAddress()->getIdentifier(), 'name' => $crowdUser->getName()->getFullName(), 'username' => $currentAccount->getAccountIdentifier(), 'external_id' => $currentAccount->getAccountIdentifier()), '', '&', PHP_QUERY_RFC3986)); $outgoingSignature = hash_hmac('sha256', $outgoingPayload, $this->ssoSecret); $this->redirectToUri(sprintf('%s?%s', $this->discourseSsoUrl, http_build_query(array('sso' => $outgoingPayload, 'sig' => $outgoingSignature), '', '&', PHP_QUERY_RFC3986)), 0, 302); } return 'Sorry, we couldn\'t log you in'; }
/** * Retrieves an existing user by the given username * * @param string $username The username * @param string $authenticationProviderName Name of the authentication provider to use. Example: "Typo3BackendProvider" * @return User The user, or NULL if the user does not exist * @throws Exception * @api */ public function getUser($username, $authenticationProviderName = NULL) { $account = $this->accountRepository->findByAccountIdentifierAndAuthenticationProviderName($username, $authenticationProviderName ?: $this->defaultAuthenticationProviderName); if (!$account instanceof Account) { return NULL; } $user = $this->partyService->getAssignedPartyOfAccount($account); if (!$user instanceof User) { throw new Exception(sprintf('Unexpected user type "%s". An account with the identifier "%s" exists, but the corresponding party is not a Neos User.', get_class($user), $username), 1422270948); } return $user; }
/** * @param Account $account * @throws \Exception * @return NodeInterface */ public function getProfileNodeOfAccount(Account $account) { $party = $this->partyService->getAssignedPartyOfAccount($account); $profileNodeIdentifier = $party->getPreferences()->get('profileNodeIdentifier'); if ($profileNodeIdentifier !== NULL) { $contentContext = $this->contextFactory->create(array()); $profileNode = $contentContext->getNodeByIdentifier($profileNodeIdentifier); if (!isset($profileNode) || !$profileNode instanceof NodeInterface) { throw new \Exception('Profile not found'); } return $profileNode; } }
/** * Adds a user whose User object has been created elsewhere * * This method basically "creates" a user like createUser() would, except that it does not create the User * object itself. If you need to create the User object elsewhere, for example in your ActionController, make sure * to call this method for registering the new user instead of adding it to the PartyRepository manually. * * This method also creates a new user workspace for the given user if no such workspace exist. * * @param string $username The username of the user to be created. * @param string $password Password of the user to be created * @param User $user The pre-built user object to start with * @param array $roleIdentifiers A list of role identifiers to assign * @param string $authenticationProviderName Name of the authentication provider to use. Example: "Typo3BackendProvider" * @return User The same user object * @api */ public function addUser($username, $password, User $user, array $roleIdentifiers = null, $authenticationProviderName = null) { if ($roleIdentifiers === null) { $roleIdentifiers = array('TYPO3.Neos:Editor'); } $roleIdentifiers = $this->normalizeRoleIdentifiers($roleIdentifiers); $account = $this->accountFactory->createAccountWithPassword($username, $password, $roleIdentifiers, $authenticationProviderName ?: $this->defaultAuthenticationProviderName); $this->partyService->assignAccountToParty($account, $user); $this->partyRepository->add($user); $this->accountRepository->add($account); $this->createPersonalWorkspace($user, $account); $this->emitUserCreated($user); return $user; }
/** * @param \TYPO3\Flow\Security\Account $account * @param \TYPO3\Flow\Http\Cookie $sessionCookie * @return \stdClass */ protected function buildAccountDTO(\TYPO3\Flow\Security\Account $account, \TYPO3\Flow\Http\Cookie $sessionCookie = NULL) { $person = $this->partyService->getAssignedPartyOfAccount($account); $simpleAccount = new \stdClass(); $simpleAccount->displayName = (string) $person->getName(); if ($sessionCookie !== NULL) { $simpleAccount->sessionIdentifier = $sessionCookie->getValue(); } $simpleAccount->profile = sprintf('//typo3.org/services/userimage.php?username=%s&size=big', $account->getAccountIdentifier()); $simpleAccount->roles = []; foreach ($account->getRoles() as $role) { /** @var $role \TYPO3\Flow\Security\Policy\Role */ $simpleAccount->roles[] = $role->getName(); } return $simpleAccount; }
/** * @param Account $account * @param array $userdata * @return \TYPO3\Flow\Security\Account */ protected function updateAccount(Account $account, array $userdata) { $person = $this->partyService->getAssignedPartyOfAccount($account); if ($person === null) { $person = new Person(); $this->partyRepository->add($person); $this->partyService->assignAccountToParty($account, $person); } if (!$account->getRoles()) { $account->setRoles(array($this->policyService->getRole('T3DD.Backend:Authenticated'))); } $this->updatePerson($person, $userdata); $this->accountRepository->update($account); $this->persistenceManager->persistAll(); return $account; }
/** * @param Registration $registration */ public function createAction(Registration $registration) { $pendingRegistration = $this->registrationRepository->findOneByAccountAndNotCompleted($this->securityContext->getAccount()); if ($pendingRegistration !== NULL) { $this->view->assign('value', $this->dataTransferObjectFactory->getDataTransferObject($pendingRegistration)); return; } $registrationLock = new \TYPO3\Flow\Utility\Lock\Lock('T3DD-Registration'); $account = $this->securityContext->getAccount(); $registrationEntity = $registration->getPayload(); $registrationEntity->setAccount($account); $ticketRequest = []; $roomRequests = []; $participantPosition = 0; /** @var \T3DD\Backend\Domain\Model\Registration\Participant $participant */ foreach ($registrationEntity->getParticipants() as $participant) { $participant->setPositionInRegistration($participantPosition++); $participant->setRegistration($registrationEntity); if ($participant->isRegistrant()) { $person = $this->partyService->getAssignedPartyOfAccount($account); $participant->setAccount($account); $participant->setPerson($person); if ($participant->getRoomSize() > 0) { for ($i = 1; $i < $participant->getRoomSize(); $i++) { $participant->addRoomMate(new \T3DD\Backend\Domain\Model\Registration\Mate()); } } } $ticketRequest[] = $participant->getTicketRequest(); $roomRequest = $participant->getRoomRequest(); if ($roomRequest !== NULL) { $roomRequests[] = $roomRequest; } } $this->bookableService->requestTickets($ticketRequest); $this->bookableService->requestRooms($roomRequests); $this->registrationRepository->add($registrationEntity); $this->persistenceManager->persistAll(); $registrationLock->release(); $this->view->assign('value', $registration); }
/** * @return string */ public function getDisplayName() { return (string) $this->partyService->getAssignedPartyOfAccount($this->payload)->getName(); }
/** * @return void */ public function indexAction() { $account = $this->securityContext->getAccount(); $this->view->assign('account', $account); $this->view->assign('person', $this->partyService->getAssignedPartyOfAccount($account)); }