Проверка Google reCAPTCHA в Nginx с использованием njs

опубликовано

server.conf:

js_import recaptcha from /path/to/recaptcha.js;
js_var $grc_cookie_name "grc";

upstream backend {
    server 127.0.0.1:12345;
}

server {
    
    location /check {
        internal;
        js_content recaptcha.check;
    }

    location / {
        auth_request /check;
        error_page 403 = /auth;
        proxy_pass http://backend;
    }

    location /auth/ {
        proxy_pass http://backend;
    }
}

server {
    listen 127.0.0.1:12345;
    
    root /path/to/root/;
}

recaptcha.js:

const check = (req) => {
    const cookie_name = req.variables.grc_cookie_name || 'grc'
    const cookies = req.headersIn.Cookie
    let code = 403
    if (typeof cookies === 'string' && cookies.indexOf(`${cookie_name}=`) !== -1) {
        // any additional logic
        code = 200
    }
    req.return(code)
}

export default {
    check,
}

/auth/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script async src="https://www.google.com/recaptcha/api.js"></script>
    <script>
        const grc_cookie_name = 'grc'
        function my_callback(id) {
            // any additional logic
            const date = new Date()
            date.setTime(date.getTime() + 365 * 24 * 3600 * 1000)
            document.cookie = `${grc_cookie_name}=1; expires=${date.toGMTString()}; path=/`
            location.replace('/')
        }
    </script>
</head>
<body>
    <div class="g-recaptcha" data-sitekey="key" data-callback="my_callback"></div>
</body>
</html>

Аналогичную проверку куки можно делать без njs используя map, однако использование njs позволяет реализовать решение в более гибком виде.