2017-01-04 8 views
7

API 및 해당 API를 사용하는 별도의 프런트 엔드 앱을 만들고 있습니다. 필자의 경우 API API에는 Laravel Passport을, 프론트 엔드 앱에는 VueJS를 사용하고 있습니다. 계정을 만들 수있는 사용자에 대한 위해API/SPA에 대한 사용자 등록

, 전달하는 client_secret (https://laravel.com/docs/5.3/passport#password-grant-tokens)을 필요로하는 API에 대한 경로 (/oauth/token)에 대한 사용자해야 POST. 내가 볼

유일한 옵션은 다음과 같습니다

  1. client_secret 내 프론트 엔드 응용 프로그램에서 헤더로 전송 가졌어요. 그러나이 토큰을 열어 두는 것이 현명하지는 않습니다.
  2. client_secret을 전혀 필요로하지 마십시오. 이것은 옵션 1보다 훨씬 좋아 보이지 않습니다.
  3. 내 프런트 엔드 앱에 client_secret을 안전하게 저장할 수있는 동적 페이지를 만든 다음 API로 보냅니다. 이것은 분명히 가장 안전하지만 완전히 정적 인 프론트 엔드 (SPA)의 목적을 부분적으로 무효화하는 것 같습니다.

이러한 유형의 접근 방식에 가장 좋은 방법은 무엇입니까? API 및 SPA를 통해이 문제가 어떻게 다루어 지는지에 대해 조사했지만 올바른 방향으로 나를 가리키고있는 것을 발견하지 못했습니다.

+0

등록을 위해 CSRF 또는 기타 토큰 기반 보호가 중요하지 않다고 생각하기 시작했습니다. 사용자 등록은 공개 될 가능성이 있기 때문에 서버에서 유효성을 검사 한 클라이언트 측의 모든 보호는 그다지 효과적이지 않습니다. – tptcat

답변

4

나는 같은 문제를 겪었고,이 문제에 관해 더 많은 문서를 찾지 못했습니다.

내가 한 일은 여기까지입니다. 지금까지 멋진 일을하고있는 것 같아요, 당신이 틀린 것을 보게되면 저에게 말해 줄 수 있습니다.

내 앱의 경우, 내 앱의 각 '클라이언트'에 대해 즉석에서 만드는 비밀번호 부여 클라이언트를 사용하게됩니다. 고객이란 브라우저 나 모바일 앱 등을 의미합니다.

각 브라우저는 시작할 때 localStorage (또는 쿠키 등)에 client_id 및 client_secret이 있는지 확인합니다. 그런 다음, 그렇지 않으면 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'); 
    } 
} 

당신이 볼 수 있듯이 : 여기

내가 암호 부여 클라이언트를 만드는 데 사용하는 컨트롤러입니다. 따라서 모든 고객에게 내 고객에게 페이지를 표시 할 수 있으며 다음과 같은 일부 고객의 자격을 취소 할 수있는 권한을 부여 할 수 있습니다.

"Google Chrome, New York" 또한 클라이언트 IP를 저장하거나 장치의 클라이언트 유형을보다 정확하게 식별 할 수있는 항목을 저장할 수 있습니다.

+0

고맙습니다. @El_Matella. 재미있는 접근법. 지금까지 한 가지 질문을 던졌을 것입니다.이 접근 방식은 실제로 누군가가 등록/가입 URI에 대한 요청을보고 자유롭게 만들지 못하게합니다. 맞습니까? 내가 놓친 게 있니? – tptcat

+0

아니요. 누락 된 부분이 없습니다. 코드에서 일부 토큰을 숨기지 않고 리버스 엔지니어링 엔지니어가 해당 경로를 계속 사용할 수 없게하는 것을 방지하는 방법을 모르겠습니다. 그러나 좋은 보안 정책과 일부 요청 분석을 사용하면이 최종 트래픽과 맞설 수 있습니다. – Hammerbot

+0

확인. 이 페이지 중 하나에 대해 CSRF를 사용하는 기존의 서버 측 앱보다 훨씬 나쁜지 궁금합니다. 이론상 악의적 인 행위자는 해당 페이지를 크롤링하고 CSRF를 얻으며 원치 않는 요청을 백엔드에 제출할 수 있습니다. 이것에 대한 다른 사람들의 의견을 알고 싶습니다. – tptcat

5

Laravel Passport 구성 요소는 OAuth2 Framework Protocol을 잘못 구현 한 것으로 보입니다.

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는 고객의 비밀을 노출하지 않습니다.

+0

이 솔루션은 저의 관점에서 볼 때 가장 큰 것으로 보이지만 Laravel Passport에 문제를 만듭니다. 토큰의 revokation.클라이언트는 동일한 암호 부여 클라이언트를 사용하여 두 개의 다른 장치에서 동시에 로그인 할 수 없으므로 연결이 끊어집니다 (새 토큰을 만들 때 암호 부여 토큰이이 클라이언트와 사용자의 다른 모든 토큰을 취소 함) – Hammerbot

+1

권한 서 v가 새 액세스 토큰을 발행 했으므로 권한 서 v가 이전 액세스 토큰을 취소 할 이유는 없습니다. 이는 매우 나쁘고 바람직하지 않은 부작용입니다. 특히 [RFC7009] (https://tools.ietf.org/html/rfc7009)에서이를 다루고 토큰을 철회해야하는 시점을 클라이언트가 결정할 수 있기 때문에 바람직하지 않습니다. 그러나 [Passport source code] (https://github.com/laravel/passport/blob/0e8fe951996ed2a60b0b9a4012e21601a284f035/src/Passport.php#L24)를 볼 때 기본 동작은 기존 액세스 토큰을 유지하는 것입니다. 그 부작용을 해제하는 옵션을 사용할 수있는 것 같습니다 –

+1

호! 당신 말이 맞아요, 그들은 마지막 방문 때부터 코드를 바꿨습니다. 그들은 이것을 만들었습니다 : https://github.com/laravel/passport/commit/b95791d42f42d405ffacdf21007f80ef7798b164 그리고 나서 컨트롤러를 완전히 리팩토링하여 동료가 모든 작업을 수행하도록했습니다. 잘 했어! – Hammerbot

-1

더 간단한 방법은 여권 자체를 실행하는 Laravel 앱 (API를 통해 프론트 엔드 Vuejs 앱 사용 안함)으로 사용자 등록을 처리하는 것입니다.
사용자가 등록되고 로그인하면 Passport의 CreateFreshApiToken 미들웨어를 사용하여 프론트 엔드 응용 프로그램을로드하는 동안 사용자의 쿠키에 토큰을 추가 할 수 있습니다. client_secret에 더 이상 문제가 없습니다.

또한 oauth/token 내가 생각 사용자를 만들지 않습니다 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

를 참조하십시오? 토큰 (암호 부여 클라이언트 용) 또는 인증 코드 (인증 코드 부여 클라이언트)를 전달해야합니다.

+0

이 특정 사례의 경우 프론트 엔드 앱은 API와 별개의 앱이므로이 유스 케이스는 여기에 적용되지 않습니다. – tptcat