This commit is contained in:
TiclemFR
2023-12-29 16:00:02 +01:00
parent 9d79d7c0c6
commit 884eb3011a
8361 changed files with 1160554 additions and 4 deletions

View File

@@ -0,0 +1,90 @@
<?php
namespace Laravel\Sanctum\Http\Middleware;
use Closure;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Auth\SessionGuard;
use Illuminate\Contracts\Auth\Factory as AuthFactory;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Symfony\Component\HttpFoundation\Response;
class AuthenticateSession
{
/**
* The authentication factory implementation.
*
* @var \Illuminate\Contracts\Auth\Factory
*/
protected $auth;
/**
* Create a new middleware instance.
*
* @param \Illuminate\Contracts\Auth\Factory $auth
* @return void
*/
public function __construct(AuthFactory $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*
* @throws \Illuminate\Auth\AuthenticationException
*/
public function handle(Request $request, Closure $next): Response
{
if (! $request->hasSession() || ! $request->user()) {
return $next($request);
}
$guards = Collection::make(Arr::wrap(config('sanctum.guard')))
->mapWithKeys(fn ($guard) => [$guard => $this->auth->guard($guard)])
->filter(fn ($guard) => $guard instanceof SessionGuard);
$shouldLogout = $guards->filter(
fn ($guard, $driver) => $request->session()->has('password_hash_'.$driver)
)->filter(
fn ($guard, $driver) => $request->session()->get('password_hash_'.$driver) !==
$request->user()->getAuthPassword()
);
if ($shouldLogout->isNotEmpty()) {
$shouldLogout->each->logoutCurrentDevice();
$request->session()->flush();
throw new AuthenticationException('Unauthenticated.', [...$shouldLogout->keys()->all(), 'sanctum']);
}
return tap($next($request), function () use ($request, $guards) {
if (! is_null($request->user())) {
$this->storePasswordHashInSession($request, $guards->keys()->first());
}
});
}
/**
* Store the user's current password hash in the session.
*
* @param \Illuminate\Http\Request $request
* @param string $guard
* @return void
*/
protected function storePasswordHashInSession($request, string $guard)
{
if (! $request->user()) {
return;
}
$request->session()->put([
"password_hash_{$guard}" => $request->user()->getAuthPassword(),
]);
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace Laravel\Sanctum\Http\Middleware;
use Illuminate\Auth\AuthenticationException;
use Laravel\Sanctum\Exceptions\MissingAbilityException;
class CheckAbilities
{
/**
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param mixed ...$abilities
* @return \Illuminate\Http\Response
*
* @throws \Illuminate\Auth\AuthenticationException|\Laravel\Sanctum\Exceptions\MissingAbilityException
*/
public function handle($request, $next, ...$abilities)
{
if (! $request->user() || ! $request->user()->currentAccessToken()) {
throw new AuthenticationException;
}
foreach ($abilities as $ability) {
if (! $request->user()->tokenCan($ability)) {
throw new MissingAbilityException($ability);
}
}
return $next($request);
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace Laravel\Sanctum\Http\Middleware;
use Illuminate\Auth\AuthenticationException;
use Laravel\Sanctum\Exceptions\MissingAbilityException;
class CheckForAnyAbility
{
/**
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param mixed ...$abilities
* @return \Illuminate\Http\Response
*
* @throws \Illuminate\Auth\AuthenticationException|\Laravel\Sanctum\Exceptions\MissingAbilityException
*/
public function handle($request, $next, ...$abilities)
{
if (! $request->user() || ! $request->user()->currentAccessToken()) {
throw new AuthenticationException;
}
foreach ($abilities as $ability) {
if ($request->user()->tokenCan($ability)) {
return $next($request);
}
}
throw new MissingAbilityException($abilities);
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace Laravel\Sanctum\Http\Middleware;
use Laravel\Sanctum\Exceptions\MissingScopeException;
/**
* @deprecated
* @see \Laravel\Sanctum\Http\Middleware\CheckForAnyAbility
*/
class CheckForAnyScope
{
/**
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param mixed ...$scopes
* @return \Illuminate\Http\Response
*
* @throws \Illuminate\Auth\AuthenticationException|\Laravel\Sanctum\Exceptions\MissingScopeException
*/
public function handle($request, $next, ...$scopes)
{
try {
return (new CheckForAnyAbility())->handle($request, $next, ...$scopes);
} catch (\Laravel\Sanctum\Exceptions\MissingAbilityException $e) {
throw new MissingScopeException($e->abilities());
}
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace Laravel\Sanctum\Http\Middleware;
use Laravel\Sanctum\Exceptions\MissingScopeException;
/**
* @deprecated
* @see \Laravel\Sanctum\Http\Middleware\CheckAbilities
*/
class CheckScopes
{
/**
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param mixed ...$scopes
* @return \Illuminate\Http\Response
*
* @throws \Illuminate\Auth\AuthenticationException|\Laravel\Sanctum\Exceptions\MissingScopeException
*/
public function handle($request, $next, ...$scopes)
{
try {
return (new CheckAbilities())->handle($request, $next, ...$scopes);
} catch (\Laravel\Sanctum\Exceptions\MissingAbilityException $e) {
throw new MissingScopeException($e->abilities());
}
}
}

View File

@@ -0,0 +1,91 @@
<?php
namespace Laravel\Sanctum\Http\Middleware;
use Illuminate\Routing\Pipeline;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
class EnsureFrontendRequestsAreStateful
{
/**
* Handle the incoming requests.
*
* @param \Illuminate\Http\Request $request
* @param callable $next
* @return \Illuminate\Http\Response
*/
public function handle($request, $next)
{
$this->configureSecureCookieSessions();
return (new Pipeline(app()))->send($request)->through(
static::fromFrontend($request) ? $this->frontendMiddleware() : []
)->then(function ($request) use ($next) {
return $next($request);
});
}
/**
* Configure secure cookie sessions.
*
* @return void
*/
protected function configureSecureCookieSessions()
{
config([
'session.http_only' => true,
'session.same_site' => 'lax',
]);
}
/**
* Get the middleware that should be applied to requests from the "frontend".
*
* @return array
*/
protected function frontendMiddleware()
{
$middleware = array_values(array_filter(array_unique([
config('sanctum.middleware.encrypt_cookies', \Illuminate\Cookie\Middleware\EncryptCookies::class),
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
config('sanctum.middleware.validate_csrf_token'),
config('sanctum.middleware.verify_csrf_token', \Illuminate\Foundation\Http\Middleware\VerifyCsrfToken::class),
config('sanctum.middleware.authenticate_session'),
])));
array_unshift($middleware, function ($request, $next) {
$request->attributes->set('sanctum', true);
return $next($request);
});
return $middleware;
}
/**
* Determine if the given request is from the first-party application frontend.
*
* @param \Illuminate\Http\Request $request
* @return bool
*/
public static function fromFrontend($request)
{
$domain = $request->headers->get('referer') ?: $request->headers->get('origin');
if (is_null($domain)) {
return false;
}
$domain = Str::replaceFirst('https://', '', $domain);
$domain = Str::replaceFirst('http://', '', $domain);
$domain = Str::endsWith($domain, '/') ? $domain : "{$domain}/";
$stateful = array_filter(config('sanctum.stateful', []));
return Str::is(Collection::make($stateful)->map(function ($uri) {
return trim($uri).'/*';
})->all(), $domain);
}
}