#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.