ich habe vor einiger Zeit eine API Anmeldung mit Wargaming ( WorldOfTanks ) gebaut. als Grundlage dafür habe ich das Twitterauth Modul von dustiii genommen.
Soweit funktioniert die Anmeldung wie sie soll.
Hier mal die AuthPHP
<?php namespace Modules\wargamingauth\Controllers; use Ilch\Controller\Frontend; use Modules\wargamingauth\Libs\wargamingOAuth; use Modules\wargamingauth\Mappers\DbLog; use Modules\User\Mappers\AuthProvider; use Modules\User\Mappers\AuthToken as AuthTokenMapper; use Modules\Phonebook\Models\Book; use Modules\Phonebook\Mappers\Phonebook as PhonebookMapper; use Modules\User\Mappers\User as UserMapper; use Modules\User\Mappers\Group; use Modules\User\Models\AuthProviderUser; use Modules\User\Models\AuthToken as AuthTokenModel; use Modules\User\Models\User; use Modules\User\Service\Password as PasswordService; use Ilch\Validation; use Modules\wargamingauth\Mappers\Wargaming as WargamingMapper; use Modules\wargamingauth\Models\Wargaming as WargamingModel; use Modules\wargamingauth\Mappers\User as WGUserMapper; use Modules\wargamingauth\Models\User as WGUserModel; class Auth extends Frontend { /** * @var DbLog instance */ protected $dbLog; /** * Renders the register form. */ public function registAction() { $oauth = array_dot($_SESSION, 'wargamingauth.login'); $groupMapper = new Group(); $userGroup = $groupMapper->getGroupByName($oauth['clantag']); //var_dump($userGroup); //die(); if (! array_dot($_SESSION, 'wargamingauth.login') || array_dot($_SESSION, 'wargamingauth.login.expires') < time() || !$userGroup ) { $this->addMessage('wargamingauth.logindenied', 'danger'); $this->redirect(['module' => 'user', 'controller' => 'login', 'action' => 'index']); } $this->getView()->set('rules', $this->getConfig()->get('regist_rules')); $this->getView()->set('user', $oauth); } /** * Saves the new user to the database. */ public function saveAction() { if (!$this->getRequest()->isPost()) { $this->addMessage('badRequest'); $this->redirect('/'); } if (! array_dot($_SESSION, 'wargamingauth.login') || array_dot($_SESSION, 'wargamingauth.login.expires') < time()) { $this->addMessage('badRequest'); $this->redirect(['module' => 'user', 'controller' => 'login', 'action' => 'index']); } $input = [ 'userName' => trim($this->getRequest()->getPost('userName')), 'email' => trim($this->getRequest()->getPost('email')), 'phonenumber' => trim($this->getRequest()->getPost('phonenumber')), ]; $validation = Validation::create($input, [ 'userName' => 'required|unique:users,name', 'email' => 'required|email|unique:users,email', 'phonenumber' => 'required', ]); $oauth = array_dot($_SESSION, 'wargamingauth.login'); if ($validation->isValid()) { // register user $registMapper = new UserMapper(); $groupMapper = new Group(); $userGroup = $groupMapper->getGroupByName($oauth['clantag']); $currentDate = new \Ilch\Date(); $user = (new User()) ->setName($input['userName']) ->setPassword((new PasswordService())->hash(PasswordService::generateSecurePassword(32))) ->setEmail($input['email']) ->setDateCreated($currentDate->format('Y-m-d H:i:s', true)) ->addGroup($userGroup) ->setDateConfirmed($currentDate->format('Y-m-d H:i:s', true)); $userId = $registMapper->save($user); $phoneBookMapper = new PhonebookMapper(); $phonebook = (new Book()) ->setUser_id($userId) ->setClantag($oauth['clantag']) ->setPhonenumber($input['phonenumber']); $phonenumberentry = $phoneBookMapper->save($phonebook); $authProviderUser = (new AuthProviderUser()) ->setIdentifier($oauth['user_id']) ->setProvider('wargaming') ->setOauthToken($oauth['oauth_token']) ->setOauthTokenSecret($oauth['oauth_token_secret']) ->setScreenName($oauth['screen_name']) ->setUserId($userId); $link = (new AuthProvider())->linkProviderWithUser($authProviderUser); if ($link === true) { $_SESSION['user_id'] = $userId; $this->addMessage('wargamingauth.linksuccess'); $this->redirect(['module' => 'user', 'controller' => 'panel', 'action' => 'index']); } $this->addMessage('wargamingauth.linkfailed', 'danger'); $this->redirect('/'); } $this->addMessage($validation->getErrorBag()->getErrorMessages(), 'danger', true); $this->redirect() ->withInput() ->withErrors($validation->getErrorBag()) ->to(['action' => 'regist']); } public function unlinkAction() { if (loggedIn()) { if ($this->getRequest()->isPost()) { $authProvider = new AuthProvider(); $res = $authProvider->unlinkUser('wargaming', currentUser()->getId()); if ($res > 0) { $this->addMessage('wargamingauth.unlinkedsuccessfully'); $this->redirect(['module' => 'user', 'controller' => 'panel', 'action' => 'providers']); } $this->addMessage('wargamingauth.couldnotunlink', 'danger'); $this->redirect('/'); } $this->addMessage('wargamingauth.badrequest', 'danger'); $this->redirect('/'); } $this->addMessage('wargamingauth.notauthenticated', 'danger'); $this->redirect('/'); } /** * Initialize authentication. */ public function indexAction() { $callbackUrl = $this->getLayout()->getUrl([ 'module' => 'wargamingauth', 'controller' => 'auth', 'action' => 'callback', ]); $auth = new wargamingOAuth( $this->getConfig()->get('wargamingauth_consumer_key'), 'popup', 1, null, $callbackUrl ); try { $auth->obtainTokens(); // var_dump($auth->getAuthenticationEndpoint()); // die(); $this->redirect($auth->getAuthenticationEndpoint()); // wargaming openid } catch (\Exception $e) { $this->addMessage('wargamingauth.authenticationfailure', 'danger'); if (loggedIn()) { $this->redirect(['module' => 'user', 'controller' => 'panel', 'action' => 'providers']); } $this->redirect(['module' => 'user', 'controller' => 'login', 'action' => 'index']); } } /** * Callback action. */ public function callbackAction() { //var_dump($_GET); //die(); $auth = new wargamingOAuth( $this->getConfig()->get('wargamingauth_consumer_key') ); try { //var_dump($this->getRequest()); //die(); $auth->handleCallback($this->getRequest()); //var_dump($auth->getToken() . '<br>' . $auth->getAccount_id() . '<br>' . $auth->getExpires_at() . '<br>'); $auth->get_clan_id(); $auth->get_memberData(); $auth->get_clanData(); //var_dump($auth->getClantag() . '<br>' . $auth->getClan_id() . '<br>' . $auth->getToken() . '<br>'. $auth->getTreasury(). '<br>' ); //die(); // $auth->convertTokens(); $wargamingUser = array( 'user_id' => $auth->getAccount_id(), 'oauth_token' => $auth->getToken(), 'screen_name' => $auth->getAccount_name(), 'oauth_token_user' => null, 'clantag' => $auth->getClantag(), 'clan_id' => $auth->getClan_id(), 'role' => $auth->getRole(), 'expires_at' => $auth->getExpires_at(), 'treasury' => $auth->getTreasury() ); $authProvider = new AuthProvider(); $existingLink = $authProvider->providerAccountIsLinked('wargaming', $wargamingUser['user_id']); $_SESSION['clantag'] = $wargamingUser['clantag']; $_SESSION['account_name'] = $wargamingUser['screen_name']; $_SESSION['account_id'] = $wargamingUser['user_id']; $_SESSION['role'] = $wargamingUser['role']; if (loggedIn()) { if ($authProvider->hasProviderLinked('wargaming', currentUser()->getId())) { $this->dbLog()->info( "User " . currentUser()->getName() . " had provider already linked.", [ 'userId' => currentUser()->getId(), 'userName' => currentUser()->getName(), 'wargamingAccount' => $wargamingUser ] ); $this->addMessage('providerAlreadyLinked', 'danger'); $this->redirect(['module' => 'user', 'controller' => 'panel', 'action' => 'providers']); } if ($existingLink === true) { $this->dbLog()->info( "User " . currentUser()->getName() . " tried to link an already linked wargaming account.", [ 'userId' => currentUser()->getId(), 'userName' => currentUser()->getName(), 'wargamingAccount' => $wargamingUser ] ); $this->addMessage('accountAlreadyLinkedToDifferentUser', 'danger'); $this->redirect(['module' => 'user', 'controller' => 'panel', 'action' => 'providers']); } $authProviderUser = (new AuthProviderUser()) ->setIdentifier($wargamingUser['user_id']) ->setProvider('wargaming') ->setOauthToken($wargamingUser['oauth_token']) ->setOauthTokenSecret($wargamingUser['oauth_token_user']) ->setScreenName($wargamingUser['screen_name']) ->setUserId(currentUser()->getId()); $link = $authProvider->linkProviderWithUser($authProviderUser); if ($link === true) { $this->dbLog()->info( "User " . currentUser()->getName() . " has linked a wargaming account.", [ 'userId' => currentUser()->getId(), 'userName' => currentUser()->getName(), 'wargamingAccount' => $wargamingUser ] ); $this->addMessage('wargamingauth.linksuccess'); $this->redirect(['module' => 'user', 'controller' => 'panel', 'action' => 'providers']); } $this->dbLog()->error( "User " . currentUser()->getName() . " could not link his wargaming account.", [ 'userId' => currentUser()->getId(), 'userName' => currentUser()->getName(), 'wargamingAccount' => $wargamingUser ] ); $this->addMessage('linkFailed', 'danger'); $this->redirect(['module' => 'user', 'controller' => 'panel', 'action' => 'providers']); } if ($existingLink === true) { $userId = $authProvider->getUserIdByProvider('wargaming', $wargamingUser['user_id']); if (is_null($userId)) { $this->addMessage('couldNotFindRequestedUser'); $this->redirect(['module' => 'user', 'controller' => 'login', 'action' => 'index']); } /** Test Update Username and Screenname * * @var \Modules\wargamingauth\Mappers\User $wgusermapper */ $wgusermapper = new WGUserMapper(); if ($_SESSION['account_name'] != $wgusermapper->getNameById($userId)->getName() AND $wgusermapper->getScreen_nameByUser_Id($userId)->getScreen_name()){ $UserModel = new WGUserModel(); $UserModel->setUser_id($userId) ->setScreen_name($_SESSION['account_name']); $wgusermapper->updateScreen_name($UserModel); $UserModel->setId($userId) ->setName($_SESSION['account_name']); $wgusermapper->updateName($UserModel); } $authTokenModel = new AuthTokenModel(); // 9 bytes of random data (base64 encoded to 12 characters) for the selector. // This provides 72 bits of keyspace and therefore 236 bits of collision resistance (birthday attacks) $authTokenModel->setSelector(base64_encode(openssl_random_pseudo_bytes(9))); // 33 bytes (264 bits) of randomness for the actual authenticator. This should be unpredictable in all practical scenarios. $authenticator = openssl_random_pseudo_bytes(33); // SHA256 hash of the authenticator. This mitigates the risk of user impersonation following information leaks. $authTokenModel->setToken(hash('sha256', $authenticator)); $authTokenModel->setUserid($userId); $authTokenModel->setExpires(date('Y-m-d\TH:i:s', strtotime( '+1 day' ) )); setcookie('remember', $authTokenModel->getSelector().':'.base64_encode($authenticator), strtotime( '+1 day' ), '/', $_SERVER['SERVER_NAME'], (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off'), true); setcookie('clantag', $_SESSION['clantag'], strtotime( '+1 day' ), '/', $_SERVER['SERVER_NAME'], (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off'), true); setcookie('account_name', $_SESSION['account_name'], strtotime( '+1 day' ), '/', $_SERVER['SERVER_NAME'], (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off'), true); setcookie('account_id', $_SESSION['account_id'], strtotime( '+1 day' ), '/', $_SERVER['SERVER_NAME'], (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off'), true); setcookie('role', $_SESSION['role'], strtotime( '+1 day' ), '/', $_SERVER['SERVER_NAME'], (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off'), true); $authTokenMapper = new AuthTokenMapper(); $authTokenMapper->addAuthToken($authTokenModel); $_SESSION['user_id'] = $userId; // treasury in db $WargamingMapper = new WargamingMapper(); $model = new WargamingModel(); $model->setClantag($wargamingUser['clantag']); $model->setClan_id($wargamingUser['clan_id']); $model->setTreasury($wargamingUser['treasury']);; $WargamingMapper->save($model); $this->addMessage('wargamingauth.loginsuccess'); $this->redirect('/'); } if ($existingLink === false && ! loggedIn() && ! $this->getConfig()->get('regist_accept')) { $this->addMessage('wargamingauth.messages.registrationNotAllowed', 'danger'); $this->redirect(['module' => 'user', 'controller' => 'login', 'action' => 'index']); } array_dot_set($_SESSION, 'wargamingauth.login', $wargamingUser); array_dot_set($_SESSION, 'wargamingauth.login.expires', strtotime('+5 minutes')); //array_dot_set($_SESSION, 'wargamingauth.login.expires', $wargamingUser['expires_at']); $this->redirect(['action' => 'regist']); } catch (\Exception $e) { $this->addMessage('wargamingauth.authenticationfailure', 'danger'); if (loggedIn()) { $this->redirect(['module' => 'user', 'controller' => 'panel', 'action' => 'providers']); } else { $this->redirect(['module' => 'user', 'controller' => 'login', 'action' => 'index']); } } } /** * @return DbLog */ protected function dbLog() { if ($this->dbLog instanceof DbLog) { return $this->dbLog; } return $this->dbLog = new DbLog(); } }
Leider habe ich diverse Schwierigkeiten.
1. Im Moment Speichere ich die Wargaming API Wehrte in eine Session und dann anschließend in einen Cookie. Sie CallBack Function
-> Ist es möglich auf soviele Coockies zu verzichten. die Wehrte virtuel über die Funktion
register->setund
register->getzu nutzen? Oder wofür sind diese funktionen Gedacht.
2. Mir ist aufgefallen, dass im Ilch keine Prüfung drin ist, wenn Cookie Abgelaufen, melde User ab.
-> Hat mehrere Gründe. Da ich im Moment ja die Daten, wie Account_Name, Account_id, role und clantag im Cookie habe. Die Ablauffrist auf +1day steht. und ich diese Daten Intern für verschiedene Module nutze und brauche.
Nun ist es so. Member xyz hat sich vor 23 Stunden angemeldet. nun kommt er wieder auf die Seite, ist noch angemeldet durch remember me cookie mit den anderen. nun passiert es. die cookies laufen aus. und er will was intern mit den wg daten machen. Sei es Im Recruting Modul oder im Away Modul, welches ich erweitert habe.
Cookies sind weg. und was bleibt sind dann fehler....
Gibt es eine Möglichkeit eine Funktion im Ilch zu implimentieren, welche prüft ob cookie abgelaufewn,m wenn ja.. session destroy und logout?
verwendete ilch Version: 2.1.x
betroffene Homepage: www.r1sing.de