dingo / api

A RESTful API package for the Laravel and Lumen frameworks.
BSD 3-Clause "New" or "Revised" License
9.33k stars 1.25k forks source link

Auth User and API User #9

Closed terion-name closed 10 years ago

terion-name commented 10 years ago

Hi. Why user instance is not corresponding with laravel user? I mean, why when I protect the route, I get 401 even if user is logged in in laravel? I think that API auth should use Laravel Auth and protected routes should utilize the Auth::check() What do you think about this?

jasonlewis commented 10 years ago

An API should be stateless. Each request should be properly authenticated by either Basic or OAuth 2. On 18 Apr 2014 00:12, "Terion" notifications@github.com wrote:

Hi. Why user instance is not corresponding with laravel user? I mean, why when I protect the route, I get 401 even if user is logged in in laravel? I think that API auth should use Laravel Auth and protected routes should utilize the Auth::check() What do you think about this?

— Reply to this email directly or view it on GitHubhttps://github.com/dingo/api/issues/9 .

terion-name commented 10 years ago

It's ok for some REST api's for external services, but it is absolutely not ok for RIA (ember, angular based, so on). Such api platform should support both auth strategies for using it as an rest-api and as ria-backend simultaneously. Maybe this might be configurable, but it really should be. Moreover, I think that it would be good, if OAuth permissions would correspond with User permissions (but it is matter of user permissions management, maybe it is beyond the scope of such library, but I think it would be great to integrate them).

It's all IMO of course, a subject for discussion.

jasonlewis commented 10 years ago

I've recently added the ability to add a custom authentication provider so you could write your own simply provider for this. I'm not going to include it in the core because, like I said, an API should be stateless. Using the resource owner (password) OAuth 2.0 grant is a good authentication method.

Details on custom authentication providers here: https://github.com/dingo/api/wiki/Authentication#custom-authentication-providers

Yeah I think OAuth permissions being the same as user permissions are beyond the scope of both this and the OAuth server. That's up to you, the developer.

ryanhungate commented 10 years ago

Hey Jason, So how exactly do we allow the authenticated user in an app to access the API? I tried using \API::be($user) but its still trying to ->setUser() and the userId is null.

Also tried to do -

  $user = User::find(1);
  $auth = \App::make('dingo.api.authentication');
  $auth->setUser($user);

EDIT:: Im assuming that once a user is logged in, this is not an issue, but if we try to implicitly set the user this way it will fail. Are there any problems with API::be()?

jasonlewis commented 10 years ago

If you want to call an API route (that's protected) internally then you just need to pass the Eloquent model of the user to API::be and it should act as though that user has authenticated. I'm not having any problems with this. It's working fine. Here is my API route that's protected. It just returns the authenticated API user.

Route::api(['version' => 'v1', 'prefix' => 'api', 'protected' => true], function()
{
    Route::get('user', function()
    {
        return API::user();
    });
});

Now I have a dummy route that grabs a user and hits this API route internally.

Route::get('pretend', function()
{
    $user = User::find(1);

    dd(API::be($user)->get('user'));
});

The dumped response is the User model.

ryanhungate commented 10 years ago

Ok, well, your right... but try this. if your making another api call other than that one right after the be() method, it will fail unless you specify the be($user) in every call. Is that what were supposed to do?

   Route::get('pretend', function()
   {
        $user = User::find(1);
        dd(array(
            'first' => API::be($user)->get('user'),
            'second' => API::get('user')
        ));
    });
jasonlewis commented 10 years ago

Yeah that's the expected behaviour. I can add a persist method so that it persists it for all following requests. Essentially you could do this:

$user = User::find(1);

API::be($user)->persist();

dd([
    API::get('user'),
    API::get('user')
]);

And it would be persisted for both requests.

ryanhungate commented 10 years ago

yeah i think that’s pretty much assumed that once you API::be($user) that your trying to mimic that user being logged in to the application for the entire request lifecycle… i would even say that if your going to do anything with a persist() option, it should probably be the reverse of this, like be()->nonPersisting() to avoid the persisting if you really needed that, but include it by default.

On Apr 23, 2014, at 6:36 AM, Jason Lewis notifications@github.com wrote:

Yeah that's the expected behaviour. I can add a persist method so that it persists it for all following requests. Essentially you could do this:

$user = User::find(1);

API::be($user)->persist();

dd([ API::get('user'), API::get('user') ]); And it would be persisted for both requests.

— Reply to this email directly or view it on GitHub.

jasonlewis commented 10 years ago

Hm, I'll think about it. I might go that route. The reason it wasn't persisted in the first place is that internally it works much the same as externally, that is, an API is stateless. So after a request you must authenticate again. I'll probably implement a once method, so API::be($user)->once()->get('resource') and it'll only authenticate as that user for the single request.

jasonlewis commented 10 years ago

API::be is now persisted and have implemented a once method to make it for a single request only.