API / SPA

时间:2017-01-04 00:04:05

标签: laravel vue.js jwt csrf laravel-passport

我正在创建一个API和一个单独的前端应用程序,它将使用所述API。在我的特定情况下,我使用Laravel Passport作为我的API,并使用一些VueJS作为我的前端应用程序。

为了让用户创建帐户,用户必须POST到API上的路由(/oauth/token),这需要client_secret传递({{3} }})。

我看到的唯一选择是:

  1. client_secret作为我前端应用的标头发送。但是,将此令牌放在公开状态似乎并不聪明。
  2. 根本不需要client_secret。这似乎没有比选项1好多了。
  3. 在我的前端应用上有一个动态页面,可以安全地存储client_secret,然后将其发送到API。虽然这显然是最安全的,但它似乎部分地破坏了完全静态前端(SPA)的目的。
  4. 这种方法的最佳做法是什么?我已经搜索过如何通过API和SPA处理这个问题,但是我没有发现任何能指向正确方向的东西。

3 个答案:

答案 0 :(得分:5)

从我的角度来看,Laravel Passport组件似乎错误地实现了OAuth2框架协议。

client_idclient_secret参数不属于授权类型。 对于资源所有者密码凭据授予类型,所需参数为usernamepassword(请参阅RFC6749 section 4.3.2)。

client_idclient_secret用于验证通过正文参数发送其凭据的机密客户端(请参阅RFC6749 section 2.3.1)。 Laravel Passport组件应该允许其他客户端身份验证方案(尤其是HTTP基本身份验证方案)。 RFC6749也表明

  

使用两者在请求体中包含客户端凭据     不建议使用参数,并且应该仅限于无法使用的客户     直接使用HTTP基本身份验证方案

OpenID Connect Core规范列出了its section 9中的一些方案。 RFC6749未指示公共客户端(例如SPA)应如何针对令牌端点进行身份验证。它们应该使用不需要客户端身份验证的隐式授权类型。

无论如何,解决方案可能是使用一种代理。此代理必须安装在服务器上。它将接收来自SPA的所有请求(无客户机密),添加客户机密钥并将修改后的请求发送到Laravel Passport端点。然后将响应发送到SPA。这样SPA就不会暴露客户的秘密。

答案 1 :(得分:4)

我遇到了同样的问题,而且我没有找到关于这个问题的更多文档。

所以这就是我所做的,到目前为止似乎工作得很好,如果你看错了,你会告诉我。

对于我的应用,我将使用我为每个"客户端即时创建的密码授予客户端"我的应用程序客户端我的意思是浏览器,移动应用程序或任何东西。

每个浏览器在启动时检查他们是否有任何client_id和client_secret到localStorage(或cookie,或任何东西)。然后,如果他们没有,他们会调用API的端点,该端点将创建密码授予客户端并将信息返回给浏览器。

然后,浏览器将能够使用此新客户端信息及其凭据登录用户。

这是我用来创建密码授予客户端的控制器:

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Contracts\Hashing\Hasher;
use Illuminate\Http\Request;
use Laravel\Passport\ClientRepository;

class AuthController extends Controller
{
    protected $hasher;

    protected $clients;

    public function __construct (Hasher $hasher, ClientRepository $clients)
    {
        $this->hasher = $hasher;
        $this->clients = $clients;
    }

    public function makeClient (Request $request)
    {
        $client = $this->clients->create(null,$request->header('User-Agent','Unknown Device'), '', false, true);

        return $client->makeVisible('secret');
    }
}

如您所见,作为客户端的名称,我尝试存储浏览器的User-Agent。因此,我可以向所有客户显示一个页面给我的用户,并让他有权撤销一些客户:

&#34; Google Chrome,纽约&#34;。您还可以存储客户端IP或其中的任何内容,以帮助您更准确地识别设备的客户端类型...

答案 2 :(得分:-1)

更简单的方法是使用运行Passport的Laravel应用程序来处理用户注册(而不是通过API使用前端Vuejs应用程序)。
一旦用户注册并登录,您就可以使用Passport的CreateFreshApiToken中间件在加载前端应用程序时向用户的cookie添加令牌。 client_secret没有更多问题。

请参阅https://laravel.com/docs/5.3/passport#consuming-your-api-with-javascripthttps://mattstauffer.co/blog/introducing-laravel-passport#super-powered-access-to-the-api-for-frontend-views

同样oauth/token不会创建我相信的用户?它应该传递令牌(用于密码授予客户端)或授权代码(授权代码授权客户端)。

相关问题