微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Firebase Auth JS / PHP

我的任务是为基于firebase的Android应用构建一个Web界面.
我有一些与数据库交互的端点(云功能).要访问这些端点,我需要使用电子邮件密码[1]对用户进行身份验证,检索accesstoken [2]并使用Authorization:Bearer {accesstoken}标头授权对端点的每个请求.

我使用PHP并努力思考如何在我的应用程序中管理经过身份验证的用户.

TL; DR请在PHP中查看我的最终解决方案. https://stackoverflow.com/a/52119600/814031

我在PHP会话中通过ajax传输accesstoken,以便向端点签署cURL请求.
显然没有其他方法可以使用firebase JS auth(据我所知[4]而言).

我的问题是:是否足以在PHP会话中保存accesstoken并通过ajax POST请求将其与每个页面加载进行比较(参见下面的代码)?
PHP中处理这个问题会有什么更强大的策略?

编辑:A user pointed out使用经典的PHP会话与JWT令牌没有多大意义,我读了有关该主题.
关于Firebase – 这是需要考虑的事情吗?
https://firebase.google.com/docs/auth/admin/manage-cookies

Firebase Auth provides server-side session cookie management for Traditional websites that rely on session cookies. This solution has several advantages over client-side short-lived ID tokens, which may require a redirect mechanism each time to update the session cookie on expiration:

这是我得到的:

1.登录页面

如Firebase示例[3]中所述

function initApp() {

  firebase.auth().onAuthStateChanged(function (user) {
    if (user) {
      // User is signed in.

      // obtain token, getIdToken(false) = no forced refresh
      firebase.auth().currentUser.getIdToken(false).then(function (idToken) {

        // Send token to your backend via HTTPS
        $.ajax({
          type: 'POST',
          url: '/auth/check',
          data: {'token': idToken},
          complete: function(data){
            // data = {'target' => '/redirect/to/route'}
            if(getProperty(data, 'responseJSON.target', false)){
              window.location.replace(getProperty(data, 'responseJSON.target'));
            }
          }
        });
        // ...
      }).catch(function (error) {
        console.log(error);
      });


    } else {
      // User Signed out
      $.ajax({
        type: 'POST',
        url: '/auth/logout',

        complete: function(data){
          // data = {'target' => '/redirect/to/route'}
          if(getProperty(data, 'responseJSON.target', false)){
            // don't redirect to itself
            // logout => /
            if(window.location.pathname != getProperty(data, 'responseJSON.target', false)){
              window.location.replace(getProperty(data, 'responseJSON.target'));
            }
          }
        }
      });

      // User is signed out.
    }

  });
}

window.onload = function () {
  initApp();
};

2.一个PHP控制器来处理auth请求

public function auth($action)
{

  switch($action) {
    // auth/logout
    case 'logout':

      unset($_SESSION);
      // some http status header and mime type header
      echo json_encode(['target' => '/']); // / => index page
    break;

    case 'check':

      // login.
      if(! empty($_POST['token']) && empty($_SESSION['token'])){

        // What if I send some bogus data here? The call to the Endpoint later would fail anyway
        // But should it get so far?

        $_SESSION['token'] = $_POST['token'];

        // send a redirect target back to the JS
        echo json_encode(['target' => '/dashboard']);
        break;
      }


      if($_POST['token'] == $_SESSION['token']){
        // do nothing;
        break;
      }
    break;
  }
}

3.主控制器

// pseudo code
class App
{
  public function __construct()
  {
    if($_SESSION['token']){
      $client = new \GuzzleHttp\Client();
      // $user Now holds all custom access rights within the app.
      $this->user = $client->request(
        'GET', 
        'https://us-centralx-xyz.cloudfunctions.net/user_endpoint',
        ['headers' => 
                [
                    'Authorization' => "Bearer {$_SESSION['token']}"
                ]
            ]
        )->getBody()->getContents();
    }else{
      $this->user = null;
    }
  }

  public function dashboard(){
    if($this->user){
      var_dump($this->user);
    }else{
      unset($_SESSION);
      // redirect to '/' 
    }
  }
}

注意:我知道这个sdk https://github.com/kreait/firebase-php并且我在那里的问题和SO上的帖子中阅读了很多,但我感到困惑,因为有关于完全管理权限等的讨论,我真的只与端点交互构建在firebase上(加上firebase auth和firestore).我还在使用PHP 5.6: – /

谢谢你的时间!

> [1]:https://firebase.google.com/docs/auth/web/password-auth
> [2]:https://firebase.google.com/docs/reference/js/firebase.User#getIdToken
> [3]:https://github.com/firebase/quickstart-js/blob/master/auth/email-password.html
> [4]:https://github.com/kreait/firebase-php/issues/159#issuecomment-360225655

解决方法:

我必须承认,firebase文档和示例以及不同服务的复杂性使我感到困惑,我认为,只有通过JavaScript才能对Web进行身份验证.那是错的.至少在我的情况下,我只需使用电子邮件密码登录来检索Json Web令牌(JWT),就可以签署所有对Firebase云功能调用.而不是通过JavaScript处理奇怪的Ajax请求或设置令牌cookie,我只需要调用Firebase Auth REST API

以下是使用Fatfreeframework的最小案例:

登录表格

<form action="/auth" method="post">
    <input name="email">
    <input name="password">
    <input type="submit">
</form>

路线

$f3->route('POST /auth', 'App->auth');

调节器

class App
{
    function auth()
    {
        $email = $this->f3->get('POST.email');
        $password = $this->f3->get('POST.password');

        $apiKey = 'API_KEY'; // see https://firebase.google.com/docs/web/setup

        $auth = new Auth($apiKey);
        $result = $auth->login($email,$password);

        if($result['success']){
            $this->f3->set('COOKIE.token',$result['idToken']);
            $this->f3->reroute('/dashboard');
        }else{
            $this->f3->clear('COOKIE.token');
            $this->f3->reroute('/');
        }
    }
}

<?PHP
use GuzzleHttp\Client;

class Auth
{

    protected $apiKey;

    public function __construct($apiKey){
        $this->apiKey = $apiKey;
    }

    public function login($email,$password)
    {

        $client = new Client();
        // Create a POST request using Google Api
        $key = $this->apiKey;
        $responsee = $client->request(
            'POST',
            'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=' . $key,
            [
                'headers' => [
                    'content-type' => 'application/json',
                    'Accept' => 'application/json'
                ],
                'body' => json_encode([
                    'email' => $email,
                    'password' => $password,
                    'returnSecuretoken' => true
                ]),
                'exceptions' => false
            ]
        );

        $body = $responsee->getBody();
        $js = json_decode($body);

        if (isset($js->error)) {
            return [
                'success' => false,
                'message' => $js->error->message
            ];
        } else {
            return [
                'success' => true,
                'localId' => $js->localId,
                'idToken' => $js->idToken,
                'email' => $js->email,
                'refreshToken' => $js->refreshToken,
                'expiresIn' => $js->expiresIn,
            ];

        }

    }

}

Credits

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐