0

I am using authentication plugin for login in cakephp.

application.php , configAuth() method code

protected function configAuth(): \Authentication\AuthenticationService
    {
        $authenticationService = new \Authentication\AuthenticationService([
            // 'unauthenticatedRedirect' => '/cake_invo/users/login' , //<= manually working fine
            'unauthenticatedRedirect' => \Cake\Routing\Router::url(['controller' => 'Users', 'action' => 'login']),
            'queryParam' => 'redirect',
        ]);

        // Load identifiers, ensure we check email and password fields
        $authenticationService->loadIdentifier('Authentication.Password', [
            'fields' => [
                'username' => 'email',
                'password' => 'password',
            ]
        ]);

        // Load the authenticators, you want session first
        $authenticationService->loadAuthenticator('Authentication.Session');
        // Configure form data check to pick email and password
        $authenticationService->loadAuthenticator('Authentication.Form', [
            'fields' => [
                'username' => 'email',
                'password' => 'password',
            ],
            // 'loginUrl' => '/cake_invo/users/login'  //<= manually working fine
            'loginUrl' => \Cake\Routing\Router::url(['controller' => 'Users', 'action' => 'login']),
        ]);

        return $authenticationService;
    }

middleware method

public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
    {
        $middlewareQueue

            ->add(new ErrorHandlerMiddleware(Configure::read('Error')))

            ->add(new AssetMiddleware([
                'cacheTime' => Configure::read('Asset.cacheTime'),
            ]))

            ->add(new RoutingMiddleware($this))
            // add Authentication after RoutingMiddleware
            ->add(new \Authentication\Middleware\AuthenticationMiddleware($this->configAuth()));

        return $middlewareQueue;
    }

Getting error like image

enter image description here

How can I solve this problem ?

After give command bin/cake routes

enter image description here

Niloy Rony
  • 602
  • 1
  • 8
  • 23
  • 1
    Have you tested it with "'unauthenticatedRedirect' => '/users/login'" and "'loginUrl' => '/users/login'" to see if it works. Then you will know if its the reverse routing that failing or the routing. Also if you can show us some more code and perhaps Var_dump "Router::url(['controller' => 'Users', 'action' => 'login'])". Routes are configured explicitly in src\config\routes.php, but from experience you don't have to handle wiring the controller / action combos by hand. – Gregory William Bryant Feb 04 '20 at 12:01
  • My project in sub directory that's why I followed this ans https://stackoverflow.com/questions/59065494/cakephp-3-authentication-plugin-login-url-did-not-match – Niloy Rony Feb 04 '20 at 14:38
  • Whenever you have a problem with routes, first check what routes exactly are connected and in which order, for example using the routes command: `bin/cake routes`. That being said, where exactly in the list of middlewares are you adding the authentication middleware (add your `Application::middleware()` code to your question if you're not sure what I'm referring to)? – ndm Feb 04 '20 at 15:32
  • @ndm Thanks for your comment , I have updated question. – Niloy Rony Feb 05 '20 at 06:23
  • In CakePHP Version 4, it would signpost if there was a missing controller file Users, and Action, login. If maybe that is older versions it just signposts the missing route? Do you have the controller and action present? Also have you tried "'loginUrl' => \Cake\Routing\Router::url('/users/login')". Finally what happens when you goto the route by hand? What is displayed in the URL of the browser for that error image? – Gregory William Bryant Feb 05 '20 at 10:45
  • Also the tutorial you are following is for and older version of CakePHP,(https://book.cakephp.org/authentication/1/en/index.html) the Authentication in CakePHP 4.0 is handled with the $this->loadComponent('Auth'). It looks like your using older resources which is tripping you up. – Gregory William Bryant Feb 05 '20 at 10:45
  • @GregoryWilliamBryant when I used 'loginUrl' => \Cake\Routing\Router::url('/users/login'), route is working fine but problem is, I am unable to login. After debug I am getting error 'Login URL `http://localhost/cake_invo/Users/login` did not match `/users/login`.' – Niloy Rony Feb 05 '20 at 10:56
  • When you say you cannot login, what error are you getting as a user? Maybe a case sensitive issue with Users and users. – Gregory William Bryant Feb 05 '20 at 11:15
  • @GregoryWilliamBryant same code working fine if I run cake server and use cake server. I want to use it without cake server. Upper and lower case issue I tested same result. I am in localhost. – Niloy Rony Feb 05 '20 at 11:21
  • Have you got a .htaccess doing any rewriting? Are you saying 'all' your problems go away when you use the cake server? If so it sounds like URL rewrite problem with xamp, pointing to .htaccess config issue. – Gregory William Bryant Feb 05 '20 at 11:28
  • @NiloyRony I ment your `middleware()` method code, the code where you do `->add(new AuthenticationMiddleware($this))`, you're probably not adding things in the required order. Your routes look fine. – ndm Feb 05 '20 at 11:32
  • @ndm I updated middleware method , Thank you. – Niloy Rony Feb 05 '20 at 11:48

1 Answers1

2

The problem is that your routes aren't loaded yet when you make the call to Router::url(), hence it will fail.

While the order of the middlewares is correct, ie the authentication middleware is being added after the routing middleware, you are building the authentication service immediately by invoking $this->configAuth(), which means that the Router::url() call will be invoked before any of the middlewares have run, specifically before the routing middleware has run, which is responsible for loading your routes.

Instead of passing a built authentication service instance, setup things as shown in the docs, that is make sure that your Application class implements \Authentication\AuthenticationServiceProviderInterface, change your configAuth method to match AuthenticationServiceProviderInterface::getAuthenticationService(), and then pass $this to the authentication middleware constructor instead. That way the method will only be invoked when the authentication middleware runs, that is after the routing middleware.

// ...
use Authentication\AuthenticationServiceInterface;
use Authentication\AuthenticationServiceProviderInterface;
use Cake\Http\BaseApplication;
use Psr\Http\Message\ServerRequestInterface;

class Application extends BaseApplication implements AuthenticationServiceProviderInterface
{
    // ...

    public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
    {
        // ...
        return $authenticationService;
    }

    public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
    {
        $middlewareQueue
            // ...
            ->add(new RoutingMiddleware($this))
            ->add(new AuthenticationMiddleware($this));

        return $middlewareQueue;
    }

    // ...
}
ndm
  • 59,784
  • 9
  • 71
  • 110