无法让Google OAuth2在CakePHP 3应用上发挥作用

时间:2016-09-30 14:37:24

标签: php angularjs cakephp oauth-2.0 google-oauth

首先,感谢任何与我一起调查此事的人。我只想说我是CakePHP的初学者。虽然我的网站功能齐全,但它相对简单,因此我没有从开发它的框架中获得太多的知识。让我们说,我是一个基本用户,基本问题不太重要......!

所以,我目前正在开发一个使用AngularJS和CakePHP 3的网站.CakePHP部分是一个REST API,当然还有Angular,网站的客户端。

有些页面只能由注册/登录的用户访问,或者至少是电子邮件匹配的用户@ mydomain.com(然后应该注册)。

在fisrt,API /网站旨在通过HTTP Basic身份验证处理此问题,但两天前我被要求通过Google OAuth2身份验证来处理它。

所以我试过看看是否有人在CakePHP3上做过,没有插件(有人向我提到了CakeDC / users插件,但是文档非常糟糕,以至于我没有去那里......) 。我找到了这些:

http://caketuts.key-conseil.fr/index.php/2015/05/22/integrer-lapi-oauth2-de-google-avec-cakephp-v3/(法语,抱歉,但代码很清楚)

http://blog.jainsiddharth21.com/2013/04/29/login-with-google-in-cakephp/(这是可以理解的,但不是我选择做的,但仍然有用且接近我的代码)

虽然我的代码差不多90%喜欢这个第一个链接,但我似乎无法按照预期的方式运行身份验证。

这是我的代码:

AppController.php:

public function initialize() {
    parent::initialize();

    $this->loadComponent('RequestHandler');
    $this->loadComponent('Flash');

    $this->loadComponent('Auth', [
        'loginAction' => [
            'controller' => 'Users',
            'action' => 'googlelogin',
        ],
        'authenticate' => [
            'Form' => [
                'fields' => [
                    'username' => 'email',
                    'password' => 'password'
                ]
            ]
        ],
        'authError' => __("You don't have rights for this page"),
        'authorize' => ['Controller'],
        'unauthorizedRedirect' => [
            'controller' => 'Users',
            'action' => 'forbidden'
        ],
        'loginRedirect' => [
            'controller' => 'myHomePage',
        ],
        'logoutRedirect' => [
            'controller' => 'Users',
            'action' => 'googlelogin'
        ]
    ]);
}

UsersController.php

public function googlelogin() {

    $client = new Google_Client();
    $client->setClientId(GOOGLE_OAUTH_CLIENT_ID);
    $client->setClientSecret(GOOGLE_OAUTH_CLIENT_SECRET);
    $client->setRedirectUri(GOOGLE_OAUTH_REDIRECT_URI);

    $client->setScopes(array(
        "https://www.googleapis.com/auth/userinfo.profile",
        'https://www.googleapis.com/auth/userinfo.email'
    ));
    $url = $client->createAuthUrl();
    $this->redirect($url);
}

public function confirmLogin() {
    $client = new Google_Client();
    $client->setClientId(GOOGLE_OAUTH_CLIENT_ID);
    $client->setClientSecret(GOOGLE_OAUTH_CLIENT_SECRET);
    $client->setRedirectUri(GOOGLE_OAUTH_REDIRECT_URI);

    $client->setScopes(array(
        "https://www.googleapis.com/auth/userinfo.profile",
        'https://www.googleapis.com/auth/userinfo.email'
    ));
    $client->setApprovalPrompt('auto');

    if (isset($this->request->query['code'])) {
        $client->authenticate($this->request->query['code']);
        $this->request->Session()->write('access_token', $client->getAccessToken());
    }

    if ($this->request->Session()->check('access_token') && ($this->request->Session()->read('access_token'))) {
        $client->setAccessToken($this->request->Session()->read('access_token'));
    }

    if ($client->getAccessToken()) {
        $this->request->Session()->write('access_token', $client->getAccessToken());
        $oauth2 = new Google_Service_Oauth2($client);
        $user = $oauth2->userinfo->get();
        try {
            if (!empty($user)) {
                if (preg_match("/(@mydomain\.com)$/", $user['email'])) {
                        $result = $this->Users->find('all')
                            ->where(['email' => $user['email']])
                            ->first();
                    if ($result) {
                        $this->Auth->setUser($result->toArray());
                        $this->redirect($this->Auth->redirectUrl());
                    } else {

                        $data = array();
                        $data['email'] = $user['email'];
                        $data['first_name'] = $user['givenName'];
                        $data['last_name'] = $user['familyName'];
                        $data['socialId'] = $user['id'];
                        //$data matches my Users table

                        $entity = $this->Users->newEntity($data);
                        if ($this->Users->save($entity)) {
                            $data['id'] = $entity->id;
                            $this->Auth->setUser($data);
                            $this->redirect($this->Auth->redirectUrl());
                        } else {
                            $this->Flash->set('Logging error');
                            $this->redirect(['action' => 'login']);
                        }
                    }
                } else {
                    $this->Flash->set('Forbidden');
                    $this->redirect(['action' => 'login']);
                }
            } else {
                $this->Flash->set('Google infos not found');
                $this->redirect(['action' => 'login']);
            }
        } catch (\Exception $e) {
            $this->Flash->set('Google error');
            return $this->redirect(['action' => 'login']);
        }
    }
}

我还在文件中添加了以下行

paths.php

define('GOOGLE_OAUTH_CLIENT_ID', 'My_client_id');
define('GOOGLE_OAUTH_CLIENT_SECRET', 'My_client_secret');
define('GOOGLE_OAUTH_REDIRECT_URI', 'mylinkto/confirmLogin');

在Chrome的调试工具中,似乎调用了confimLogin(顺便说两次),并使用有效代码作为查询参数,然后调用googlelogin。所以我每次都会在日志页面上结束......

我觉得这里肯定有一些我想念的东西。有谁有想法吗? (谢谢!)

2 个答案:

答案 0 :(得分:0)

您应该在Auth组件中允许登录方法,以便不再将这些方法的操作重定向到googlelogin方法

$this->Auth->allow(['googlelogin','confirmLogin']);

答案 1 :(得分:0)

对您对我们文档的评论做出反应,我们添加了有关how to configure CakeDC/Users to use Google login in CakePHP的详细分步教程:

  1. 使用composer安装CakeDC用户插件和所需的oauth2提供程序
  2. 为了能够在Google仪表板中配置回调,您需要为您的应用程序创建虚拟主机。您不需要有效的域名,可以使用类似“mydomain.dev”的内容,但Google需要域名(无本地主机)。

    composer require cakedc/users:@stable 
    composer require league/oauth2-google:@stable
    
    1. 从bootstrap.php文件加载

      Plugin :: load('CakeDC / Users',['routes'=> true,'bootstrap'=> true]);

    2. 运行迁移以添加2个新表:'users'和'social_accounts'

    3. bin/cake migrations migrate -p CakeDC/Users
      1. 在src / Controller / AppController.php中加载Component

        public function initialize() {     父::初始化();     //     // ...     //     $这 - > loadComponent( 'CakeDC / Users.UsersAuth'); }

      2. 创建新的Google应用

      3. 获得客户端ID和客户端密钥字符串后,在/config/users.php下添加以下配置文件,并粘贴您的客户端ID和密码。在粘贴之前修剪代码中的任何空格。

        // /config/users.php文件内容 $ config = [     'Users.Social.login'=>真正,     'OAuth.providers.google.options.clientId'=> 'CLIENT_ID_HERE',     'OAuth.providers.google.options.clientSecret'=> 'SECRET_HERE', ];

        返回$ config;

      4. 修改bootstrap.php文件以确保以这种方式加载配置文件

        配置:: write('Users.config',['users']); //在插件:: load之前添加这一行('CakeDC / Users ... Plugin :: load('CakeDC / Users',['routes'=> true,'bootstrap'=> true]);

      5. 此文件将覆盖插件中存在的任何配置密钥,您可以在此处检查配置选项。

        完成!

        现在您已准备好进入登录页面并点击“使用Google注册”。