Facebook авторизация с перезаписью URL

Я посвятил этому вопросу целый день и не могу решить... не могли бы вы помочь?

В чем проблема

Моя авторизация в Facebook (и Google+) не работает, если у меня активна перезапись URL.

Как это плохо

Если я захожу на страницу авторизации FB (или G+) и соглашаюсь с авторизацией, то я перенаправляюсь в свое приложение и снова в FB и снова, и я получаю:

This webpage has a redirect loop
ERR_TOO_MANY_REDIRECTS

Как выглядит мой класс авторизации на Facebook

В моем приложении я использую этот класс для входа в Facebook

<?php

namespace App\Presenters;

use Facebook\FacebookSession, 
    Facebook\FacebookRedirectLoginHelper, 
    Facebook\FacebookRequestException, 
    Facebook\GraphUser,
    Facebook\FacebookRequest;

class FacebookPresenter extends BasePresenter {

  /** @var \App\Model\UserManager @inject */
  public $um;

  /**
   * Default facebook action
   */
  public function actionDefault() {

    // Start session
    if (session_status() == PHP_SESSION_NONE) {
      session_start();
    }

    // Configuration
    $appId = $this->context->parameters['facebook']['appId'];
    $appSecret = $this->context->parameters['facebook']['appSecret'];
    $scope = array('email');

    // This producs always valid route based on router configuration
    $loginRedirectUrl = $this->link('//Facebook:default');    

    FacebookSession::setDefaultApplication($appId, $appSecret);
    $helper = new FacebookRedirectLoginHelper($loginRedirectUrl);

    // Get facebook session
    try {
      $session = $helper->getSessionFromRedirect();
    } catch(FacebookRequestException $ex) {
     $this->redirectUrl($helper->getLoginUrl($scope));
    } catch(\Exception $ex) {
      $this->redirectUrl($helper->getLoginUrl($scope));
    }

    // Session was established
    if ($session) {
      try {
        $req = new FacebookRequest($session, 'GET', '/me');
        $userProfile = $req->execute()->getGraphObject(GraphUser::className());
        $fbArr = $userProfile->asArray();
        $fbId = $fbArr['id'];
        $fbArr['picture'] = "https://graph.facebook.com/$fbId/picture?width=360&height=360";

        // Login or register
        $this->loginOrRegister($fbId, $fbArr);

        // After facebook login redirect to homepage
        $this->flashMessage("Facebook login was successful", "success");
        $this->redirect('Homepage:');        
      } catch (FacebookRequestException $e) {
        $this->redirectUrl($helper->getLoginUrl($scope));
      }

    // Session was not established
    } else{
      $this->redirectUrl($helper->getLoginUrl($scope));
    }
  }

  /**
   * Login or registers user
   * @param String $fbId
   * @param array $fbArr
   */
  protected function loginOrRegister($fbId, $fbArr) {

    // Try to login with given ID
    try {

      // Login
      $this->user->login(NULL, NULL, $fbId, NULL);

      // Try to update user's picture
      if (isset($fbArr['picture']) && strlen($fbArr['picture']) > 0) {
        $this->um->updateAvatar($fbArr['picture'], $fbId, null);
      }

    } catch (\Nette\Security\AuthenticationException $ex) {

      // Retrieve social info
      $email = isset($fbArr['email']) ? $fbArr['email'] : "";
      $firstName = isset($fbArr['first_name']) ? $fbArr['first_name'] : "";
      $lastName = isset($fbArr['last_name']) ? $fbArr['last_name'] : "";
      $picture = isset($fbArr['picture']) ? $fbArr['picture'] : null;

      // Check if there is user with acquired email
      // If he/she is, then update his facebook ID and verify him/her and login
      $tmpUser = $this->createDao("AppUser")->loadByEmail($email);
      if ($tmpUser && $tmpUser->isPopulated()) {
        $tmpUser->updateFbId($fbId);
        $tmpUser->updateAvatar($picture, $fbId, null);
        $tmpUser->verify($tmpUser->getVCode());
        $this->user->login(NULL, NULL, $fbId, NULL);
      } else {

        // Send user to registration
        $this->redirect('Sign:register', array(
            'name' => ($firstName . " " . $lastName),
            'email' => $email, 
            'fbId' => $fbId)
        );
      }
    }
  }
}

Как выглядит конфигурация моего роутера

Если rewrite имеет значение false, то простой роутер активен и все работает, иначе нет

  /**
   * @return \Nette\Application\IRouter
   */
  public static function createRouter() {

    $rewrite = true;

    // Simple router
    if (!$rewrite) {
      return new SimpleRouter('Homepage:default');
    }

    // Full router list
    $router = new RouteList();
    $router[] = new Route('', array(
        'presenter' => 'Homepage',
        'action' => 'default',
    ));
    $router[] = new Route('story', 'Homepage:story');
    $router[] = new Route('feed', 'Homepage:feed');
    $router[] = new Route('register', 'Sign:register');
    $router[] = new Route('verify', 'Sign:verify');
    $router[] = new Route('in', 'Sign:in');
    $router[] = new Route('user/<id>', 'User:default');
    $router[] = new Route('<presenter>/<action>[/<id>]', 'Homepage:default');
    return $router;
  }

Как выглядят мои URL

Для простого роутера:

https://www.facebook.com/v2.2/dialog/oauth?client_id=478905205596609&redirect_uri=http://localhost/~tester/testproject/www/?presenter=Facebook&state=4b63bfb3c9507c89347455663c2f5279&sdk=php-sdk-4.0.16&scope=email

Для переписанных URL:

https://www.facebook.com/v2.2/dialog/oauth?client_id=478904678929995&redirect_uri=http://localhost/~tester/testproject/www/facebook/&state=536560378c582ddb17f0fe821cf20846&sdk=php-sdk-4.0.16&scope=email

ОБНОВЛЕНИЕ 2015-06-12

Я нашел проблемную часть кода.... если перезапись URL активна, то

$session = $helper->getSessionFromRedirect();

всегда равно null, поэтому код всегда идет до последнего в actionDefault. Конечно, я нашел эту тему. Почему getSessionFromRedirect() возвращает NULL?... однако я вызываю методы getSessionFromRedirect и getLoginUrl в правильном порядке

1 ответ

Решение

Этот парень сделал пакет, который может вам помочь. Есть также класс под названием FacebookAuthenticator, основная проблема в том, что в нем отсутствует документация, поэтому вам нужно просто проанализировать исходный код и продолжить работу с ним.

Удачи

Другие вопросы по тегам