Dit is de symptoomgerichte oplossingspagina. Wil je eerst snappen waaróm een login redirect loop überhaupt ontstaat, lees dan WordPress login redirect loop: waarom dit gebeurt. Dat artikel legt het cookie-rondje uit en wat elke oplossing op deze pagina eigenlijk oplost. Dit artikel gaat ervanuit dat je het symptoom al herkent en nu gewoon de stappen wilt.
Hoe ziet de loop eruit
Je vult je gebruikersnaam en wachtwoord in op wp-login.php. De pagina knippert even en een fractie van een seconde later sta je weer op wp-login.php. Geen "wachtwoord fout"-melding. Geen zichtbare foutmelding. Soms zie je wp-login.php?redirect_to=%2Fwp-admin%2F in de adresbalk staan. Soms geeft de browser het op en toont ERR_TOO_MANY_REDIRECTS. Hoe dan ook: je wachtwoord klopt, het dashboard laadt nooit en het formulier zelf vertelt je niet waarom.
Dit gebeurt pas nadat je op "Inloggen" klikt. Krijg je juist een zichtbare foutmelding in het formulier, dan heb je een ander probleem. Begin dan bij waarom je niet kunt inloggen in WordPress en pak de account-tak.
Meest voorkomende oorzaken, op volgorde van waarschijnlijkheid
Vijf oorzaken dekken vrijwel elke echte login redirect loop die ik op WordPress 6.x tegenkom. Ze staan op volgorde van hoe vaak ze het daadwerkelijke probleem blijken te zijn, en dat is ook de volgorde waarin je ze wilt controleren.
WP_HOMEenWP_SITEURLkomen niet overeen met de URL waar de browser op staat. De site is naar HTTPS verhuisd, of het domein is gewijzigd, en de database heeft nog de oude waarde. De auth-cookie wordt geschreven voor de ene hostnaam en de browser stuurt de volgende request naar een andere. Veruit de meest voorkomende oorzaak, en vrijwel altijd het gevolg van een recente migratie.- De site staat ingesteld op
www.example.commaar de gebruiker landt opexample.com(of andersom). Strikt genomen een variant van de eerste oorzaak, maar wel apart noemen: een redirect op serverniveau kaatst de browser heen en weer tussen de twee hostnamen, en de auth-cookie gaat verloren bij die sprong. FORCE_SSL_ADMINstaat aan, maar de server merkt niet dat hij achter HTTPS draait. Een Cloudflare-, nginx- of load-balancer-proxy termineert TLS en praat plain HTTP met WordPress. De WordPress-functieis_ssl()kijkt naar$_SERVER['HTTPS']en naar de serverpoort, en níet naarX-Forwarded-Proto. Zonder extra configuratie denkt WordPress dus dat de request HTTP is en forceert een redirect naar HTTPS, die de proxy weer oplevert, en de cookie belandt op het verkeerde schema.COOKIE_DOMAINstaat hardgecodeerd op een domein dat niet klopt. Een hardening-gids, een oude migratie of een copy-paste van een andere site heeft eendefine('COOKIE_DOMAIN', ...)inwp-config.phpachtergelaten die niet meer overeenkomt met de werkelijkheid. De browser laat de cookie dan gewoon vallen bij de volgende request.- Een plugin zet
WP_HOMEruntime. Sommige redirect-, multilingual- of staging-plugins overschrijvenWP_HOMEenWP_SITEURLvia een filter alshome_urlofsite_url. Die override komt te laat om nog invloed te hebben op de cookie-write, dus de auth-cookie wordt geschreven voor de ene host en de rest van de pagina draait alsof WordPress op een andere staat.
Voordat je iets aanpast: sluit de twee triviale gevallen even uit. Dat zijn oude cookies in je browser en een pagecache die de auth-cookie uit het antwoord strijpt.
Veilige pre-checks
Deze stappen doen niets kapot. Ze bevestigen dat je echt in een login-loop zit en niet in een van de foutmeldingen die erop lijken.
Check 1: zit je wel in de login-loop en niet in een front-end-loop? Open de homepage in een incognitovenster. Cirkelt die homepage óók en zie je ERR_TOO_MANY_REDIRECTS, dan ligt het probleem aan de voorkant en hoort het in Too Many Redirects in WordPress. Laadt de homepage prima en bounced alléén wp-login.php je terug, dan zit je in het juiste artikel.
Check 2: sluit stale browser-state uit. Open een verse incognito-sessie met alle extensies uit. Probeer daar in te loggen. Werkt dat wel, dan zat het probleem in je lokale browser-state en ben je klaar. Blijft de loop bestaan, dan zit het probleem op de server.
Check 3: kijk naar de site-URL in de database. Kun je bij phpMyAdmin of een database-client? Voer dan deze query uit:
SELECT option_value FROM wp_options WHERE option_name IN ('siteurl', 'home');
Schrijf beide waarden op. Ze moeten exact gelijk zijn, inclusief het protocol en de www-prefix. Verschillen ze, dan speelt oorzaak 1 of 2. Zijn ze gelijk maar staat de browser op een andere hostnaam, dan speelt oorzaak 2.
Check 4: staat er een proxy voor je site? Open een willekeurige pagina in een incognitovenster en kijk in de developer tools naar de response-headers. Zie je server: cloudflare, een x-amz-cf-id-header of via:-entries die een CDN noemen, dan zit je achter een proxy die TLS termineert en dan speelt oorzaak 3 mee.
Oplossing 1: WP_HOME en WP_SITEURL goedzetten na een HTTPS- of domeinwissel
Dit is de oplossing voor de meest voorkomende oorzaak. Kom je niet meer in wp-admin, dan kun je de waarden niet via het instellingenscherm aanpassen, dus overschrijf je ze in wp-config.php: die heeft voorrang op de database. Beide constanten staan beschreven in de wp-config-referentie.
Open wp-config.php via SFTP of de bestandsbeheerder van je control panel. Voeg boven de regel /* That's all, stop editing! Happy publishing. */ dit toe:
// Forceer de juiste site-URL na een HTTPS-migratie.
// Vervang jouwsite.nl door het echte domein waar de browser op staat.
define('WP_HOME', 'https://jouwsite.nl');
define('WP_SITEURL', 'https://jouwsite.nl');
Sla het bestand op. Wis vervolgens de cookies voor je site in de browser (dit is belangrijk: oude cookies van de vorige hostnaam blokkeren de nieuwe anders). Probeer opnieuw in te loggen.
Verifieer of het werkt. Je zou het WordPress-dashboard moeten bereiken en erin moeten blijven. Refresh de pagina even: blijf je ingelogd, dan is het cookie-rondje gezond. Word je bij de refresh alsnog terug naar wp-login.php gestuurd, dan staan de constanten goed maar verstoort iets anders het rondje nog. Dat is meestal oorzaak 3 of 4.
Let op. Zodra de loop is opgelost, ga je in wp-admin naar Instellingen -> Algemeen en zorg je dat siteurl en home overeenkomen met wat je net in wp-config.php hebt gezet. De constanten zijn een noodrem, geen permanent huis. Laat je ze voor altijd in wp-config.php staan, dan moet elke volgende URL-wijziging op twee plekken gebeuren in plaats van één.
Oplossing 2: www versus apex-URL rechttrekken
Staat in de database https://example.com maar belandt je browser op https://www.example.com (of precies andersom), dan is er een redirect op serverniveau of DNS-niveau die www tussen login en dashboard toevoegt of weghaalt. De cookie wordt voor de ene host geschreven en teruggestuurd op een request naar de andere.
Kies één canonical host. De meeste moderne sites kiezen tegenwoordig voor apex (example.com zonder www) omdat dat korter en schoner is, maar beide kan prima, zolang het maar consistent is.
Pas wp-config.php aan zodat hij matcht met de canonical:
define('WP_HOME', 'https://example.com');
define('WP_SITEURL', 'https://example.com');
Zorg daarna dat de server de andere hostnaam naar de canonical toe redirect, en niet andersom. Check de redirect-regels in .htaccess en elke DNS- of CDN-forwarding. De redirect moet in één sprong: bezoek https://www.example.com, krijg een 301 naar https://example.com, klaar. Geen heen-en-weer.
Verifieer of het werkt. Open een incognitovenster, ga naar https://www.example.com/wp-login.php (mét www, ook al is apex de canonical) en log in. Je zou eenmalig naar https://example.com/wp-admin/ moeten worden doorgestuurd en dan in het dashboard moeten landen. Refresh je de pagina, dan blijf je ingelogd. Blijft de adresbalk na het inloggen tussen www.example.com en example.com wisselen, dan zit er nog ergens een tegenstrijdige redirect en blijft de loop terugkomen.
Oplossing 3: FORCE_SSL_ADMIN laten werken achter een reverse proxy
Zit je achter Cloudflare, een load balancer of een andere fronting-proxy die TLS termineert, en staat FORCE_SSL_ADMIN op true, dan merkt WordPress soms niet dat de oorspronkelijke request HTTPS was. Hij forceert dan een redirect naar de HTTPS-versie, de proxy geeft die request vervolgens als plain HTTP door, en de schema-detectie herstelt zich daarna niet. De auth-cookie belandt op het verkeerde schema.
De fix bestaat uit twee delen. Eerst in wp-config.php: vertrouw de X-Forwarded-Proto-header die de proxy meestuurt. Zet dit boven elke define die met site-URLs werkt, én boven de WordPress bootstrap:
// Vertel WordPress dat de oorspronkelijke request HTTPS was wanneer
// die via een reverse proxy binnenkomt die TLS upstream heeft getermineerd.
if (
!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])
&& $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https'
) {
$_SERVER['HTTPS'] = 'on';
}
Ten tweede: controleer of je proxy de X-Forwarded-Proto: https-header ook daadwerkelijk meestuurt. Bij Cloudflare gebeurt dat automatisch. Voor nginx vóór Apache moet je in de upstream-configuratie proxy_set_header X-Forwarded-Proto $scheme; hebben staan. Bij een load balancer controleer je de listener-configuratie.
Verifieer of het werkt. Open een incognitovenster, log in, kom in het dashboard. Refresh daarna. Je blijft ingelogd. Kaats je bij de refresh alsnog terug naar wp-login.php, dan stuurt de proxy geen X-Forwarded-Proto mee, óf de snippet staat onder code die $_SERVER['HTTPS'] al had uitgelezen.
Niet doen: FORCE_SSL_ADMIN uitzetten als "oplossing". Het is verleidelijk om gewoon define('FORCE_SSL_ADMIN', false); te zetten en ermee klaar te zijn. Dat stopt de loop, maar laat je admin-login aan de binnenkant van de proxy onversleuteld op applicatieniveau, wat precies het hele punt van FORCE_SSL_ADMIN ondermijnt. Fix de schema-detectie netjes.
Oplossing 4: een hardgecodeerde COOKIE_DOMAIN weghalen of corrigeren
Open wp-config.php via de bestandsbeheerder van je hosting control panel of via SFTP en zoek naar COOKIE_DOMAIN (gebruik Ctrl+F of Cmd+F in de editor).
Als je SSH-toegang hebt:
grep -n COOKIE_DOMAIN /pad/naar/wordpress/wp-config.php
Zie je iets als define('COOKIE_DOMAIN', '.example.com'); en draait je huidige site op een ander domein, dan is dát je loop. In een single-site WordPress heb je COOKIE_DOMAIN eigenlijk nooit nodig. Haal de regel gewoon helemaal weg en laat WordPress de default (leeg) gebruiken, wat neerkomt op "whatever host de browser aan het praten is". Voor 99% van alle installaties is dat precies goed.
Heb je COOKIE_DOMAIN wél nodig (bijvoorbeeld voor een multisite met een specifieke subdomein-strategie), zorg dan dat de waarde exact klopt. .example.com met een punt ervoor is geldig en dekt subdomeinen. example.com zonder punt dekt alléén de exacte hostnaam.
Verifieer of het werkt. Sla wp-config.php op, wis de cookies voor je site in de browser en probeer in te loggen. Je blijft ingelogd nadat het dashboard laadt, en ook na een refresh. Blijft de loop, dan is COOKIE_DOMAIN niet het probleem en ga je door naar oorzaak 5.
Oplossing 5: voorkomen dat een plugin WP_HOME runtime zet
Dit komt minder vaak voor, maar is wel pijnlijk: elke andere fix oogt namelijk correct. Een plugin (meestal een redirect-manager, een meertalige plugin met een domein per taal, of een staging-workflow plugin) haakt in op home_url of site_url en herschrijft de return-waarde. De auth-cookies zijn dan al lang geschreven, dus de cookie staat voor de ene host en de rest van de pagina draait als op een andere.
Om dit te testen schakel je alle plugins uit door de plugin-map te hernoemen. Open de bestandsbeheerder van je hosting control panel of een SFTP-client, navigeer naar wp-content en hernoem de map plugins naar plugins_off.
Als je SSH-toegang hebt:
mv wp-content/plugins wp-content/plugins_off
Probeer opnieuw in te loggen. Is de loop weg, dan is een plugin de boosdoener. Hernoem de map terug naar plugins (via de bestandsbeheerder of SFTP, of mv wp-content/plugins_off wp-content/plugins via SSH).
Hernoem daarna binnen wp-content/plugins elke submap één voor één met een suffix als _off, probeer na elke hernoeming opnieuw in te loggen, en de plugin die bij hernoemen de loop fixt is de dader. Let extra op WPML, Polylang, Redirection en elke staging- of domain-mapping-plugin.
Verifieer of het werkt. Met de schuldige plugin uitgeschakeld: log in, refresh, klik wat rond in wp-admin. Blijft alles werken, dan is de plugin bevestigd. Je vervolgstap is de plugin netjes herconfigureren (de meeste hebben ergens een "site URL"-instelling die exact moet matchen met WP_HOME) of vervangen door iets dat de core-URL-functies niet overschrijft.
Basale terugvaloplossing: cookies, incognito en plugins uit
Klopt geen van de vijf specifieke oorzaken? Dan loop je in deze volgorde even de basis door. Elke stap kost hooguit een minuut en samen vangen ze de long-tail-gevallen die ik hierboven niet heb genoemd.
- Wis de cookies voor je site in de browser. Niet je hele browsergeschiedenis, alleen de cookies voor dat ene domein. Herlaad
wp-login.phpen probeer het nog eens. Dit fixt het geval waarin een dode cookie van gisteren de nieuwe nog blokkeert. Krijg je op de loginpagina juist een "Cookies zijn geblokkeerd"-melding in plaats van een stille loop, dan heb je een ander symptoom te pakken: lees dan cookies zijn geblokkeerd of worden niet ondersteund in WordPress. - Test in een andere browser. Kaatst Chrome je in de loop maar werkt Firefox prima, dan zit het probleem lokaal in je browser (een extensie, een gecachte redirect of een strict privacy-profiel) en niet op de server.
- Test incognito met alle extensies uit. Zelfde idee, maar dan specifiek voor extensies.
- Check of een pagecache de auth-cookie uit de response haalt. Sommige cachingplugins en vrijwel alle CDN-pagecaches hebben een regel die cookies op gecachte responses negeert of strijpt. Wordt
wp-adminzelf vanuit de cache geserveerd, dan komt de auth-cookie er nooit uit. De fix iswp-adminenwp-login.phptoevoegen aan de cache-bypass van de plugin of het CDN.
Helpt dit nog niks, dan is het probleem specifiek genoeg dat remote diagnose onbetrouwbaar wordt. Tijd voor escalatie.
Wanneer escaleren
Ben je alle oorzaken doorlopen en blijft de loop? Vraag dan om hulp met het volgende lijstje alvast verzameld. Een host of een WordPress-specialist kan zonder deze info weinig, en het alvast verzamelen scheelt minstens één rondje heen-en-weer.
- De exacte URL waar je op belandt na het inloggen (kopieer de volledige URL uit de adresbalk op het moment dat je wordt teruggekaatst)
- De waarden van
siteurlenhomeuitwp_options(uit de SQL van Check 3) - De inhoud van
wp-config.php, met database-credentials weggelakt. Met name: elkedefinedieWP_HOME,WP_SITEURL,COOKIE_DOMAIN,FORCE_SSL_ADMINof$_SERVER['HTTPS']noemt - Of de site achter Cloudflare, een load balancer of een andere proxy staat
- De volledige plugin-lijst (een screenshot van Plugins -> Geïnstalleerde plugins of de output van
wp plugin listals je WP-CLI hebt) - De WordPress-versie, PHP-versie en de naam van de host
- De browser en versie die je test, en of de loop ook in een tweede browser gebeurt
- Een notitie van welke van de vijf oplossingen op deze pagina je al hebt geprobeerd en wat daar uit kwam
Wil je WordPress laten loggen wat er gebeurt, zet dan debug logging aan via wp-config.php (WP_DEBUG-documentatie):
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
Het log belandt in wp-content/debug.log. Reproduceer de loop één keer en voeg de laatste regels van dat bestand bij je escalatie.
Voorkomen dat de loop terugkomt
Een paar gewoontes houden vrijwel elke herhaling van deze loop buiten de deur.
- Kies één canonical hostnaam en dwing die af op de webserver, niet in WordPress. Kies apex of
www, kieshttps, en laat één redirect op webserver-niveau al het andere daarheen sturen. - Zet
COOKIE_DOMAINnooit hard in een single-site installatie. De default (leeg) is voor bijna iedereen de juiste waarde, en hardcoden is precies hoe de meeste loops ná een migratie ontstaan. - Update bij een HTTPS-migratie of domeinwijziging altijd zowel
wp-config.phpals dewp_options-waarden in dezelfde actie. Een oude waarde in de database achterlaten is wat de mismatch veroorzaakt. - Staat je site achter een proxy, zet de
X-Forwarded-Proto-bridge dan in één keer goed. Zet de snippet uit Oplossing 3 vanaf dag één inwp-config.phpen je loopt oorzaak 3 nooit meer tegen het lijf. - Test het inlogproces na elke migratie, TLS-certificaatwissel of plugin-update die iets met redirects doet. Het kost tien seconden en het is de goedkoopste manier om dit symptoom eerder te vinden dan een echte gebruiker.