Making your script work with security tokens in cPanel & WHM

What is a security token?
“Security token” URLs were added in cPanel & WHM 11.25 as a security measure, and they were enabled by default in version 11.28. They help combat a common type of attack called a Cross-Site Request Forgery (XSRF).

So, what does a “security token” look like? Take, for example, this URL:
https://example.com:2087/i/love/cpanel

With security tokens enabled, this would become:
https://example.com:2087/cpsessYYYYYYY/i/love/cpanel

In that example, cpsessYYYYYYY is the token unique to that logged-in user on that browser. (You can learn more about security tokens in cPanel & WHM by reading our Security Tokens white paper.) In order for your custom script to work with cPanel & WHM, every URL involved needs to be compatible with the security token.

Creating security token-compatible URLs

Fortunately, it is very easy to do!

The token is available in the environment variable ‘cp_security_token’.

If security tokens are not in use, ‘cp_security_token’ will be an empty string.

If security tokens are in use, ‘cp_security_token’ will be, in terms of the above example: /cpsessYYYYYYY

Note the preceding slash! Since the variable has that slash, the examples will work whether cPanel & WHM has security tokens enabled or disabled.

  • Here’s how you’d use it in Perl code that calls one of our API URLS.
    Simply change this:

    my $APIurl = "http://127.0.0.1:2087/xml-api/$url";

    to this:

    my $APIurl = "http://127.0.0.1:2087$ENV{'cp_security_token'}/xml-api/$url";

  • Here’s how you might use it in JavaScript for, say, an AJAX call.
    First, make it available to your JavaScript. For example:

    print <<"END_SECURITY_TOKEN_JAVASCRIPT";

    if ( !("CPANEL" in window) ) CPANEL = {};
    CPANEL.security_token = "$ENV{'cp_security_token'}";

    END_SECURITY_TOKEN_JAVASCRIPT

    Next, make your URLs compatible by changing this:

    var ajaxURL = '/3rdparty/ZZZ/zzz.cgi';

    to this:

    var ajaxURL = CPANEL.security_token + '/3rdparty/ZZZ/zzz.cgi';

cPanel

The web hosting industry's most reliable management solution since 1997. With our first-class support and rich feature set, it's easy to see why our customers and partners make cPanel & WHM their hosting platform of choice. For more information, visit cPanel.net.

5 responses to “Making your script work with security tokens in cPanel & WHM”

  1. Bernard says:

    I’m sorry for being so ignorant, but I can’t work out where and how you would use these ‘codes’. I have multiple websites and open Awstats via CPanel for all of them on a daily basis using group launch. Previously all I had to do is hit the Enter key for each one and they opened, now I have to paste the password for each site. I would love a simple way to disable these annoying tokens. Can you help, please?

  2. Eduard Ignatov says:

    I use this code to generate new email box via cpanel. For previous versions of Cpanel we have no need in security token and for now we need it by default. What I’m doing wrong with security token generation or why email box could not be created. whm hash is correct 100%.
    I see $ENV{‘cp_security_token’} with variable $ENV but if we insert it in the php code we will get an error that this variable is not defined!
    Look forward to hearing from you.
    Thanks

    $cpanel_username = $this->config->item(‘cpanel_username’);
    $cpanel_domain = $this->config->item(‘cpanel_domain’);
    $case_email = ‘case’ . $case_number;
    $case_email_password = $this->config->item(‘zenfile_default_email_password’);
    $url = ‘67.139.36.73:2087{“cp_security_token”}’;
    $hash = ‘whm hash here for access’;
    $query = ‘https://’.$url.’/json-api/cpanel?cpanel_jsonapi_user=’ . $cpanel_username . ‘&cpanel_jsonapi_module=Email&cpanel_jsonapi_func=addpop&cpanel_jsonapi_apiversion=1&arg-0=’ . $case_email . ‘&arg-1=’ . $case_email_password . ‘&arg-2=0&arg-3=’ . $cpanel_domain;
    $curl = curl_init();
    $header[0] = “Authorization: WHM root:” . preg_replace(“‘(r|n)'”, “”, $hash);
    curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    # Create Curl Object
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
    # Allow self-signed certs
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
    # Allow certs that do not match the hostname
    curl_setopt($curl, CURLOPT_TIMEOUT, 30);
    curl_setopt($curl, CURLOPT_HEADER, 0);
    # Do not include header in output
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    # Return contents of transfer on curl_exec
    # set the username and password
    curl_setopt($curl, CURLOPT_URL, $query);
    # execute the query
    $result = curl_exec($curl);
    curl_close($curl);

  3. Jeremy says:

    Howdie do,

    Can you explain how you would do this for a PHP script?

    I currently have:

    $query =”https://(IP)/$ENV{‘cp_security_token’}/xml-api/createacct?username=$hookuser&domain=$hookdomain&password=$hookpassword”;

  4. @mariorodriguez  says:

    Glad the information was helpful to you. Appreciate the feedback!

  5. stefan says:

    Thank you very much! really helpful this detailed explanation!

Leave a Reply