CMS:USER_TOKEN

Outputs the security token (CSRF token) for a form that triggers a writing CMS:USER_* command.

(CMS:USER_TOKEN [parameter=value …])

Method: Modules\Record\RecordUser::cmsToken()

Parameters

Parameter Value Default Required Description
format "field" / "value" "field" field: hidden input field <input type="hidden" name="_token">, with the value masked by htmlspecialchars. value: only the token (for Ajax), unmasked.
set $set array index – The output is not printed, but stored in $set. The token is additionally always in $set['user_token'].
formguard true / false false true: additionally outputs a timestamp and an invisible honeypot field (form protection against robots).

Usage

The token prevents a foreign website from submitting forms in the name of your visitors (cross-site request forgery): signing in, registering, resetting a password, saving or deleting contributions, signing out, changing the shopping basket. These commands check the token. Without a valid token, they abort with a message (index token):

Command Checked
USER_LOGIN, USER_REGISTER, USER_PW, USER_INPUT, USER_2FA when submit is filled (not for sign-in by hash)
USER_LOGIN_CODE when submit or resend is set
USER_DELETE always
USER_LOGOUT always – with submit only if submit is filled
USER_BASKET for add, update and update_addon – not for load; without a valid token, only reading takes place

The token is held in a cookie. The first call on a page must therefore stand before any output – at the start of the template (or in the head include before <!doctype>), with set, so that nothing is output there. After that, write (CMS:USER_TOKEN) into every form that triggers one of these commands:

(CMS:USER_TOKEN set=token)
<?php $submit = $_POST['submit'] ?? ''; ?>
(CMS:USER_LOGIN container=members submit="$submit" successtemplate=u_welcome)
<!doctype html>
…
<form method="post">
  (CMS:USER_TOKEN)
  <input name="data[nickname]"> <input type="password" name="data[password]">
  <button name="submit" value="1">Sign in</button>
</form>

Form protection against robots

(CMS:USER_TOKEN formguard=true) additionally outputs a signed timestamp and a honeypot field that visitors do not see. Commands with formguard=true (CMS:USER_REGISTER, CMS:USER_PW, CMS:EMAIL) reject the form if the honeypot field is filled, or if the form was submitted faster than three seconds or later than one hour after it was served. The system administrator sets both times (user.formguard_min_seconds, formguard_max_seconds). For an individual form, formguard=5 on the command sets the minimum time to five seconds – for example for a long form that nobody completes within three seconds. This stops robots that fill in every form blindly – no captcha, no third-party service. The system administrator can additionally connect an external captcha (security.form_challenge); you then embed its widget yourself.

<form method="post">
  (CMS:USER_TOKEN formguard=true)
  …
</form>

For Ajax calls, send the token as the POST field _token or in the header X-Camindo-Token. A FormData object from a form with (CMS:USER_TOKEN) already contains it:

<script>
fetch('/0,basket_api', {
  method: 'POST',
  headers: { 'X-Camindo-Token': '(CMS:USER_TOKEN format=value)' },
  body: new URLSearchParams({ product: 42 })
});
</script>

If the first call comes too late, there is no token: in place of the field there is an HTML comment with a note, and the form fails with the message token.

The cookie (ucsrf) applies to all forms of the website and survives sign-in. It is not accepted in the query string (GET). Writing actions belong in POST forms.

The check can be switched off per command with csrf=false. The system administrator can switch it off globally with user.csrf = false. Both open the commands to foreign websites and are meant only for transitional periods.


← Overview

As of camindo CMS 9.1.3