10

I am using Laravel to build a RESTful API. I use Basic HTTP Auth (Authenticate header), with this filter:

Route::filter('auth', function()
{
    $credentials = ['email' => Request::getUser(), 'password' => Request::getPassword()];

    if (!Auth::once($credentials)) {
        $response   = ['error' => true, 'message' => 'Unauthorized request'];
        $code       = 401;
        $headers    = ['WWW-Authenticate' => 'Basic'];

        return Response::json($response, $code, $headers);
    }
});

It works, but Laravel then tries to set a cookie for the user (sending a Set-Cookie header). I tried setting the session.driver configuration key to array, only to see it now sends a Set-Cookie: laravel_session=deleted thingy.

How can i fully disable this Set-Cookie header?

Thank you.

Iso
  • 3,148
  • 23
  • 31
  • Have you tried Laravel 4's native basic auth filter `auth.basic`? – Muhammad Usman May 07 '13 at 09:58
  • @Usman yes, it works almost the same except it sends a `WWW-Authenticate` response header, which I did not want. It also sets `laravel_session` cookie. – Iso May 07 '13 at 10:01
  • For future reference - in Laravel 5, just use array for session storage and disable cookie support in config/app.php. Don't forget to use artisan to clear-compiled. – gidmanma Mar 27 '15 at 15:19

7 Answers7

15

For stateless APIs, no cookies and clean headers the following works:

Route::filter('auth.basic', function()
{
    Config::set('session.driver', 'array');
    return Auth::onceBasic();
});

Note that the above is using Auth::onceBasic() which for some reason still sends the "Set-Cookie" header. According to the docs onceBasic auth is stateless; perhaps the cookie is sent for information purposes, is a side-effect of debug mode, or maybe it's a bug. Either way Config::set(...) is still required. A quick curl on routes with this filter return the following headers:

HTTP/1.1 200 OK
Date: Wed, 12 Feb 2014 02:34:26 GMT
Server: Apache/2.4.6 (Ubuntu)
X-Powered-By: PHP/5.5.3
Cache-Control: no-cache
X-Frame-Options: SAMEORIGIN
Transfer-Encoding: chunked
Content-Type: application/json

Auth::onceBasic() seems like a good approach for a stateless REST API. Each client request is authenticated and no session cookies are used in this approach.

nb. Other routes not caught by the above filter and will still set cookies (and send the "Set-Cookie" header). So this solution works for the common situation of both stateless API & stateful web access/admin.

sebt
  • 2,254
  • 2
  • 14
  • 11
6

To disable sessions for all routes in a Laravel 4 controller, set the session driver option in the class construct:

<?php

class ExampleController extends BaseController {

    public function __construct()
    {
        Config::set('session.driver', 'array');
    }

    public function getExample()
    {
        return "This example response should have no session cookie.";
    }

}
Paul Wenzel
  • 1,886
  • 2
  • 15
  • 15
2

Try this - dirty, but works for me.
The example is for a single route, can be modified to manage route prefix and so on.
First, create a directory inside app/config for a specific environment, let's say stateless.
Then, place a session.php file inside app/config/stateless, with code like below:

<?php
return array(
    'driver' => 'array'
);

Finally, modify the detectEnvironment part in bootstrap/start.php:

$env = $app->detectEnvironment(function()
{
    if ($_SERVER['REQUEST_URI'] == '/your/route') return 'stateless';
});
matpop
  • 1,969
  • 1
  • 19
  • 36
2

you need to create your filter like follws in laravel 4, 4.2

Route::filter('no.session.cookie', function()
{
    Config::set('session.driver', 'array');
    Config::set('cookie.driver', 'array');
});

In laravel 5, 5.1 set middleware handle() like follows

public function handle($request, Closure $next){
  \Config::set('session.driver', 'array');
  \Config::set('cookie.driver', 'array');
 return $next($request);
}
Rameez Rami
  • 5,322
  • 2
  • 29
  • 36
0

Remove 'Illuminate\Cookie\CookieServiceProvider', from your providers array in app.php. It should do the trick :)

ipalaus
  • 2,253
  • 4
  • 27
  • 42
  • Nope, now I have a `ReflectionException`: “Class cookie does not exist” (in `bootstrap/compiled.php`). Looks like it stems from `vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php:20`: `$guard->setCookieJar($this->app['cookie']);`. Thanks for helping though! – Iso May 07 '13 at 11:51
  • Mmmm... what happens if you remove the Session provider then? I did this trick sometime in the past but I can't remember where! :( – ipalaus May 07 '13 at 12:26
  • 1
    The same thing happens, but with the “Class session”. Are you sure removing a provider was the way to go? – Iso May 07 '13 at 13:21
  • when something in a compiled file seems to produce errors, it might be a good idea to clear that file, for example with `artisan clear:compiled`. – imme May 08 '18 at 05:52
0

I'm developing an API using laravel, so definitely I don't want to use the cookies. However, I do want to use the sessions mechanism for APIs that require authentication.

So, I'm using the sessions.driver = "file"

To be able to use the mechanism, but allow to override the cookie set, after much debugging, I found out that there is some hardwiring at the Middleware class, but through the magic of filters, you can disable the feature right before the cookie is set.

So, on filters.php, I created the following filter, and added as an after filter of my route group

/*
|--------------------------------------------------------------------------
| Custom Filter to remove the session cookie
|--------------------------------------------------------------------------
|
| By default, if session driver is other than `null` or `array`, it will
| create a cookie and pass the encrypted session id so that it can be used
| across web requests.
| However, since our application is an API, we dont need the cookie, but
| we still want to be able to use the session functionality, so to allow
| this, we just need to set the driver to `array` right before the 
| dispatcher gets to the point to add the session cookie.
| 
| This is the Laravel call stack
| \Illuminate\Session\Middleware::handle()
|   -> \Illuminate\Session\Middleware::addCookieToResponse()
|        -> \Illuminate\Session\Middleware::sessionIsPersistent()
|
| All session handling and file storage has happened before sessionIsPersistent()
| is called, so we are safe to add an `after` filter that will reset
| the driver in the configuration and thus preventing this specific
| cookie to be added, all other previously added cookies will be 
| kept (if any added) and thus sent as part of the response.
*/
Route::filter('session.cookie.remove', function(){
    // Has to be 'array' because null, will prevent from writing sessions
    Config::set('session.driver', 'array');
});

Note: the only case where this filter will not get called and thus producing the cookie, is if an exception occurs, in which case you may want to update the config on your error handler as well (default error handler if you haven't overwritten laravel's). To override, look at app/start/global.php

AlphaZygma
  • 228
  • 2
  • 9
-1

You should modify session.php:

<?php
return array(
    'driver' => isset($_SERVER['REQUEST_URI']) && (stripos($_SERVER['REQUEST_URI'], '/api') === 0) ? 'array' : 'native'
);
jww
  • 97,681
  • 90
  • 411
  • 885