depsimon's avatar

Passing parameters from Middleware to Controller

Hello everyone,

With my Lumen API, consumers can authenticate providing their API key and user credentials. I provide them an access_token (associated with the consumer and the user).

The thing is that some of my routes should be publicly accessible, some others should be private but some can be both.

In a classic flow I'd use a route middleware to protect my private routes but in my case the routes and the controllers are the same independantly from the authentication. I'd just like something to check if the query is given a valid access token and maybe use something like this in my controllers :

public function index(Request $request, $book_id)
{
    // $this->consumer would be defined by a middleware ?
    if (! $this->consumer) {
        // Public call, just return the books
        return response()->json(Book::all());
    } elseif ($this->consumer->level == 1) {
        // Authenticated call, but low level return the books and their author
        return response()->json(Book::with('author')->get());
    } elseif ($this->consumer->level == 2) {
        // Authenticated call, higher level return full data
        return response()->json(Book::with('author', 'meta', 'stats', 'pages')->get());
    }
}

Have you any idea how I could achieve this ?

0 likes
6 replies
depsimon's avatar
depsimon
OP
Best Answer
Level 16

I manage to handle this by extending Lumen Auth like this :

Extends the Guard class.

<?php namespace App\Auth;

use App\Models\Consumer;
use Illuminate\Auth\Guard;

class ApiGuard extends Guard
{

    protected $consumer = null;

    public function consumer()
    {
        return $this->consumer;
    }

    public function setConsumer($consumer_id)
    {
        $this->consumer = Consumer::find($consumer_id);
    }

}

Create a new AuthServiceProvider in order to use our new ApiGuard class.

<?php namespace App\Providers;

use App\Auth\ApiGuard;
use Illuminate\Auth\AuthServiceProvider as ServiceProvider;
use Illuminate\Auth\EloquentUserProvider;

class AuthServiceProvider extends ServiceProvider
{

    public function boot()
    {
        $this->app['auth']->extend('eloquent', function ($app)
        {
            $model = $app['config']['auth.model'];

            $provider = new EloquentUserProvider($app['hash'], $model);

            return new ApiGuard($provider, $this->app['session.store']);
        });
    }
}

Then register the service provider in our app.php

$app->register('App\Providers\AuthServiceProvider');

Then I can use this in my Auth middleware :

Auth::setConsumer($user_token->consumer_id);

And this in my controllers

$consumer = Auth::consumer()

If anyone has a better solution, I'd like to know :)

henninghorn's avatar

Hey @SimonD

I'm also dealing with an API with some auth, I'm using JSON Web Tokens for this. My flow goes like this.

User makes post request to /auth/login Credentials are verified via Auth::once. Then a JWT is generated containing the user id and a access token. The token is saved in the db.

Each time a user then needs to make a request, they send the JWT. The JWT is then decoded and the user is then verified through Auth::onceUsingId() and the access token is also verified. This above is done through middleware, which means a controller have this:

$this->middleware('auth')

By doing the above I can access the user through $request->user().

depsimon's avatar

Hi @henninghorn thanks for your answer.

In my case I also need to know from which consumer/application the user is authenticated because for example the mobile application should only allow to view public data such as books and authors whether or not the user is a member, an author or an administrator.

But basically I'm using a sort of JWT (home made).

henninghorn's avatar

@SimonD

Of course, that's where role/permission get in the picture. I use Kodeine's ACL, so I can easily check which permissions or roles a use have through that package.

$request->user()->is('admin')
$request->user()->can('edit.books)
ahuggins's avatar

In Lumen 5.2, Auth::once() is gone, replaced with Auth::validate(), which expects a Request object. Anyone manually authenticating users?

Please or to participate in this conversation.