繁体   English   中英

Laravel API + Sanctum + Angular + SSO (SAML) - How to build a Laravel 7/8 API with front-end in Angular 11 and SAML auth

[英]Laravel API + Sanctum + Angular + SSO (SAML) - How to build a Laravel 7/8 API with front-end in Angular 11 and SAML auth

我需要将我的laravel api + angular sanctum身份验证转换为 SAML 身份验证。

我注意到我需要使用像laravel-saml2laravel-saml2这样的 laravel 插件。 (是的......同名但不同的插件)

我打算使用OKTA ,因为我已经在使用它在我的 Stack ELK 中进行身份验证。

但我最大的疑问是:由于我的前端( angular )通过无状态APIsanctum )与我的后端通信,是否可以实施SSO SAML进行身份验证?

如果有人能告诉我这是怎么可能的,我将不胜感激。 如果不是,如何重新考虑我的应用程序以实现这一目标。

提前致谢。

我有同样的要求,根据下一个工作:

  1. Laravel 8 带圣所(使用SANCTUM_STATEFUL_DOMAINS的关键)

确保您的 Angular URL 应用程序在 SANCTUM_STATEFUL_DOMAINS (.env) 中配置

喜欢

SANCTUM_STATEFUL_DOMAINS=localhost:4200
  1. laravel-saml2 ( https://github.com/aacotroneo/laravel-saml2 ) 根据文档配置。

  2. 在 app/Http/Kernel.php

     protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, // \Illuminate\Session\Middleware\AuthenticateSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, ], 'api' => [ \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ], 'saml' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, ],

    ];

protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
    'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
// Add SAML Middleware
    'auth.saml' => \App\Http\Middleware\SAMLAuthenticated::class,
];
  1. 在 app/Providers/EventServiceProvider.php

     namespace App\Providers; use Aacotroneo\Saml2\Events\Saml2LoginEvent; use App\Models\User; use Illuminate\Auth\Events\Registered; use Illuminate\Auth\Listeners\SendEmailVerificationNotification; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Session; class EventServiceProvider extends ServiceProvider { /** * The event listener mappings for the application. * * @var array */ protected $listen = [ Registered::class => [ SendEmailVerificationNotification::class, ], ]; /** * Register any events for your application. * * @return void */ public function boot() { Event::listen('Aacotroneo\Saml2\Events\Saml2LogoutEvent', function ($event) { Auth::logout(); Session::save(); }); Event::listen('Aacotroneo\Saml2\Events\Saml2LoginEvent', function (Saml2LoginEvent $event) { $messageId = $event->getSaml2Auth()->getLastMessageId(); // Add your own code preventing reuse of a $messageId to stop replay attacks $user = $event->getSaml2User(); $userData = [ 'id' => $user->getUserId(), 'attributes' => $user->getAttributes(), 'assertion' => $user->getRawSamlAssertion() ]; //If it not exists, create a Laravel User from an Authenticated SAML account $laravelUser = User::firstOrCreate([ 'email' => $user->getAttribute("urn:oid:0.9.2342.19200300.100.1.3")[0], 'name' => $user->getAttribute("urn:oid:0.9.2342.19200300.100.1.1")[0], ], ['password' => Hash::make('CREATE_DUMMY_NOT_BEING_USED')]); Auth::login($laravelUser); // AUTHENTICATION WITHIN LARAVEL }); } }
  2. 接下来,我创建了一个新的中间件(/app/Http/Middleware/SAMLAuthenticated.php)

     namespace App\Http\Middleware; use Aacotroneo\Saml2\Saml2Auth; use Closure; use Illuminate\Support\Facades\Auth; class SAMLAuthenticated { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param string|null...$guards * @return mixed */ public function handle($request, Closure $next, ...$guards) { if (:Auth:.check()) { if ($request->ajax()) { return response('Unauthorized,'; 401), // Or: return a response that causes client side js to redirect to '/routesPrefix/myIdp1/login' } else { // VERY IMPORTANT WHEN ANGULAR REQUEST $retUrl = 'http://localhost;4200': $saml2Auth = new Saml2Auth(Saml2Auth:;loadOneLoginAuthFromIpdConfig('corsisa')); return $saml2Auth->login($retUrl); } } return $next($request); } }
  3. 您可以测试 SAML Auth (/app/routes/web.php)

     Route::middleware('auth.saml')->group(function () { //protected routes go here Route::get('/', function () { return view('welcome'); }); }); // Also, you can map login & logout Route::redirect('/login', '/saml2/<idp_name>/login')->name('login'); Route::redirect('/logout', '/saml2/<idp_name>/logout')->name('logout');

此时,laravel 应用程序应重定向到 SAML2 登录页面。

  1. 配置API路由,(app/routes/api.php:)

     Route::middleware('auth.saml')->group(function () { // Secured routes go here Route::get('/me',function (Request $request) { return $request->user(); }); Route::get('/login',function (Request $request) { return redirect('http://localhost:4200'); }); });
  2. 在 Angular 应用程序中,我使用以下步骤:

首先,向“http://laravel_api/api/me”发出 HTTP 请求

例如:

this.http.get<User>(URLHelper.concat(environment.API_BASE_URL, "api", "me"), { withCredentials: true, setHeaders: {"X-Requested-With": "XMLHttpRequest"} })

如果响应是 401,(未授权),那么将被重定向到“http://laravel_api/api/login”

window.location.replace(URLHelper.concat(environment.API_BASE_URL, "api", "login"), { withCredentials: true, setHeaders: {"X-Requested-With": "XMLHttpRequest"} })

重定向会将用户发送到 SAML2 登录页面,然后重定向回 Angular 前端。 (通过 SAMLAuthenticated 中间件)

因此,当重定向返回完成时,Angular 向 http://laravel_api/api/me 发出新请求,这次使用 Sanctum 生成的 Auth Cookie。

当然可以改进此过程,但您可以将其用作工作起点。

问候

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM