Unauthorized error by calling view

I have a portal, where you can add posts. If you add a post, or the post will be changed, then you will get an email with a link to your post.
When you click on the link, it brings you directly to the post. But since you are not logged in, an error message

Identity is not authorized to perform ``view``

I mean, it is ok, if the user is not logged in.
But what I want to have is, that the user will be redirected to the login page and after login, the user should come back to the post.

Hey efjot,

this could be helpful:
Authorization Middleware - 3.x - Handling Unauthorized Requests

With the 'queryParam' => 'redirectUrl', you can return the User back after successfully login.

Hi thanks for reply, but do I need to implement the middleware by my owne?
I don’t understand the example on your linked page.

$middlewareQueue->add(new AuthorizationMiddleware($this, [
    'unauthorizedHandler' => [
        'className' => 'Authorization.Redirect',
        'url' => '/pages/unauthorized',
        'queryParam' => 'redirectUrl',
        'exceptions' => [
            MissingIdentityException::class,
            OtherException::class,
        ],
    ],
]));

Where should I implement this? In my user class? Or in the class I want to open and get the error? Or do I need to create a new class?

When someone tries to open the page without beeing logged in, then I want to show an errormessage and redirect the user to the login page.
But for now I get an error that the user object in my policy is null.

Sounds like you’re confused about how middleware works in general. Middleware - 4.x may help you out.

Yes you are right. I am completely confused about middleware and I was not aware that I have to do something.
I will read the documentation and hope it will be clearer then.
Thanks a lot.

ok, now I added some code.
In my Application.php in the function middleware, I added a Handler for the ForbiddenException:

->add(new AuthorizationMiddleware($this, [
                'unauthorizedHandler' => [
                    'className' => 'CustomRedirect',
                    'url' => '/users/login',
                    'queryParam' => 'redirectUrl',
                    'exceptions' => [
                        MissingIdentityException::class,
                        ForbiddenException::class,
                    ],
                    'custom_param' => true,
                ],
            ]));

In additional, I added a Custom Redirect

<?php
declare( strict_types = 1 );

namespace App\Middleware\UnauthorizedHandler;

use Authorization\Exception\Exception;
use Authorization\Middleware\UnauthorizedHandler\RedirectHandler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

class CustomRedirectHandler extends RedirectHandler {
    public function handle( Exception $exception, ServerRequestInterface $request, array $options = [] ): ResponseInterface {
        $response = parent::handle( $exception, $request, $options );
        $request->getFlash()->error( 'You are not authorized to access that location' );
        return $response;
    }
}

I checked it with some debug statement, the file will be loaded and the function handle will be called.
But the uncaught Exception is still on my page.
What is wrong?

Ahhhh,
I got it.
I missed to add the use statement in the Application.php

use Authorization\Exception\ForbiddenException;

Now the exception is catched.
Only thing is to get redirected. Because this

'url' => Router::url('/users/login),

redirects me to localhost/users/login
Instead of localhost/myProject/users/login

I think I have to adjust something in router.
But I am not sure.

You could try 'url' => ['controller' => 'Users', 'action' => 'login'] and see if it resolves it correctly for you.

Unfortunatelly not.

Argument #1 ($haystack) must be of type string, array given

try using a string URL instead of an array for this kind of scenario.

I remember having a similar problem due to the fact, that the router has not been setup at that point and therefore not being able to convert the URL array to the corresponding array

Well, that’s what he was doing, but it wasn’t working. :frowning:

Seems that this is a known problem. I found some Threads here.
https://discourse.cakephp.org/t/handling-forbidden-exception-for-request-authorization-middleware/6708
https://discourse.cakephp.org/t/redirect-to-last-visited-page-after-authorization-fail/10598