Dolibarr/dolibarr · error

Access to a page that needs a token (constant…

Error message

Access to a page that needs a token (constant CSRFCHECK_WITH_TOKEN is defined) is refused by CSRF protection in main.inc.php. Token not provided.

What it means

Dolibarr's CSRF protection refuses requests without a valid token. This variant fires when the target page declares CSRFCHECK_WITH_TOKEN, meaning it unconditionally demands a token; since none was supplied, access is refused with HTTP 403.

Solutions

  1. Generate links/forms with the token: use $form->showFormConfirm, newToken() or append '?token='.newToken() to the URL
  2. Re-open the page from within the Dolibarr UI so a fresh session token is issued
  3. If a page wrongly declares CSRFCHECK_WITH_TOKEN, remove that define from your custom page
  4. Check that proxies don't strip query parameters

Example fix

// before
header('Location: ./card.php?action=confirm&id=15');
// after
header('Location: ./card.php?action=confirm&id=15&token='.newToken());
Defensive patterns

Strategy: fallback

Validate before calling

if (empty($_REQUEST['token'])) { die('CSRF token missing: regenerate the link via the UI'); }

Prevention

When it happens

Trigger: GET/POST to a page whose code has define('CSRFCHECK_WITH_TOKEN', 1) (or called via GETPOST check with the constant) without the 'token' URL/POST parameter or with an invalid/absent session token.

Common situations: Building links to action pages by hand instead of via dolBuildUrl/Form helpers; token lost when copying a URL into an email/bookmark (token bound to session and expired); proxies or HTML sanitizers stripping the token parameter; custom module pages missing newToken().

Related errors


AI-assisted analysis of Dolibarr/dolibarr@598aa4bdad (2026-09-14). Data as JSON: /api/errors/ee204b57a5b0eddf. Report an issue: GitHub.

Appendix: source

Thrown at htdocs/main.inc.php:440

	if (
		(!empty($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') ||
		$sensitiveget ||
		GETPOSTISSET('massaction') ||
		((GETPOSTISSET('actionlogin') || GETPOSTISSET('action')) && defined('CSRFCHECK_WITH_TOKEN'))
	) {
		// If token is not provided or empty, error (we are in case it is mandatory)
		if (!GETPOST('token', 'alpha') || GETPOST('token', 'alpha') == 'notrequired') {
			top_httphead();
			if (GETPOSTINT('uploadform')) {
				dol_syslog("--- Access to ".(empty($_SERVER["REQUEST_METHOD"]) ? '' : $_SERVER["REQUEST_METHOD"].' ').$_SERVER["PHP_SELF"]." refused. File size too large or not provided.");
				$langs->loadLangs(array("errors", "install"));
				print $langs->trans("ErrorFileSizeTooLarge").' ';
				print $langs->trans("ErrorGoBackAndCorrectParameters");
			} else {
				http_response_code(403);
				if (defined('CSRFCHECK_WITH_TOKEN')) {
					dol_syslog("--- Access to ".(empty($_SERVER["REQUEST_METHOD"]) ? '' : $_SERVER["REQUEST_METHOD"].' ').$_SERVER["PHP_SELF"]." refused by CSRF protection (CSRFCHECK_WITH_TOKEN protection) in main.inc.php. Token not provided.", LOG_WARNING);
					print "Access to a page that needs a token (constant CSRFCHECK_WITH_TOKEN is defined) is refused by CSRF protection in main.inc.php. Token not provided.\n";
				} else {
					dol_syslog("--- Access to ".(empty($_SERVER["REQUEST_METHOD"]) ? '' : $_SERVER["REQUEST_METHOD"].' ').$_SERVER["PHP_SELF"]." refused by CSRF protection (POST method or GET with a sensible value for 'action' parameter) in main.inc.php. Token not provided.", LOG_WARNING);
					print "Access to this page this way (POST method or GET with a sensible value for 'action' parameter) is refused by CSRF protection in main.inc.php. Token not provided.\n";
					print "If you access your server behind a proxy using url rewriting and the parameter is provided by caller, you might check that all HTTP header are propagated (or add the line \$dolibarr_nocsrfcheck=1 into your conf.php file or MAIN_SECURITY_CSRF_WITH_TOKEN to 0";
					if (getDolGlobalString('MAIN_SECURITY_CSRF_WITH_TOKEN')) {
						print " instead of " . getDolGlobalString('MAIN_SECURITY_CSRF_WITH_TOKEN');
					}
					print " into setup).\n";
				}
			}
			die;
		}
	}

	$sessiontokenforthisurl = (empty($_SESSION['token']) ? '' : $_SESSION['token']);
	// TODO Get the sessiontokenforthisurl into an array of session token (one array per base URL so we can use the CSRF per page and we keep ability for several tabs per url in a browser)
	if (GETPOSTISSET('token') && GETPOST('token') != 'notrequired' && GETPOST('token', 'alpha') != $sessiontokenforthisurl) {
		dol_syslog("--- Access to ".(empty($_SERVER["REQUEST_METHOD"]) ? '' : $_SERVER["REQUEST_METHOD"].' ').$_SERVER["PHP_SELF"]." refused by CSRF protection (invalid token), so we disable POST and some GET parameters - referrer=".(empty($_SERVER['HTTP_REFERER']) ? '' : $_SERVER['HTTP_REFERER']).", action=".GETPOST('action', 'aZ09').", _GET|POST['token']=".GETPOST('token', 'alpha'), LOG_WARNING);

View on GitHub (pinned to 598aa4bdad)