1
0
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:
Dan Brown
2019-12-30 02:16:07 +00:00
parent 2cfa37399c
commit 3de55ee645
7 changed files with 183 additions and 37 deletions

View 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);
}
}

View File

@ -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);

View 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');
}
}