Войдите на сторонний сайт, используя Laravel Паспорт - PullRequest
1 голос
/ 17 февраля 2020

Мне нужно решить следующую проблему: я создал два приложения, используя Laravel.

  • Приложение A может быть достигнуто через https://test.example.org и предоставляет экземпляр паспорта и все пользовательские данные (модель: User).
  • Приложение B может быть достигнуто через https://test.org и использует API Приложение A обеспечивает использование "API-пользователя", существующего в Приложение A для извлечения данных "publi c"

Теперь я хотел бы предоставить метод входа для пользователей Приложение B . Все пользователи, которые используют Приложение B , существуют в Приложение A . Таким образом, пользователь, выполняющий вход в Приложение B , использует учетные данные, сохраненные в Приложение A . Все изменения, внесенные пользователю в приложении A , должны быть видны в приложении B .

Теперь мне интересно, как я мог это сделать. Есть идеи, как это решить? Я могу представить себе использование API-вызовов с

        $client = $this->client;
        try {
            return $client->request('POST',
                'https://'.config('server').'/oauth/token', [
                    'headers'     => [
                        'cache-control' => 'no-cache',
                        'Content-Type'  => 'application/x-www-form-urlencoded',
                    ],
                    'form_params' => [
                        'client_id'     => ...,
                        'client_secret' => ...,
                        'grant_type'    => 'password',
                        'username'      => $users-username,
                        'password'      => $users-password,
                    ],
                ]);
        } catch (BadResponseException $e) {
            return $e->getResponse();
        }
    }

, но я не понимаю, нужно ли мне создавать client_id и client_secret для каждого пользователя в приложении A . Если это так, мне нужно где-то хранить эту информацию, чтобы в конечном итоге я создал модель User для приложения B .

Мои вопросы:

  • Как войти в систему пользователей, которые существуют в Приложение A до Приложение B наиболее элегантным способом?
  • Это опция использовать Laravel / Socialite со стороны клиента ( Приложение B )?

Ответы [ 3 ]

3 голосов
/ 09 марта 2020

Самый элегантный способ - использовать Laravel Socialite в приложении B для работы в качестве клиента OAuth для приложения A , действующего как сервер OAuth (с использованием Laravel Паспорт).

  1. Вкл. Приложение A , вам необходимо создать клиент в Паспорте для вашего Приложения B :
php artisan passport:client --password

Сначала вас спросят Which user ID should the client be assigned to?. Нажмите ввод, поскольку вы не хотите ограничивать клиента определенным c пользователем.

Затем вам будет предложено указать имя вашего клиента, вам следует ввести что-то вроде Application B.

Наконец, вас попросят указать URL-адрес перенаправления вашего клиента. Вы должны ввести https://test.org/oauth/callback, то есть URL-адрес, который Socialite будет использовать для перенаправления пользователей после их аутентификации.

Если вам нужно проверить это на своем компьютере, введите свой локальный домен, например, https://application-b.test/oauth/callback .

После того, как клиент будет создан, держите в секрете идентификатор клиента и клиента, так как они понадобятся вам позже.

Вам также понадобится конечная точка API для предоставления подробностей для аутентифицированного пользователя,. например, https://test.example.org/user.

Вкл. Приложение B , после установки Laravel Socialite необходимо установить учетные данные для Приложения A в файле конфигурации services.php. Например:
'passport' => [
    'client_id' => env('PASSPORT_CLIENT_ID'),
    'client_secret' => env('PASSPORT_CLIENT_SECRET'),
    'redirect' => 'oauth/callback',
],

В своем файле .env укажите идентификатор клиента и секретный ключ для клиента Passport, который вы создали в Приложении A :

PASSPORT_CLIENT_ID=...
PASSPORT_CLIENT_SECRET=...
Теперь вам нужно расширить Socialite с помощью специального провайдера для Application A.

Создать класс PassportProvider в каталоге app/Socialite (или в любом месте внутри app, если хотите) .

<?php

namespace App\Socialite;

use Laravel\Socialite\Two\AbstractProvider;
use Laravel\Socialite\Two\ProviderInterface;
use Laravel\Socialite\Two\User;
use Illuminate\Support\Arr;

class PassportProvider extends AbstractProvider implements ProviderInterface
{
    /**
     * {@inheritdoc}
     */
    protected function getAuthUrl($state)
    {
        return $this->buildAuthUrlFromBase('https://test.example.org/oauth/authorize', $state);
    }

    /**
     * {@inheritdoc}
     */
    protected function getTokenUrl()
    {
        return 'https://test.example.org/oauth/token';
    }

    /**
     * {@inheritdoc}
     */
    protected function getUserByToken($token)
    {
        $response = $this->getHttpClient()->get(
            'https://test.example.org/user',
            $this->getRequestOptions($token)
        );

        return json_decode($response->getBody(), true);
    }

    /**
     * {@inheritdoc}
     */
    protected function mapUserToObject(array $user)
    {
        return (new User)->setRaw($user)->map([
            'id' => $user['id'],
            'name' => Arr::get($user, 'name'),
            'email' => Arr::get($user, 'email'),
        ]);
    }

    /**
     * Get the default options for an HTTP request.
     *
     * @param string $token
     * @return array
     */
    protected function getRequestOptions($token)
    {
        return [
            'headers' => [
                'Accept' => 'application/json',
                'Authorization' => 'token '.$token,
            ],
        ];
    }
}

Далее, в вашем ApplicationServiceProvider (или в отдельном поставщике услуг) добавьте следующее:

use App\Socialite\PassportProvider;
use Illuminate\Support\Facades\URL;
use Laravel\Socialite\Facades\Socialite;

public function boot()
{
    Socialite::extend('passport', function (function ($app) {
        $config = $app['config']['services.passport'];

        return new PassportProvider(
            $app['request'],
            $config['client_id'],
            $config['client_secret'],
            URL::to($config['redirect'])
        );
    });
}

Теперь вы готовы использовать своего собственного поставщика Socialite в ваш контроллер входа в вашем клиентском приложении:

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Laravel\Socialite\Facades\Socialite;

class LoginController extends Controller
{
    /**
     * Redirect the user to the GitHub authentication page.
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function redirectToProvider()
    {
        return Socialite::driver('passport')->redirect();
    }

    /**
     * Obtain the user information from GitHub.
     *
     * @return \Illuminate\Http\Response
     */
    public function handleProviderCallback()
    {
        $user = Socialite::driver('passport')->user();
    }
}

Не забудьте зарегистрировать маршруты входа в ваш routes/web.php файл:

Route::get('oauth/redirect', 'Auth\LoginController@redirectToProvider');
Route::get('oauth/callback', 'Auth\LoginController@handleProviderCallback');
0 голосов
/ 09 марта 2020

есть два решения

1. Если вам просто нужно Детали базы данных приложения A , чем создать несколько соединений с базой данных в вашем приложении B

https://fideloper.com/laravel-multiple-database-connections

2. Если вы хотите получить доступ к конечной точке приложения A , чем сохранить то же хранилище файлов / oauth -publi c .key, storage / oauth-private.key для обоих приложений, поэтому Приложение A может легко аутентифицировать Приложение B токен авторизации.

0 голосов
/ 05 марта 2020

A. Вы должны создать только один client_id и client_secret для приложения B Б. Используйте паспорт, как вы написали выше C. Вы можете, но вам нужно настроить его вручную, но я не уверен, что это хорошая идея, лучше было бы перенаправить его в интерфейс приложения A (в случае веб-интерфейса) или напрямую связаться с приложением A (в случае мобильного). ) и пусть он справится сам.

...