Laravel Public Routing - Bypass CSRF and CORS

By default, all routes in Laravel require CSRF and CORS protection, which makes obvious sense. Occasionally, we need to bypass that for specific routes in your application; here's how I did it.


At TheReverseCalculator.com, I needed the forms to be accessible from websites outside of the base domain, since that's how the whole application works. So first I started off by modifying the RouteServiceProvider this way:

    /**
     * Define the routes for the application.
     *
     * @return void
     */
    public function map()
    {
        $this->mapApiRoutes();
        $this->mapWebRoutes();
        $this->mapPublicRoutes();
    }

    ...

    /**
     * Define the "public" routes for our application
     *     These routes circumvent all the csrf checks;
     *     they are served outside of application domain.
     */
    protected function mapPublicRoutes()
    {
        Route::group([
            'middleware' => 'public',
            'namespace' => $this->namespace,
        ], function($router) {
            require base_path('routes/public.php');
        });
    }

This allows us to have a new file called public.php in the routes folder where we can store all of our publicly-accessible routes. These routes, and only these routes, circumvent all the domain protections, so we definitely need to be careful what we allow in these controllers.

There are two pieces that get referenced above that need to be created: the routes/public.php file (obviously), and a new middleware called public. Head over to app/Http/Kernel.php and reference the middleware there:

    'public' => \App\Http\Middleware\AllowAccessFromAnywhere::class

and then create the middleware, like this:

<?php

namespace App\Http\Middleware;

use Closure;

class AllowAccessFromAnywhere
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        return $next($request)
            ->header('Access-Control-Allow-Origin', '*')
            ->header('Access-Control-Allow-Headers', 'Content-Type, Accept, X-Requested-With, Origin')
            ->header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
    }
}

So the middleware disables the CORS built-in to Laravel. One big thing to notice is the 'Access-Control-Allow-Methods' line: TheReverseCalculator needs to have access to GET and POST, but not PUT, DELETE, etc. We'll set this to limit routes to only what's absolutely necessary.

...and that's it! Any routes added to routes/public.php file bypass any domain protection to be accessible from anywhere. Obviously be very careful with this, but if you have a website that needs public access, it's a quick and easy way to enable it.

Validate a form with Google Recaptcha and Javascript

If you work with the web, chances are you've run across Google's Recaptcha. You know, the "click to prove you're not a robot" stuff. It's pretty ubiquitous, and even though it's very well documented, there's one case that came up today that bears mentioning: submitting a form directly to an outside service instead of validating it yourself. It's a pretty simple little piece of code, but could easily be overlooked in the thousands of lines of documentation on the Recaptcha software.

So without further ado, code:

<form action="outside-service-url">
    <div id="g-recaptcha"></div>
    <input type="submit" id="submit" disabled value="Submit" />
</form>

The form requires a submit button, obviously; make sure the button starts as disabled so the user can't submit the form until they've validated the captcha. Obviously for more sophisticated users this might require a bit more work to make sure they don't directly edit your code and submit, but for most cases this should work just fine.

<script src='https://www.google.com/recaptcha/api.js?onload=recaptchaLoadCallback&render=explicit' async defer></script>

Next, somewhere at the bottom of the page, include the google recaptcha script. The onload parameter is crucial: it allows us to trigger a callback when the script gets loaded so we can load up and configure out recaptcha exactly the way we want it.

Underneath that, add another script block with the following:

// When the recaptcha is validated, run the following callback
var recaptchaVerifyCallback = function() {
    // Enable the submit button.
    document.getElementById('submit').disabled = false;
}

// This callback gets run when the recaptcha loads.
var recaptchaLoadCallback = function() {
    grecaptcha.render('g-recaptcha', {
        'sitekey': 'your_site_key',
        'callback': recaptchaVerifyCallback
    });
}

This is where we create the actual recaptcha block in our code. We're explicitly rendering it so we can also provide the success callback. After the user clicks the button, it immediately calls the recaptchaVerifyCallback so that we can update the input to actually work and submit the form. Simple right?

Finally, it's probably a good idea to update the UI to reflect the changes we just made; make sure you add in a little CSS that will do something like:

input[type=submit]:disabled {
    background-color: #999;
    cursor: not-allowed;
}

Easy! Obviously you could do a lot more with this. Submitting forms to an internal URL that you can control makes things easier, but if you just have a quick site that needs to submit to an external form, it's a quick and easy way that gives you recaptcha support for most users.

Foundation and Wordpress - Responsive Images

I've been building a lot of my recent WordPress client sites in Foundation, specifically JointsWP because it's just so damn easy to build fast and it works really well straight out of the box. Granted, it doesn't look much like the original 'theme' when I get done with it.

While I was out searching for a solution for implementing responsive images in WordPress, I found... well, nothing, actually. Interchange is a cool feature, but it was a bit tricky to get implemented to show the WordPress featured images. So I made it. Here you go:

https://gist.github.com/joshrainwater/69b94e5169f7252bc1cd

NOTE: This specific use case has different form factors for a grid-based thumbnail layout, and the featured image sizes for the top of posts. Hence the two different entry points to the same function.