CodeIgniter Forums

Full Version: Reply Error Interception
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Today's brainteaser:  I have a situation where the server returns a 403 error to users.

I wish to somehow intercept these and display a friendly "have a nice life" response instead of sending only the 403 header, which users' browser simply seem to swallow (I've only checked this on FF so far, which quietly disposes of the errors, giving the impression the site has become unresponsive (I suspect most of the other browsers would follow suit)).

It was seasonably easy to redirect 404's and 500's inside CI... and I already have an ErrorDocument 403 redirection in the .htaccess file that sends 403 errors generated by user's trying to get directory access to the 404 page (which seems to work nicely)… yet, when a 403 error is generated by CI giving a user the finger... the only way the user can tell is via the server's response header (and the unresponsive page), which the average user would not be any the wiser about.

I'd be grateful if someone could please point me in a sensible direction.

Thanks,
Gary
Anyone...?
Maybe you can create a custom exception? I’m not sure if that would do what you’re trying to accomplish: https://codeigniter4.github.io/userguide...exceptions
Thanks Includebeer... I did start having a look at doing this, and although it was easy enough to find and change for a similar problem (for 429 response used by the Throttle class, which is in the App folder), when it comes to 403s (which are returned for the csrf filter), all I can find is what looks like the csrf form insertion functions in form_helper.php and Common.php and the place where is thrown SYSTEMPATH/Security\Exceptions\SecurityException.php, which you'll note are all in the system directory and I'm reluctant- for a couple of reasons- to fiddle with).
(04-12-2020, 12:30 PM)Gary Wrote: [ -> ]Thanks Includebeer... I did start having a look at doing this, and although it was easy enough to find and change for a similar problem (for 429 response used by the Throttle class, which is in the App folder), when it comes to 403s (which are returned for the csrf filter), all I can find is what looks like the csrf form insertion functions in form_helper.php and Common.php  and the palce where is thrown SYSTEMPATH/Security\Exceptions\SecurityException.php, which you'll note are all in the system directory and I'm reluctant- for a couple of reasons- to fiddle with).

Definitely don't mess with the system directory. But you can override or extends a system class in your own app: https://codeigniter4.github.io/userguide...re-classes

Maybe you could extend the Security class and just override the CSRFVerify() function to handle the exception like you want:
PHP Code:
public function CSRFVerify(RequestInterface $request)
{
...
    
// Do the tokens exist in both the _POST/POSTed JSON and _COOKIE arrays?
    
if (! isset($CSRFTokenValue$_COOKIE[$this->CSRFCookieName]) || $CSRFTokenValue !== $_COOKIE[$this->CSRFCookieName]
    ) 
// Do the tokens match?
    
{
        
/*** Do something else here, throw your own exception? ***/
        
throw SecurityException::forDisallowedAction();
    }
...

Thanks for the lead Includebeer, it appears to be exactly what I’m looking for.

I’ve implemented it pretty much verbatim from the https://codeigniter4.github.io/userguide...asses.html link (so it looks identical to your suggested code)... and also read the bit about the "Replacing Core Classes" immediately above in the link (which is “nearly identical with one exception”)… however, because I can't get my extended class explicitly called/loaded it obviously won’t work- after all my experimenting, I’ve still not been able to successfully modify the appropriate Service to load my new class in place of the class it’s extending

So my questions are now:
1) how do I force my new Security class extension to be loaded whenever PHP starts processing a request
2) once I get it loaded will the original one (being extended) also be automatically loaded because of my replacement USE’ing the original and/or explicitly extending it?

As a side-line experiment, I’ve also looked at possibly only extending/replacing forDisallowedAction(), which is the code invoked by the CSFR exception… however, being a noob, I’m not sure how to go about extending/replacing an in implementation that’s declared as: “class SecurityException extends FrameworkException implements ExceptionInterface”, especially when I can’t get the (apparently more basic) extending of a normal function working.

Code:
<?php namespace App\Controllers;    // CodeIgniter\Security;

    use CodeIgniter\HTTP\RequestInterface;
    use CodeIgniter\Security\Exceptions\SecurityException;
    use CodeIgniter\Security\Security;

    class Security extends Security {   // CodeIgniter\Security\Security\Security

        // TRIED:
  // public function __construct()
        // {
        //      parent::__construct();
        // }

        //--------------------------------------------------------------------

        public function CSRFVerify(RequestInterface $request)
        {
            // If it's not a POST request we will set the CSRF cookie

            ...

            // Do the tokens exist in both the _POST/POSTed JSON and _COOKIE arrays?
            if (! isset($CSRFTokenValue, $_COOKIE[$this->CSRFCookieName]) || $CSRFTokenValue !== $_COOKIE[$this->CSRFCookieName]
            ) // Do the tokens match?
            {
                // --- inserted notification start ---
                Echo('CSRF error exception insert');
                // --- inserted notification end ---

                // throw SecurityException::forDisallowedAction();
            }

            // We kill this since we're done and we don't want to pollute the _POST array
            ...

            return $this;
        }
I never tried it but my understanding is you create a security() service in app/Config/service.php and load you own class instead of the system class. Copy the one from the “official” service and change it to load your class: https://github.com/codeigniter4/CodeIgni...s.php#L714
Thanks Includebeer, I had another look at it this evening, after a couple of beverages.

Somehow things seemed to look and work better... and it is/was working- not sure exactly what the problem was... perhaps a missing "\" in one of the paths somewhere (?)

However, afterward getting it working, I found that some of my other code was also throwing the same SecurityException::forDisallowedAction() exceptions, so I tried to do the (almost) identical overriding for the forDisallowedAction() (which isn't a service?) and couldn't seem to override the static forDisallowedAction() implementation. As best I can see, I'd have to make a tiny mod to the CI system code, if I wanted to do the change/insertion into the final FINAL output.