Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sharing same route with unauthenticated and authenticated users in Laravel 5.3

I have a route that where I'm using an auth middleware and it works great.

Route::group(['prefix' => 'v1','middleware' => ['auth:api']], function()
{
  Route::resource('user', 'v1\MyController');
});

The problem is that I would also like this route to be accessible to non-authenticated users as well. With the above, I get a 401 Unauthorized error and I can't return any content for unauthenticated users. So how can I authenticate this route (so it passes down the user data) while also allowing the route to proceed even if the user is NOT authenticated?

(I tried doing a conditional Auth check on the router page but it seems the user has gone through authentication yet so it always remains false.)

EDIT: I should also note that I'm using an API route with Password Grant & access tokens.

like image 629
Andrew Avatar asked Sep 20 '16 11:09

Andrew


3 Answers

remove this route from current route group (which applies auth middleware).

then

public function __construct()
{
    if (array_key_exists('HTTP_AUTHORIZATION', $_SERVER)) {
        $this->middleware('auth:api');
    }
}

then

if (Auth::check()) {
    // Auth users
} else{ 
    //Guest users 
}
like image 122
Yves Avatar answered Oct 20 '22 20:10

Yves


I am experiencing the same case.

since the auth middleware only checks for authenticated user, we can use client credentials for the non-authenticated user.

the client credentials have a separated middleware located in Laravel\Passport\Http\Middleware\CheckClientCredentails.

I have created a custom middleware to combine both middleware to allow either one is pass.

here is my custom middleware

namespace Laravel\Passport\Http\Middleware;

use Closure;
use League\OAuth2\Server\ResourceServer;
use Illuminate\Auth\AuthenticationException;
use League\OAuth2\Server\Exception\OAuthServerException;
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;

class CheckClientCredentials
{
    /**
     * The Resource Server instance.
     *
     * @var ResourceServer
     */
    private $server;

    /**
     * Create a new middleware instance.
     *
     * @param  ResourceServer  $server
     * @return void
     */
    public function __construct(ResourceServer $server)
    {
        $this->server = $server;
    }

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @return mixed
     *
     * @throws \Illuminate\Auth\AuthenticationException
     */
    public function handle($request, Closure $next, ...$scopes)
    {
        $psr = (new DiactorosFactory)->createRequest($request);

        try{
            $psr = $this->server->validateAuthenticatedRequest($psr);
        } catch (OAuthServerException $e) {
            throw new AuthenticationException;
        }

        foreach ($scopes as $scope) {
           if (!in_array($scope,$psr->getAttribute('oauth_scopes'))) {
             throw new AuthenticationException;
           }
         }

        return $next($request);
    }
}

Kernal.php

protected $routeMiddleware = [
    'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
    'auth.api' => \App\Http\Middleware\APIAuthenticate::class,
    ....

routes\api.php

Route::group([
    'namespace' => 'API',
    'middleware' => 'auth.api:api',
], function(){
    ....
like image 31
Joel Chan Avatar answered Oct 20 '22 19:10

Joel Chan


From within an unauthenticated (not assigned the auth:api middleware) route's handler method, try:

Auth::guard("api")->user();

If it's populated, then your unguarded route can treat the access as authenticated. If not, its a random user accessing the route, and can be treated as such.

like image 33
Rimer Avatar answered Oct 20 '22 20:10

Rimer