Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
REST application continues after $this->response is returned
  • I have the following code in my base controller's before() method:

    // Make sure the user is authenticated.
    if (!\Auth::check()
    and \Request::active()->route->segments[1] != 'login'
    and \Request::active()->action != 'logout'
    )
    {
    return $this->response(array('error' => 'unauthorized'), 403);
    }

    However, this does not produce the expected results. If the user is logged in, everything works fine. If the user is not logged in, the application continues to execute after returning the 403 response. Am I doing something wrong here?
  • You can not return anything in a before() method.

    The before is designed as a prepping method, not as something that alters the request flow. If you want that, use router(), which does allow you to return a response. Don't forget to call parent::router if you want the request to be executed by your controller.
  • I'm used to using \Response::redirect() in the before() method of my application's base controller if a user isn't authenticated. Something along the lines of:

    if (!\Auth::check())
    {
    return \Response::redirect('unauthorized');
    }

    How would I accomplish the same functionality in a RESTful manner? I tried calling an unauthorized() method from my before() method, but that didn't work. I created a router() method in my base controller, but I haven't figured out how to make it do anything useful.
  • REST calls should not be redirected, you should return a 403 status, optionally with an error message.

    if you're in < 1.6, it's nothing more then something like:
    public function router()
    {
        if ( ! \Auth::check())
    {
    $this->response(array('status'=> 0, 'error'=> 'Not Authorized'), 401);
        }
        else
        {
             return parent::router();
        }
    }

    In 1.6, you configure the auth method in the rest config file as 'myauth', and then you do:
    public function myauth()
    {
        return \Auth::check();
    }

  • I'm on 1.6/develop, but the project I'm working on started with 1.4/master. The rest config file that I have doesn't mention anything about an auth method. I tried setting the "auth" parameter, but that apparently is for basic or digest authentication.

    I tried using the pre 1.6 method above, but the response isn't formatted according to my HTTP accept header. No matter whether I specify application/json or application/xml, I'm getting a text/html response.
  • Then your 1.6 is not up to date (it has been added recently).

    You can define 'basic' or 'digest' for client authentication mechanisms, or any other string to define the method that will take care of your authentication, and should return a boolean.

    How do you request the result, how do you set the accept header? If you request a REST URI from the browser, it will always return text/html, as that is what the header specifies. If you want to force a different result, quickest is to add an extension (".json" or ".xml") to the URI.
  • I'm specifying "Accept: application/json" or "Accept: application/xml" in the request headers, but still getting a response type of "text/html". This only happens when the response is sent by the router() method, which looks like this:

    public function router($resource, $arguments)
    {
    if (!\Auth::check()
    and \Request::active()->route->segments[1] != 'login'
    and \Request::active()->action != 'logout'
    )
    {
    return $this->response(array('error' => 'unauthorized'), 403);
    }
    else
    {
    return parent::router($resource, $arguments);
    }
    }

  • How do you insert these headers, and how do you do the request?

    There is nothing in the REST controller that would default to "text/html", the only way it would return that response is if that is detected in the request. If you do the request with a browser, the result is ALWAYS text/html, it's a header the browser sends.
  • I've been using Postman for Chrome for the development of the API. I set the accept header through it's interface. All of the API calls return application/json or applicaiton/xml correctly when I specify the accept header except for the router() method that returns the 403 unauthorized error. The other developer on my team is accessing the API from an iOS App. Both Postman and the iOS app are having the same issue. When the user isn't authenticated, they get the "unauthorized" response as text/html.
  • HarroHarro
    Accepted Answer
    If you're doing the Auth check this way, you bypass the entire parent router. Which is what does all format detection, so when your 403 is returned, all that code hasn't been executed.

    This is exactly why we introduced the option to define a custom auth method, so you can do verification from inside the parent router, and you don't need a custom one anymore.

    Since you dont' want/can go to the latest 1.6, you can probably work around it via

    parent::router('this-is-a-fake-resource-name', $arguments);
    return $this->response(array('error' => 'unauthorized'), 403);

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion