{"id":5684,"date":"2026-06-20T03:05:24","date_gmt":"2026-06-20T03:05:24","guid":{"rendered":"https:\/\/www.cmsgalaxy.com\/blog\/?p=5684"},"modified":"2026-06-20T03:05:26","modified_gmt":"2026-06-20T03:05:26","slug":"master-troubleshooting-guide-flarum-google-login-oauth-issue-on-cpanel-apache-with-wordpress-root-site","status":"publish","type":"post","link":"https:\/\/www.cmsgalaxy.com\/blog\/master-troubleshooting-guide-flarum-google-login-oauth-issue-on-cpanel-apache-with-wordpress-root-site\/","title":{"rendered":"Master Troubleshooting Guide: Flarum Google Login OAuth Issue on cPanel\/Apache with WordPress Root Site"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">1. Environment Overview<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This guide is based on a real troubleshooting case where:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>WordPress is installed at the root domain:<br><code>https:\/\/www.truereviewnow.com<\/code><\/li>\n\n\n\n<li>Flarum is installed under a subdirectory:<br><code>https:\/\/www.truereviewnow.com\/forum<\/code><\/li>\n\n\n\n<li>Server path:<br><code>\/home\/ireviewed\/public_html<\/code><\/li>\n\n\n\n<li>WordPress root path:<br><code>\/home\/ireviewed\/public_html<\/code><\/li>\n\n\n\n<li>Flarum path:<br><code>\/home\/ireviewed\/public_html\/forum<\/code><\/li>\n\n\n\n<li>Flarum config URL:<code>'url' => 'https:\/\/www.truereviewnow.com\/forum',<\/code><\/li>\n\n\n\n<li>Google OAuth callback URL:<code>https:\/\/www.truereviewnow.com\/forum\/auth\/google<\/code><\/li>\n\n\n\n<li>OAuth extension:<code>fof\/oauth<\/code><\/li>\n\n\n\n<li>Web server:<code>Apache \/ cPanel<\/code><\/li>\n\n\n\n<li>Apache domain log:<code>\/usr\/local\/apache\/domlogs\/truereviewnow.com.ireviewed.in-ssl_log<\/code><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">2. Original Problem<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Google login was enabled for Flarum using FoF OAuth.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The login started correctly:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;www.truereviewnow.com\/forum\/auth\/google\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Flarum redirected the user to Google successfully.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But after Google authentication, the browser returned to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;www.truereviewnow.com\/forum\/auth\/google?state=...&amp;iss=https%3A%2F%2Faccounts.google.com&amp;code=...&amp;scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+openid&amp;authuser=7&amp;prompt=consent\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Instead of completing login, the page showed:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>404 Error - Page Not Found\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The page was actually a <strong>WordPress 404 page<\/strong>, not a Flarum error.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">3. Key Finding<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">The main issue was <strong>not<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Google redirect URI mismatch<\/li>\n\n\n\n<li>Flarum config URL mismatch<\/li>\n\n\n\n<li>FoF OAuth not installed<\/li>\n\n\n\n<li>Wrong <code>.htaccess<\/code> only<\/li>\n\n\n\n<li>Browser cookies only<\/li>\n\n\n\n<li>Session storage only<\/li>\n\n\n\n<li>Google client secret only<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The final root cause was:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ModSecurity OWASP CRS rule 930120 was blocking the Google OAuth callback.\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Google sends this scope:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;www.googleapis.com\/auth\/userinfo.profile\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The string:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>userinfo.profile\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">contains:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.profile\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">ModSecurity interpreted <code>.profile<\/code> as a possible attempt to access a Unix\/Linux local file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>~\/.profile\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">So ModSecurity rule <code>930120<\/code>, which detects Local File Inclusion attacks, blocked the callback before normal application handling.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Because the block happened before Flarum could process the request, Apache\/cPanel\/WordPress behavior resulted in a WordPress-style 404 response.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">4. Symptoms Observed<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">4.1 OAuth Start Route Worked<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -skI https:\/\/www.truereviewnow.com\/forum\/auth\/google\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Expected\/observed good output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>HTTP\/2 302\nx-powered-by: Flarum\nset-cookie: flarum_session=...\nlocation: https:\/\/accounts.google.com\/o\/oauth2\/v2\/auth?...\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Meaning:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/forum\/auth\/google is handled by Flarum correctly.\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">4.2 Short Callback Worked<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -sk \"https:\/\/www.truereviewnow.com\/forum\/auth\/google?state=test&amp;code=test\" | head -n 5\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Expected\/observed output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>FoF\\OAuth\\Errors\\AuthenticationException: Invalid state\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This is a good result.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It means:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>The short callback reaches Flarum\/FoF OAuth.\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The error is expected because <code>state=test<\/code> is fake.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">4.3 Long Google Callback Failed<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -skI \"https:\/\/www.truereviewnow.com\/forum\/auth\/google?state=test&amp;iss=https%3A%2F%2Faccounts.google.com&amp;code=test&amp;scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+openid&amp;authuser=7&amp;prompt=consent\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Bad output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>HTTP\/2 404\nlink: &lt;https:\/\/www.truereviewnow.com\/wp-json\/&gt;; rel=\"https:\/\/api.w.org\/\"\ncontent-type: text\/html; charset=UTF-8\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">That <code>wp-json<\/code> header proves the response came from WordPress, not Flarum.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">4.4 Browser Callback Failed<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Apache log showed:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>GET \/forum\/auth\/google HTTP\/2.0\" 302\nGET \/forum\/auth\/google?state=...&amp;iss=https%3A%2F%2Faccounts.google.com&amp;code=...&amp;scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+... HTTP\/2.0\" 404 42117\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Meaning:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>OAuth start worked.\nGoogle returned correctly.\nThe callback with long scope parameter failed.\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">5. Important Misleading Clues<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">During troubleshooting, several things looked like possible causes but were not the final root cause.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5.1 <code>.htaccess<\/code> Looked Suspicious<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Because WordPress was installed at root and Flarum under <code>\/forum<\/code>, the first suspicion was that WordPress was hijacking Flarum pretty URLs.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This was partly valid because WordPress root <code>.htaccess<\/code> can catch subdirectory routes if not excluded correctly.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A normal WordPress rule like this can be dangerous for Flarum:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>RewriteCond %{REQUEST_FILENAME} !-f\nRewriteCond %{REQUEST_FILENAME} !-d\nRewriteRule . \/index.php &#91;L]\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">It can cause:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/forum\/auth\/google\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">to be handled by WordPress.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So <code>.htaccess<\/code> still had to be fixed, but it was not the only issue.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">5.2 Google Client Secret Looked Suspicious<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Changing\/regenerating the Google client secret did not fix the WordPress 404.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Why?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Because the callback was not even reaching Flarum in the failing case.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If the request does not reach Flarum\/FoF OAuth, the client secret does not matter yet.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">5.3 Flarum Session Looked Suspicious<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">OAuth uses a <code>state<\/code> parameter and server-side session.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A fake callback returned:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Invalid state\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">At first this looked like a session issue.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But a proper same-cookie\/same-state test proved the session was working.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">6. Proper Session\/State Test<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">This test verifies whether Flarum can save and read OAuth state.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd \/home\/ireviewed\/public_html\/forum\n\nrm -f \/tmp\/flarum_cookie.txt \/tmp\/flarum_headers.txt \/tmp\/flarum_callback_headers.txt \/tmp\/flarum_callback_body.txt\n\ncurl -sk \\\n  -c \/tmp\/flarum_cookie.txt \\\n  -D \/tmp\/flarum_headers.txt \\\n  https:\/\/www.truereviewnow.com\/forum\/auth\/google \\\n  -o \/dev\/null\n\nSTATE=$(grep -i \"^location:\" \/tmp\/flarum_headers.txt | sed -n 's\/.*&#91;?&amp;]state=\\(&#91;^&amp;]*\\).*\/\\1\/p' | tr -d '\\r')\n\necho \"STATE=$STATE\"\n\ncurl -sk \\\n  -b \/tmp\/flarum_cookie.txt \\\n  -D \/tmp\/flarum_callback_headers.txt \\\n  \"https:\/\/www.truereviewnow.com\/forum\/auth\/google?state=$STATE&amp;code=test\" \\\n  -o \/tmp\/flarum_callback_body.txt\n\ncat \/tmp\/flarum_callback_headers.txt\nhead -n 120 \/tmp\/flarum_callback_body.txt\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Expected result:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>FoF\\OAuth\\Errors\\AuthenticationException: invalid_grant\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This is good.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It means:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>State validation passed.\nSession is working.\nFlarum moved to token exchange.\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>invalid_grant<\/code> is expected because <code>code=test<\/code> is fake.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">7. Correct Root <code>.htaccess<\/code> for WordPress + Flarum<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Path:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/home\/ireviewed\/public_html\/.htaccess\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Backup first:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cp \/home\/ireviewed\/public_html\/.htaccess \/home\/ireviewed\/public_html\/.htaccess.bak.$(date +%F-%H%M)\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Recommended root <code>.htaccess<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># ==========================================================\n# ROOT .htaccess\n# WordPress: https:\/\/www.truereviewnow.com\n# Flarum   : https:\/\/www.truereviewnow.com\/forum\n# ==========================================================\n\nDirectoryIndex index.php\n\n&lt;IfModule mod_rewrite.c&gt;\nRewriteEngine On\n\n# Preserve Authorization header for PHP apps\nRewriteRule .* - &#91;E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]\n\n# ----------------------------------------------------------\n# Canonical redirects\n# ----------------------------------------------------------\n\n# Old domain -&gt; final canonical domain\nRewriteCond %{HTTP_HOST} ^(www\\.)?ireviewed\\.in$ &#91;NC]\nRewriteRule ^(.*)$ https:\/\/www.truereviewnow.com\/$1 &#91;R=301,L]\n\n# Non-www -&gt; www\nRewriteCond %{HTTP_HOST} ^truereviewnow\\.com$ &#91;NC]\nRewriteRule ^(.*)$ https:\/\/www.truereviewnow.com\/$1 &#91;R=301,L]\n\n# Force HTTPS\nRewriteCond %{HTTPS} off\nRewriteCond %{HTTP:X-Forwarded-Proto} !https &#91;NC]\nRewriteRule ^(.*)$ https:\/\/%{HTTP_HOST}\/$1 &#91;R=301,L]\n\n# ----------------------------------------------------------\n# Security\n# ----------------------------------------------------------\n\n# Block .git access\nRewriteRule (^|\/)\\.git(\/|$) - &#91;F,END]\n\n# ----------------------------------------------------------\n# IMPORTANT FLARUM FIX\n# Route \/forum\/* to Flarum BEFORE WordPress can catch it.\n# ----------------------------------------------------------\n\n# Block sensitive Flarum files from root level\nRewriteRule ^forum\/(\\.env|auth\\.json|composer\\.(json|lock)|config\\.php|flarum)$ - &#91;F,END]\nRewriteRule ^forum\/(storage|vendor)(\/.*)?$ - &#91;F,END]\nRewriteRule ^forum\/(.*\/)?\\.git(\/.*)?$ - &#91;F,END]\n\n# Route exact \/forum and \/forum\/ to Flarum\nRewriteRule ^forum\/?$ \/forum\/index.php &#91;QSA,END]\n\n# Serve real existing files\/folders under \/forum normally\nRewriteCond %{REQUEST_URI} ^\/forum(\/|$) &#91;NC]\nRewriteCond %{REQUEST_FILENAME} -f &#91;OR]\nRewriteCond %{REQUEST_FILENAME} -d\nRewriteRule ^ - &#91;END]\n\n# Route all other Flarum pretty URLs to Flarum index.php\nRewriteRule ^forum\/.*$ \/forum\/index.php &#91;QSA,END]\n\n&lt;\/IfModule&gt;\n\n# ----------------------------------------------------------\n# Block WordPress XML-RPC\n# ----------------------------------------------------------\n&lt;Files xmlrpc.php&gt;\n  Require all denied\n&lt;\/Files&gt;\n\n# Extra .git protection\nRedirectMatch 404 ^(.*\/)?\\.git+\n\n# BEGIN WordPress\n# The directives between \"BEGIN WordPress\" and \"END WordPress\"\n# are dynamically generated and should only be modified via WordPress filters.\n&lt;IfModule mod_rewrite.c&gt;\nRewriteEngine On\nRewriteRule .* - &#91;E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]\nRewriteBase \/\nRewriteRule ^index\\.php$ - &#91;L]\n\n# Extra safety: WordPress must never handle \/forum\nRewriteCond %{REQUEST_URI} !^\/forum(\/|$) &#91;NC]\n\nRewriteCond %{REQUEST_FILENAME} !-f\nRewriteCond %{REQUEST_FILENAME} !-d\nRewriteRule . \/index.php &#91;L]\n&lt;\/IfModule&gt;\n# END WordPress\n\n# php -- BEGIN cPanel-generated handler, do not edit\n&lt;IfModule mime_module&gt;\n  AddHandler application\/x-httpd-ea-php82 .php .php8 .phtml\n&lt;\/IfModule&gt;\n# php -- END cPanel-generated handler, do not edit\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Important note:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;END]\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">is stronger than:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;L]\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>[END]<\/code> stops rewrite processing completely for the current request. This helps prevent WordPress rules from catching Flarum routes in later rewrite passes.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">8. Correct Minimal Flarum <code>.htaccess<\/code><\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Path:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/home\/ireviewed\/public_html\/forum\/.htaccess\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Backup first:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cp \/home\/ireviewed\/public_html\/forum\/.htaccess \/home\/ireviewed\/public_html\/forum\/.htaccess.bak.$(date +%F-%H%M)\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Recommended minimal Flarum <code>.htaccess<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># ==========================================================\n# FORUM .htaccess\n# Flarum: https:\/\/www.truereviewnow.com\/forum\n# ==========================================================\n\nOptions -Indexes\nOptions -MultiViews\n\n&lt;IfModule mod_rewrite.c&gt;\n  RewriteEngine On\n  RewriteBase \/forum\/\n\n  # Preserve Authorization header\n  RewriteRule .* - &#91;E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]\n\n  # Protect sensitive files\/directories\n  RewriteRule (^|\/)\\.git(\/|$) - &#91;F,L]\n  RewriteRule ^\\.env$ - &#91;F,L]\n  RewriteRule ^auth\\.json$ - &#91;F,L]\n  RewriteRule ^composer\\.(lock|json)$ - &#91;F,L]\n  RewriteRule ^config\\.php$ - &#91;F,L]\n  RewriteRule ^flarum$ - &#91;F,L]\n  RewriteRule ^storage\/(.*)?$ - &#91;F,L]\n  RewriteRule ^vendor\/(.*)?$ - &#91;F,L]\n\n  # Flarum pretty URLs\n  RewriteCond %{REQUEST_FILENAME} !-f\n  RewriteCond %{REQUEST_FILENAME} !-d\n  RewriteRule ^ index.php &#91;QSA,L]\n&lt;\/IfModule&gt;\n\n&lt;IfModule mod_headers.c&gt;\n  RequestHeader unset Proxy\n&lt;\/IfModule&gt;\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">9. Why <code>.htaccess<\/code> Sanitizer Was Not the Final Fix<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">A sanitizer rule was considered:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>RewriteCond %{REQUEST_URI} ^\/forum\/auth\/google$ &#91;NC]\nRewriteCond %{QUERY_STRING} (^|&amp;)state=(&#91;^&amp;]+).*&amp;code=(&#91;^&amp;]+).*&amp;scope= &#91;NC]\nRewriteRule ^forum\/auth\/google$ \/forum\/auth\/google?state=%2&amp;code=%3 &#91;R=302,L,NE]\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The idea was to strip Google\u2019s extra parameters and keep only:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>state\ncode\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">But this did not solve the root problem because ModSecurity was blocking before normal rewrite processing could help.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So the sanitizer was removed.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">10. Final Root Cause: ModSecurity Rule 930120<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">The real blocked value was inside Google\u2019s callback query:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>scope=email profile https:\/\/www.googleapis.com\/auth\/userinfo.profile https:\/\/www.googleapis.com\/auth\/userinfo.email openid\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The problematic part:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>userinfo.profile\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">contains:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.profile\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">OWASP CRS rule <code>930120<\/code> flagged <code>.profile<\/code> as a possible Local File Inclusion attempt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This happened before the request reached Flarum.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">11. Final ModSecurity Fix<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">A server-level ModSecurity exclusion was created using cPanel userdata includes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">File:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/etc\/apache2\/conf.d\/userdata\/ssl\/2_4\/ireviewed\/truereviewnow.com.ireviewed.in\/modsec-flarum.conf\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Rule:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SecRule REQUEST_URI \"@beginsWith \/forum\/auth\/\" \\\n  \"id:1000001,phase:1,nolog,pass,ctl:ruleRemoveTargetById=930120;ARGS:scope\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This removes rule <code>930120<\/code> only for:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ARGS:scope\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">and only when the URI begins with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/forum\/auth\/\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This is a safe, narrow fix.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It does not disable ModSecurity globally.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It does not disable the LFI rule for WordPress.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It does not disable the LFI rule for all Flarum requests.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It only excludes the <code>scope<\/code> argument on Flarum OAuth callback routes.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">12. If Both SSL and Non-SSL vhosts Exist<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Also create the same file for standard non-SSL userdata if needed:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/etc\/apache2\/conf.d\/userdata\/std\/2_4\/ireviewed\/truereviewnow.com.ireviewed.in\/modsec-flarum.conf\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Same content:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SecRule REQUEST_URI \"@beginsWith \/forum\/auth\/\" \\\n  \"id:1000001,phase:1,nolog,pass,ctl:ruleRemoveTargetById=930120;ARGS:scope\"\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">13. Rebuild Apache Includes and Restart Apache<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">After creating userdata include files:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/scripts\/ensure_vhost_includes --user=ireviewed\n\/scripts\/restartsrv_httpd\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check syntax:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apachectl -t\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Expected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Syntax OK\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">14. Verify the ModSecurity Rule Is Loaded<\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>grep -R \"1000001\\|930120\\|ARGS:scope\" \/etc\/apache2\/conf.d\/userdata\/\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Expected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SecRule REQUEST_URI \"@beginsWith \/forum\/auth\/\" ...\nctl:ruleRemoveTargetById=930120;ARGS:scope\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">15. Verify Long Callback No Longer Goes to WordPress<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -skI \"https:\/\/www.truereviewnow.com\/forum\/auth\/google?state=test&amp;iss=https%3A%2F%2Faccounts.google.com&amp;code=test&amp;scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+openid&amp;authuser=7&amp;prompt=consent\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Bad output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>HTTP\/2 404\nlink: &lt;https:\/\/www.truereviewnow.com\/wp-json\/&gt;; rel=\"https:\/\/api.w.org\/\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Good output should not include:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>wp-json\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then run body test:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -sk \"https:\/\/www.truereviewnow.com\/forum\/auth\/google?state=test&amp;iss=https%3A%2F%2Faccounts.google.com&amp;code=test&amp;scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+openid&amp;authuser=7&amp;prompt=consent\" | head -n 5\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Good fake-test output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>FoF\\OAuth\\Errors\\AuthenticationException: Invalid state\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This means the long Google-style callback is reaching Flarum.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">16. Real Browser Test<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Watch OAuth logs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>LOG=\/usr\/local\/apache\/domlogs\/truereviewnow.com.ireviewed.in-ssl_log\ntail -f $LOG | grep --line-buffered \"\/forum\/auth\/google\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Open fresh private\/incognito browser:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;www.truereviewnow.com\/forum\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Click Google login.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Expected log flow:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>GET \/forum\/auth\/google HTTP\/2.0\" 302\nGET \/forum\/auth\/google?state=...&amp;iss=...&amp;code=...&amp;scope=... HTTP\/2.0\" 302\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Bad old flow:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>GET \/forum\/auth\/google?state=...&amp;code=...&amp;scope=... HTTP\/2.0\" 404 42117\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the <code>404 42117<\/code> disappears, ModSecurity issue is fixed.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">17. If Real Login Fails After ModSecurity Fix<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Once the callback reaches Flarum, new errors may appear.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">17.1 <code>Invalid state<\/code><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Meaning:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>The browser callback did not send the same Flarum session cookie used when OAuth started.\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Started from correct URL:<code>https:\/\/www.truereviewnow.com\/forum<\/code><\/li>\n\n\n\n<li>Not from:<code>https:\/\/truereviewnow.com\/forum http:\/\/www.truereviewnow.com\/forum https:\/\/ireviewed.in\/forum<\/code><\/li>\n\n\n\n<li>Clear cookies for:<code>truereviewnow.com www.truereviewnow.com ireviewed.in<\/code><\/li>\n\n\n\n<li>Try incognito.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Check cookie from OAuth start:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -skI https:\/\/www.truereviewnow.com\/forum\/auth\/google\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Expected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>set-cookie: flarum_session=...; Path=\/forum; Secure; HttpOnly; SameSite=Lax\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">17.2 <code>invalid_grant<\/code><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Meaning:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Google rejected the authorization code during token exchange.\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Common causes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Fake\/stale\/reused code<\/li>\n\n\n\n<li>Wrong client secret<\/li>\n\n\n\n<li>Redirect URI mismatch<\/li>\n\n\n\n<li>Time skew<\/li>\n\n\n\n<li>Code already used<\/li>\n\n\n\n<li>Old browser callback after regenerating secret<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Fixes:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Use fresh incognito.<\/li>\n\n\n\n<li>Re-save Google client ID and secret in Flarum.<\/li>\n\n\n\n<li>Confirm redirect URI exactly:<code>https:\/\/www.truereviewnow.com\/forum\/auth\/google<\/code><\/li>\n\n\n\n<li>Do not use trailing slash.<\/li>\n\n\n\n<li>Do not reuse old callback URL.<\/li>\n\n\n\n<li>Check server time:<code>date timedatectl<\/code><\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">17.3 <code>invalid_client<\/code><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Meaning:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Google Client ID or Client Secret is wrong.\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Fix:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Go to Google Cloud Console.<\/li>\n\n\n\n<li>Open the OAuth client.<\/li>\n\n\n\n<li>Regenerate client secret.<\/li>\n\n\n\n<li>Update Flarum Admin \u2192 FoF OAuth \u2192 Google.<\/li>\n\n\n\n<li>Save.<\/li>\n\n\n\n<li>Clear cache:<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>cd \/home\/ireviewed\/public_html\/forum\nphp flarum cache:clear\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">17.4 <code>redirect_uri_mismatch<\/code><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Meaning:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Google Console authorized redirect URI does not exactly match what Flarum sends.\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Correct value:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;www.truereviewnow.com\/forum\/auth\/google\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Wrong examples:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;truereviewnow.com\/forum\/auth\/google\nhttp:\/\/www.truereviewnow.com\/forum\/auth\/google\nhttps:\/\/www.truereviewnow.com\/forum\/auth\/google\/\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">18. Check Flarum Configuration<\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>cd \/home\/ireviewed\/public_html\/forum\ncat config.php\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Important:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>'url' =&gt; 'https:\/\/www.truereviewnow.com\/forum',\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">No trailing slash.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">19. Check FoF OAuth<\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>cd \/home\/ireviewed\/public_html\/forum\n\ncomposer show fof\/oauth\nphp flarum info | grep -i oauth\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Expected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>fof\/oauth\nfof-oauth enabled\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Enable if needed:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>php flarum extension:enable fof-oauth\nphp flarum cache:clear\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">20. Check Google OAuth Settings in Flarum<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">In Flarum Admin:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Admin \u2192 Extensions \u2192 FoF OAuth \u2192 Google\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Verify:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Client ID: present\nClient Secret: present\nHosted Domain: blank unless intentionally restricted\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If a Google secret was exposed, regenerate it.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">21. Check Flarum Logs<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Flarum logs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd \/home\/ireviewed\/public_html\/forum\nls -ltr storage\/logs\/\ntail -n 200 storage\/logs\/*.log\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Important note:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If no new Flarum log appears, the request may be blocked before Flarum, for example by:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ModSecurity<\/li>\n\n\n\n<li>Apache vhost config<\/li>\n\n\n\n<li>cPanel rule<\/li>\n\n\n\n<li>WordPress rewrite<\/li>\n\n\n\n<li>CDN\/WAF<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">22. Check Apache Access Logs<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Correct cPanel log path in this case:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/usr\/local\/apache\/domlogs\/truereviewnow.com.ireviewed.in-ssl_log\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Watch OAuth only:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>LOG=\/usr\/local\/apache\/domlogs\/truereviewnow.com.ireviewed.in-ssl_log\ntail -f $LOG | grep --line-buffered \"\/forum\/auth\/google\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Review previous attempts:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep \"GET \/forum\/auth\/google\" \/usr\/local\/apache\/domlogs\/truereviewnow.com.ireviewed.in-ssl_log | tail -n 30\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Important status codes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>302 = redirect \/ likely normal OAuth flow\n404 = likely WordPress or route not found\n403 = WAF\/ModSecurity\/security block\n500 = Flarum\/PHP exception\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">In this case, ModSecurity caused behavior that surfaced as WordPress-style 404.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">23. Check Apache Error Logs<\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>tail -n 200 \/usr\/local\/apache\/logs\/error_log\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For ModSecurity:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep -i \"930120\\|ModSecurity\\|userinfo.profile\\|\/forum\/auth\/google\" \/usr\/local\/apache\/logs\/error_log | tail -n 50\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Also check ModSecurity audit logs if enabled:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep -Rni \"930120\\|userinfo.profile\\|\/forum\/auth\/google\" \/var\/log\/apache2\/ \/usr\/local\/apache\/logs\/ 2&gt;\/dev\/null | tail -n 100\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">24. Check Apache Include Files<\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>apachectl -S\napachectl -t\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Find cPanel userdata includes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>find \/etc\/apache2\/conf.d\/userdata\/ -type f | sort\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Verify the Flarum ModSecurity exclusion:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep -R \"1000001\\|930120\\|ARGS:scope\" \/etc\/apache2\/conf.d\/userdata\/\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">25. File Permission Checks<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Flarum needs writable storage:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd \/home\/ireviewed\/public_html\/forum\n\nls -ld storage storage\/sessions storage\/cache storage\/logs\nfind storage -maxdepth 2 -type d -exec ls -ld {} \\;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Fix if needed:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd \/home\/ireviewed\/public_html\/forum\n\nmkdir -p storage\/sessions storage\/cache storage\/logs\nchown -R ireviewed:ireviewed storage\nchmod -R 775 storage\n\nphp flarum cache:clear\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Restrict config.php:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd \/home\/ireviewed\/public_html\/forum\n\nchown ireviewed:ireviewed config.php\nchmod 640 config.php\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">26. Debug Mode<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Enable temporarily:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>'debug' =&gt; true,\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd \/home\/ireviewed\/public_html\/forum\nphp flarum cache:clear\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Disable after fixing:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>'debug' =&gt; false,\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>php flarum cache:clear\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Never leave debug enabled on production.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">27. Clean Testing Procedure<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Use this exact sequence.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Confirm Flarum route<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -skI https:\/\/www.truereviewnow.com\/forum\/auth\/google\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Expected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>HTTP\/2 302\nx-powered-by: Flarum\nlocation: https:\/\/accounts.google.com\/...\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Confirm short fake callback<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -sk \"https:\/\/www.truereviewnow.com\/forum\/auth\/google?state=test&amp;code=test\" | head -n 5\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Expected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>FoF\\OAuth\\Errors\\AuthenticationException: Invalid state\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Confirm long Google-style fake callback<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -sk \"https:\/\/www.truereviewnow.com\/forum\/auth\/google?state=test&amp;iss=https%3A%2F%2Faccounts.google.com&amp;code=test&amp;scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+openid&amp;authuser=7&amp;prompt=consent\" | head -n 5\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Expected after ModSecurity fix:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>FoF\\OAuth\\Errors\\AuthenticationException: Invalid state\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Bad:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en-US\"&gt;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">or:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>wp-json\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Real browser test<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>LOG=\/usr\/local\/apache\/domlogs\/truereviewnow.com.ireviewed.in-ssl_log\ntail -f $LOG | grep --line-buffered \"\/forum\/auth\/google\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then try login.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">28. Final Security Notes<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">28.1 Rotate Google OAuth Secret<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If the Google OAuth client secret was pasted into chat, screenshots, logs, or shared with third-party tools, regenerate it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then update:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Flarum Admin \u2192 FoF OAuth \u2192 Google\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Clear cache:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd \/home\/ireviewed\/public_html\/forum\nphp flarum cache:clear\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">28.2 Protect config.php<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Flarum stores DB credentials in <code>config.php<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Recommended:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd \/home\/ireviewed\/public_html\/forum\nchmod 640 config.php\nchown ireviewed:ireviewed config.php\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">28.3 Do Not Disable ModSecurity Globally<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Do not use broad fixes like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SecRuleEngine Off\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Do not disable ModSecurity for the full domain.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Do not disable rule <code>930120<\/code> globally.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Use narrow exclusion:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ctl:ruleRemoveTargetById=930120;ARGS:scope\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">only for:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/forum\/auth\/\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">29. Final Diagnosis Summary<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">The issue looked like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Google OAuth \/ Flarum \/ .htaccess \/ WordPress routing problem\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">But the true root cause was:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ModSecurity OWASP CRS rule 930120 flagged Google OAuth's scope parameter because it contained userinfo.profile, which includes .profile.\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">That block prevented the long Google callback from reaching Flarum.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Short callbacks worked because they did not contain:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>scope=...userinfo.profile...\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The final fix was a narrow server-level ModSecurity exclusion:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SecRule REQUEST_URI \"@beginsWith \/forum\/auth\/\" \\\n  \"id:1000001,phase:1,nolog,pass,ctl:ruleRemoveTargetById=930120;ARGS:scope\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then rebuild Apache includes and restart Apache:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/scripts\/ensure_vhost_includes --user=ireviewed\n\/scripts\/restartsrv_httpd\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Finally disable Flarum debug mode after successful test.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">30. Golden Troubleshooting Lesson<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">When OAuth works for the start URL but fails only after provider callback, always compare:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>short fake callback\nlong real provider callback\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the short callback reaches the app but the long callback does not, inspect:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>WAF<\/li>\n\n\n\n<li>ModSecurity<\/li>\n\n\n\n<li>encoded URL values inside query string<\/li>\n\n\n\n<li>suspicious parameter names\/values<\/li>\n\n\n\n<li>provider-specific scopes<\/li>\n\n\n\n<li>Apache error\/audit logs<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">In this case, the entire issue came down to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>userinfo.profile\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">being misread as:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.profile\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">by a Local File Inclusion rule.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. Environment Overview This guide is based on a real troubleshooting case where: 2. Original Problem Google login was enabled for Flarum using FoF OAuth. The login&#8230; <\/p>\n","protected":false},"author":13,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-5684","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/posts\/5684","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/users\/13"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/comments?post=5684"}],"version-history":[{"count":1,"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/posts\/5684\/revisions"}],"predecessor-version":[{"id":5685,"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/posts\/5684\/revisions\/5685"}],"wp:attachment":[{"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/media?parent=5684"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/categories?post=5684"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/tags?post=5684"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}