mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-07-31 15:24:31 +03:00
Linked new API token system into middleware
Base logic in place but needs review and refactor to see if can better fit into Laravel using 'Guard' system. Currently has issues due to cookies in use from active session on API.
This commit is contained in:
78
app/Http/Middleware/ApiAuthenticate.php
Normal file
78
app/Http/Middleware/ApiAuthenticate.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Http\Middleware;
|
||||
|
||||
use BookStack\Api\ApiToken;
|
||||
use BookStack\Http\Request;
|
||||
use Closure;
|
||||
use Hash;
|
||||
|
||||
class ApiAuthenticate
|
||||
{
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
// TODO - Look to extract a lot of the logic here into a 'Guard'
|
||||
// Ideally would like to be able to request API via browser without having to boot
|
||||
// the session middleware (in Kernel).
|
||||
|
||||
// $sessionCookieName = config('session.cookie');
|
||||
// if ($request->cookies->has($sessionCookieName)) {
|
||||
// $sessionCookie = $request->cookies->get($sessionCookieName);
|
||||
// $sessionCookie = decrypt($sessionCookie, false);
|
||||
// dd($sessionCookie);
|
||||
// }
|
||||
|
||||
// Return if the user is already found to be signed in via session-based auth.
|
||||
// This is to make it easy to browser the API via browser after just logging into the system.
|
||||
if (signedInUser()) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
$authToken = trim($request->header('Authorization', ''));
|
||||
if (empty($authToken)) {
|
||||
return $this->unauthorisedResponse(trans('errors.api_no_authorization_found'));
|
||||
}
|
||||
|
||||
if (strpos($authToken, ':') === false || strpos($authToken, 'Token ') !== 0) {
|
||||
return $this->unauthorisedResponse(trans('errors.api_bad_authorization_format'));
|
||||
}
|
||||
|
||||
[$id, $secret] = explode(':', str_replace('Token ', '', $authToken));
|
||||
$token = ApiToken::query()
|
||||
->where('token_id', '=', $id)
|
||||
->with(['user'])->first();
|
||||
|
||||
if ($token === null) {
|
||||
return $this->unauthorisedResponse(trans('errors.api_user_token_not_found'));
|
||||
}
|
||||
|
||||
if (!Hash::check($secret, $token->secret)) {
|
||||
return $this->unauthorisedResponse(trans('errors.api_incorrect_token_secret'));
|
||||
}
|
||||
|
||||
if (!$token->user->can('access-api')) {
|
||||
return $this->unauthorisedResponse(trans('errors.api_user_no_api_permission'), 403);
|
||||
}
|
||||
|
||||
auth()->login($token->user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a standard API unauthorised response.
|
||||
*/
|
||||
protected function unauthorisedResponse(string $message, int $code = 401)
|
||||
{
|
||||
return response()->json([
|
||||
'error' => [
|
||||
'code' => $code,
|
||||
'message' => $message,
|
||||
]
|
||||
], 401);
|
||||
}
|
||||
}
|
@ -2,41 +2,16 @@
|
||||
|
||||
namespace BookStack\Http\Middleware;
|
||||
|
||||
use BookStack\Http\Request;
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
|
||||
class Authenticate
|
||||
{
|
||||
/**
|
||||
* The Guard implementation.
|
||||
* @var Guard
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
/**
|
||||
* Create a new filter instance.
|
||||
* @param Guard $auth
|
||||
*/
|
||||
public function __construct(Guard $auth)
|
||||
{
|
||||
$this->auth = $auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if ($this->auth->check()) {
|
||||
$requireConfirmation = (setting('registration-confirmation') || setting('registration-restrict'));
|
||||
if ($requireConfirmation && !$this->auth->user()->email_confirmed) {
|
||||
return redirect('/register/confirm/awaiting');
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAppAccess()) {
|
||||
if ($request->ajax()) {
|
||||
return response('Unauthorized.', 401);
|
||||
|
60
app/Http/Middleware/ConfirmEmails.php
Normal file
60
app/Http/Middleware/ConfirmEmails.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Http\Middleware;
|
||||
|
||||
use BookStack\Http\Request;
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
|
||||
/**
|
||||
* Confirms the current user's email address.
|
||||
* Must come after any middleware that may log users in.
|
||||
*/
|
||||
class ConfirmEmails
|
||||
{
|
||||
/**
|
||||
* The Guard implementation.
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
/**
|
||||
* Create a new ConfirmEmails instance.
|
||||
*/
|
||||
public function __construct(Guard $auth)
|
||||
{
|
||||
$this->auth = $auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if ($this->auth->check()) {
|
||||
$requireConfirmation = (setting('registration-confirmation') || setting('registration-restrict'));
|
||||
if ($requireConfirmation && !$this->auth->user()->email_confirmed) {
|
||||
return $this->errorResponse($request);
|
||||
}
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide an error response for when the current user's email is not confirmed
|
||||
* in a system which requires it.
|
||||
*/
|
||||
protected function errorResponse(Request $request)
|
||||
{
|
||||
if ($request->wantsJson()) {
|
||||
return response()->json([
|
||||
'error' => [
|
||||
'code' => 401,
|
||||
'message' => trans('errors.email_confirmation_awaiting')
|
||||
]
|
||||
], 401);
|
||||
}
|
||||
|
||||
return redirect('/register/confirm/awaiting');
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user