[proposal] Retrieve user and don't throw middleware.
- Dominant language
- PHP
- Stars
- 9.4k
- Forks
- 1.3k
- PR merge metrics
- No merged PRs in 30d
Description
There are occasions when users of this package will want routes/endpoints that need to run the `api.auth` middleware in a conditional manner that does not throw any HTTP exceptions when a user cannot be retrieved.
For example, lets say we have an endpoint `/post/{postId}` that has an ACL that allows non-authenticated users to view visible posts `{ status: 'PUBLISHED' }` and denies access to posts that are not visible `{ status: 'DRAFT' }`.
In the ACL, controller, form request or Policy class we would want to access a user `$request->user()` although this will only be present in some cases. If we run the endpoint through the `api.auth` middleware it throws auth exceptions when a user cannot be retrieved from any of the auth drivers.
We have written a simple middleware `AttemptAuth` that we hook into the kernel with a `api.auth.attempt` key:
````php
*/
class AttemptAuth
{
/**
* Router instance.
*
* @var \Dingo\Api\Routing\Router
*/
protected $router;
/**
* Authenticator instance.
*
* @var \Dingo\Api\Auth\Auth
*/
protected $auth;
/**
* Create a new auth middleware instance.
*
* @param \Dingo\Api\Routing\Router $router
* @param \Dingo\Api\Auth\Auth $auth
*/
public function __construct(Router $router, Authentication $auth)
{
$this->router = $router;
$this->auth = $auth;
}
/**
* Attempt to retrieve user
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @return mixed
*/
public function handle($request, Closure $next)
{
$route = $this->router->getCurrentRoute();
if (! $this->auth->check(false)) {
try {
$this->auth->authenticate($route->getAuthenticationProviders());
} catch (UnauthorizedHttpException $exception) {
// do nothing
} catch (BadRequestHttpException $exception) {
// do nothing
}
}
return $next($request);
}
}
````
Now from a request we can do the following:
````php
$isAuthenticated = $request->user() ?? false;
````
Or even build some form of conditional ACL:
````php
// PostPolicy.php
public function canViewPost(Post $post, User $user = null)
{
if ($post->status === 'PUBLISHED') {
return true;
}
if ($user && $user->canEditPosts()) {
return true;
}
return false;
}
````
Contributor guide
Assessment
This issue has not been assessed yet.