dingo / dingo/api

[proposal] Retrieve user and don't throw middleware.

Open
#1,313 1 comment 0 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.