Skip to content
This repository has been archived by the owner on Jul 31, 2023. It is now read-only.

Exception thrown in login_middleware.php #68

Closed
janeczku opened this issue Oct 29, 2013 · 6 comments
Closed

Exception thrown in login_middleware.php #68

janeczku opened this issue Oct 29, 2013 · 6 comments

Comments

@janeczku
Copy link
Contributor

When calling an OPDS/JSON route, the app throws an exception:

DEBUG - 2013-10-29T06:39:30+01:00 - login resource: /opds/newest/
DEBUG - 2013-10-29T06:39:30+01:00 - login accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
DEBUG - 2013-10-29T06:39:30+01:00 - login: unauthorized OPDS request
ERROR - 2013-10-29T06:39:30+01:00 - exception 'Slim\Exception\Stop' in /var/www/virtual/janeczku/html/books/vendor/slim/slim/Slim/Slim.php:1001
Stack trace:
#0 /var/www/virtual/janeczku/html/books/vendor/slim/slim/Slim/Slim.php(1021): Slim\Slim->stop()
#1 /var/www/virtual/janeczku/html/books/lib/BicBucStriim/login_middleware.php(50): Slim\Slim->halt(401, 'Please authenti...')
#2 /var/www/virtual/janeczku/html/books/lib/BicBucStriim/own_config_middleware.php(36): LoginMiddleware->call()
#3 /var/www/virtual/janeczku/html/books/vendor/slim/slim/Slim/Middleware/PrettyExceptions.php(67): OwnConfigMiddleware->call()
#4 /var/www/virtual/janeczku/html/books/vendor/slim/slim/Slim/Slim.php(1251): Slim\Middleware\PrettyExceptions->call()
#5 /var/www/virtual/janeczku/html/books/index.php(188): Slim\Slim->run()
#6 {main}   

First of all there is typo in login_middleware.php:

$app->response['WWW-Authenticate']

won't work - the $response object is not an array/dict. But even after changing to $app->response->headers->set, the error persists. So i think another problem is the halt() function.
As far as i understand, halt() completely ignores the $response object, so the WWW-authenticate header is never sent to the client.

From slim docs: http://docs.slimframework.com/

The Slim application’s halt() method will immediately return an HTTP response with a given status code and body.
Slim will immediately halt the current application and send an HTTP response to the client with the specified status and optional message (as the response body).
This will override the existing \Slim\Http\Response object.

After i changed the code like this, the error went away:

in: login_middleware.php

    } elseif (stripos($resource, '/opds') === 0) {
        $app->getLog()->debug('login: unauthorized OPDS request');
        $app->response['WWW-Authenticate'] = 'Basic realm="'.$this->realm.'"';
        $app->halt(401,'Please authenticate');
    } elseif ($accept === 'application/json') {
        $app->getLog()->debug('login: unauthorized JSON request');
        $app->response['WWW-Authenticate'] = 'Basic realm="'.$this->realm.'"';
        $app->halt(401,'Please authenticate');

replace with

    } elseif (stripos($resource, '/opds') === 0) {
        $app->getLog()->debug('login: unauthorized OPDS request');
        $app->response->headers->set('WWW-Authenticate', sprintf('Basic realm="%s"', $this->realm));
        $app->response->status(401);
    } elseif ($accept === 'application/json') {
        $app->getLog()->debug('login: unauthorized JSON request');
        $app->response->headers->set('WWW-Authenticate', sprintf('Basic realm="%s"', $this->realm));
        $app->response->status(401);
@rvolz
Copy link
Owner

rvolz commented Oct 29, 2013

First of all there is typo in login_middleware.php: $app->response['WWW-Authenticate'] won't work - the $response object is not an array/dict.

It is an array, or better: it has the array methods, although that seems now to be deprecated and is removed from the documentation. So the code works, try using curl -v and you'll see the header. But to be future-proof I'll change it to set.

The halt() problem is still open. The solution of simply setting a status didn't work in all situations, and the Slim documentation wasn't very clear about where halt() would be allowed. So I was lazy and let the response code 500 go through for the moment. It seemed to work with clients like Stanza.

Now it seems that halt() can't be used in a middleware call, but maybe in hooks. I'll check both, your solution and the hooks.

Thanks for digging so deep.

@rvolz
Copy link
Owner

rvolz commented Oct 29, 2013

Ok, updating Slim 2.3.1 to 2.3.4 changed the behaviour back to normal. Now the 401 response code comes through again, the exception is gone. I'll check in the new version today.

@janeczku
Copy link
Contributor Author

I just updated to the latest trunk and i still get the same exception thrown
#68
Can you confirm this?

@janeczku
Copy link
Contributor Author

As also explained in this posting http://stackoverflow.com/questions/20270340/slim-php-route-in-middleware, it seems that indeed halt() cannot be used inside a middleware call.

I just changed login_middleware.php, so that halt() fires inside a hook attached to 'slim.before.dispatch'. That makes it work again.

@janeczku
Copy link
Contributor Author

I changed login_middleware.php to this:

    public function call() {
        $this->app->hook('slim.before.dispatch', array($this, 'authBeforeDispatch'));
        $this->next->call();
    }

    public function authBeforeDispatch() {
        $app = $this->app;
        $request = $app->request;
        $resource = $request->getResourceUri();
        $accept = $request->headers('ACCEPT');
        $app->getLog()->debug('login resource: '.$resource);
        $app->getLog()->debug('login accept: '.$accept);
        if (!$this->is_static_resource($resource) && !$this->is_authorized()) {
            if ($resource === '/login/') {
                // special case login page
                $app->getLog()->debug('login: login page authorized');
                return;    
            } elseif (stripos($resource, '/opds') === 0) {
                $app->getLog()->debug('login: unauthorized OPDS request');
                $app->response->headers->set('WWW-Authenticate', sprintf('Basic realm="%s"', $this->realm));
                $app->halt(401,'Please authenticate');
            } elseif ($accept === 'application/json') {
                $app->getLog()->debug('login: unauthorized JSON request');
                $app->response->headers->set('WWW-Authenticate', sprintf('Basic realm="%s"', $this->realm));
                $app->halt(401,'Please authenticate');
            } else {
                $app->getLog()->debug('login: redirecting to login');
                // now we can also use the native app->redirect method!
                $this->app->redirect($app->request->getRootUri().'/login/');
            }
        }
    }

@rvolz
Copy link
Owner

rvolz commented Feb 18, 2014

Yes, the behavior was reproducible. Your solution works fine, thanks.

rvolz added a commit that referenced this issue Feb 18, 2014
Updated version to 1.2.1
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants