Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Authentication Method - Passing Error Messages #34

Open
HappyAmos opened this issue Apr 2, 2017 · 11 comments
Open

Custom Authentication Method - Passing Error Messages #34

HappyAmos opened this issue Apr 2, 2017 · 11 comments
Assignees

Comments

@HappyAmos
Copy link

How would you pass back a custom error message from a custom authenticator? Obviously my example below is pulled completely out of thin air and would never work, but I think you get what I mean? Somehow, there must be a way to pass a message from here, back to the error handler, or alter the $arguments?

class DbAuthenticator implements AuthenticatorInterface {
    private $settings;
 
    public function __construct($settings) {
        $this->settings = $settings;
    }
 
    public function __invoke(array $arguments) {
        if (wrongPassword($user, $pass)) {
            $returnAmessageSomeHow = "Invalid password";
            $failedLogins = $failedLogins + 1;
            return false;
        } 
        if (invalidUsername($user, $pass)) {
            $returnAmessageSomeHow = "Invalid username";
            return false;
        }
    }

}

then...

$container["HttpBasicAuthentication"] = function ($container) {
    return new HttpBasicAuthentication([
        "path" => [ ... ],
        "authenticator" => new DbAuthenticator($container['settings']),
        "error" => function ($request, $response, $arguments) {
            $data = [];
            $data["status"] = "error";
            $data["message"] = $messageReturnedFromAuthenticatorSomehow;
            return $response->write(json_encode($data, JSON_UNESCAPED_SLASHES));
        }
    ]);
};

@tuupola
Copy link
Owner

tuupola commented Apr 4, 2017

This is not currently possible. It is however a good idea and I should implement it in the near future.

@tuupola tuupola self-assigned this Apr 4, 2017
@tuupola tuupola added the 3.x label Jul 13, 2017
@Metainy
Copy link

Metainy commented Aug 22, 2017

I am not sure if it's implemented already, but if that's not the case is there another way I can pass container settings to my custom authenticator?

@tuupola
Copy link
Owner

tuupola commented Aug 22, 2017

This bug report is about custom error messages. Container you can already pass with something like:

$app->add(new \Slim\Middleware\HttpBasicAuthentication([
    "path" => "/admin",
    "realm" => "Protected",
    "authenticator" => new CustomAuthenticator($container)
]));

@alexssandrog
Copy link

alexssandrog commented Dec 27, 2017

Hi, has this issue (custom error messagens) been developed?

@tuupola
Copy link
Owner

tuupola commented Dec 28, 2017

It is still in TODO list but plan is to implement this feature since it is quite useful.

@alexssandrog
Copy link

Tks

@wollanup
Copy link

Hi,

Any news on this feature for 3.0 ?
Mika, do you have some implementation ideas in mind ?

I wonder if I could implement this feature by passing a Response object to the authenticator, and return a Response instead of a boolean.
We could check the status of the response to determine the success/error state, and we give ability to the Authenticator to manage it's own status?

What do you think ?

Thank you.

@apuleus
Copy link

apuleus commented Mar 20, 2019

Adding this just before the final return in the process function (src/HttpBasicAuthentication.php) worked for me, may not the best way to handle it though.

           if(method_exists($this->options['authenticator'], 'getCustomErrorMessage')) {
                return $this->processError($response, [
                        "message" => $this->options['authenticator']->getCustomErrorMessage()
                ]);
            }

@alexssandrog
Copy link

Thanks @apuleus , but I dont understood how this works. What does getCustomErrorMessage do?

@apuleus
Copy link

apuleus commented Mar 21, 2019

getCustomErrorMessage() returns a string with the customer error message that my authenticator set. I placed it right before the code that returns the $response and default message. You can see that original code snippet below. It changes the behavior by checking if the "getCustomErrorMessage()" method exists in my custom authenticator.

Original Code

 /* Check if user authenticates. */
        if (false === $this->options["authenticator"]($params)) {
            /* Set response headers before giving it to error callback */
            $response = (new ResponseFactory)
                ->createResponse(401)
                ->withHeader(
                    "WWW-Authenticate",
                    sprintf('Basic realm="%s"', $this->options["realm"])
                );
            return $this->processError($response, [
                "message" => "Authentication failed"
            ]);
        }

Code with my addition

 /* Check if user authenticates. */
        if (false === $this->options["authenticator"]($params)) {
            /* Set response headers before giving it to error callback */
            $response = (new ResponseFactory)
                ->createResponse(401)
                ->withHeader(
                    "WWW-Authenticate",
                    sprintf('Basic realm="%s"', $this->options["realm"])
                );
            if(method_exists($this->options['authenticator'], 'getCustomErrorMessage')) {
                return $this->processError($response, [
                        "message" => $this->options['authenticator']->getCustomErrorMessage()
                ]);
            }
            return $this->processError($response, [
                "message" => "Authentication failed"
            ]);
        }

The function in my authenticator class

        
public function getCustomErrorMessage() {
  return (string) $this->errorMessage;
}
        

Like I said, may not be the best way, but it worked for my purposes. The reason why I needed the authenticator to handle the error message is due to the authenticator class having the ability to lock people out and this was an easy way to allow the authenticator to change the default message when that happens.

@alexssandrog
Copy link

Thanks @apuleus!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants