Реализация единого входа Laravel 8

#laravel #single-sign-on #laravel-8 #laravel-passport

Вопрос:

Я пытаюсь внедрить структуру единого входа:

  • основное приложение со всеми пользователями для управления входом в систему (sso-приложение)
  • несколько приложений, которые будут проходить аутентификацию в sso-приложении (app1, app2,…)

Мне удалось выполнить базовый вход в систему с помощью api sso-приложения, используя пакет Laravel Passport. Здесь контроллер app1 для процесса авторизации:

 class SSOController extends Controller
{

public function getLogin(Request $request){
    $request->session()->put("state", $state = Str::random(40));
    $query = http_build_query([
        'client_id' => env('SSO_CLIENT_ID'),
        'redirect_uri' => env('APP_URL') . '/auth/callback',
        'response_type' => 'code',
        'scope' => '',
        'state' => $state
    ]);

    return redirect(env('SSO_HOST') . '/oauth/authorize?' . $query);
}

public function getCallback(Request $request){
    $state = $request->session()->pull('state');

    throw_unless(strlen($state) > 0 amp;amp; $state == $request->state, 
        InvalidArgumentException::class
    );

    $response = Http::asForm()->post(
        env('SSO_HOST') . '/oauth/token',
        [
            'grant_type' => 'authorization_code',
            'client_id' => env('SSO_CLIENT_ID'),
            'client_secret' => env('SSO_SECRET'),
            'redirect_uri' => env('APP_URL') . '/auth/callback',
            'code' => $request->code
        ]
    );

    $request->session()->put($response->json());

    $token = $response->json()['access_token'];

    
    $jwtHeader = null;
    $jwtPayload = null;
    $parsed_token = parse_jwt($token);

    
    try{
        $email = $parsed_token->payload->user->email;
    }
    catch(Throwable $e){
        return redirect('login')->withError("Failed to get login information! Try again.");
    }
    
    $user = User::firstOrCreate(['email' => $email], array_merge((array)$parsed_token->payload->user, ['name' => ($parsed_token->payload->user->first_name." ".$parsed_token->payload->user->last_name)]));

    Auth::login($user);

    return redirect(route('home'));
    
}
}
 

Приложение 1 перенаправит на форму входа в sso-приложение, чем при успешном входе пользователя он перенаправит обратно в приложение 1.

Все работает как задумано, но как я могу использовать этот подход для авторизации маршрута api?

Это работает только для «веб -» охранника, потому что я создал локальную таблицу пользователей для каждого приложения и сделал вход в систему на основе сеанса, как вы можете видеть в конце SSOController.

Но как я могу использовать токен, возвращенный из sso-приложения, для аутентификации локального app1, app2, … api? Должен ли я создавать промежуточное программное обеспечение, которое вызывает sso-приложение каждый раз, когда я вызываю api app1, чтобы проверить, действителен ли токен, или есть лучший подход для экономии времени и увеличения скорости?

Спасибо.

Комментарии:

1. Получаете ли вы токен jwt от поставщика единого входа?

2. Да, он вернет токен jwt.

3. Чем использовать jwt auth с помощью tymondesigns/jwt-auth. Вы можете получить всю информацию о пользователе непосредственно из токена без вызовов S2S

4. Моя проблема не в том, чтобы получить информацию о пользователе, а в том, чтобы использовать выдачу токена сервером единого входа в моем клиентском приложении для аутентификации вызова api

5. Нет проблем, используйте эту библиотеку для проверки токена в клиентском приложении. Получите открытый ключ единого входа и подтвердите токен без вызова api.