Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Slim Basic Authentication

Good day everyone!

I have a working slim code here with slim-basic-auth and when I go to a restricted directory, this shows up:

enter image description here

Everything works, but what I wanted to do is to redirect it to my login page instead of showing a popup login box. Here is my login page:

enter image description here

My slim code:

$pdo = new \PDO("mysql:host=localhost;dbname=databasename", "username");
$app->add(new \Slim\Middleware\HttpBasicAuthentication([
    "path" => "/main",
    "realm" => "Protected",
    "authenticator" => new PdoAuthenticator([
        "pdo" => $pdo,
        "table" => "accounts",
        "user" => "accountUsername",
        "hash" => "accountPassword"
    ]),
    "callback" => function ($request, $response, $arguments) use ($app) {
        return $response->withRedirect('/main/contacts');
    }

When I try to login using the popup login box, it works but I really want to redirect it to my login page instead of that.

Any help would be much appreciated.

like image 877
wobsoriano Avatar asked Mar 23 '16 01:03

wobsoriano


2 Answers

The middleware implements HTTP Basic Access Authentication. Authentication dialog is triggered via response header. It is up to the browser vendor to decide how credentials are asked. Most browsers use the popup login dialog you described.

What you are trying to do is a bit unorthodox way of using HTTP Basic Authentication. However you can suppress the login dialog by removing the WWW-Authenticate header from the response. Note the you need at least version 2.0.2 for this to work.

$app->add(new \Slim\Middleware\HttpBasicAuthentication([
    "path" => ["/main"],
    "authenticator" => new PdoAuthenticator([
        "pdo" => $pdo,
        "table" => "accounts",
        "user" => "accountUsername",
        "hash" => "accountPassword"
    ]),
    "error" => function ($request, $response, $arguments) {
        return $response
            ->withRedirect("/auth/login")
            ->withoutHeader("WWW-Authenticate");
    }
]));

However with code above you still have to set the Authentication: Basic request header somehow. One way to do is using an AJAX request.

$.ajax({
   url: "http://example.com/auth/login",
   username: $("username").val(),
   password: $("password").val(),
   success: function(result) {
     alert("Authorization header should now be set...");
   }
});
like image 153
Mika Tuupola Avatar answered Nov 06 '22 06:11

Mika Tuupola


At this point it looks like you're not trying to use the Http Basic Authenticator but rather a normal login process so you'll need to use sessions and such.

A very simple example is adding this close to the bottom of your middleware stack.(meaning it will be executed first as it will be at the top of the stack)

$middleware = function (Request $request, Response $response, $next) {

    if (!isset($_SESSION['__user'])) {
        //don't interfere with unmatched routes
        $route = $request->getAttribute('route');
        if ($route && !in_array($route->getName(), ['login'])) {
            return $response->withStatus(403)->withHeader('Location', $this->router->pathFor('login'));
        }
    }

    return $next($request, $response);
};
$app->add($middleware);

Looking at the HttpBasicAuthentication middleware it will always send the WWW-Authenticate header making your login form useless as it will trigger the auth pop-up.

like image 31
the-noob Avatar answered Nov 06 '22 05:11

the-noob