Validate Token (With Private Key)
Validate MTCaptcha Success Token
A Verified-Token will be created once a user is verified via captcha. This token must be checked on the server side using the corresponding PrivateKey to ensure its validity. The standard approach is to use the CheckToken API, but for more customized and network-sensitive use cases, the token can also be decrypted directly on the server side.
Getting the Token
This Verified-Token can be found commonly via:
- HTML hidden input form with name
mtcaptcha-verifiedtoken
:
<input type='hidden' name='mtcaptcha-verifiedtoken' … />
and can also be found via
- Javascript method
mtcaptcha.getVerifiedToken()
- part of the status callback argument via verified-callback (see JS Callbacks for more details)
function mtcaptchaVerifiedCallback( status ) {
console.log( status.verifiedToken );
}
console.log( status.verifiedToken ); }
Token Constraints
Each verifiedToken is normally valid for a few minutes, and can only be verified once via the CheckToken API to prevent replay attacks.
After you get the verifiedToken, you need to check it within the time limit to ensure the token is still valid. The MTCaptcha javascript widget will insure at least 50 seconds is available for the server to verify.
CHECKTOKEN API
HTTP METHOD: GET
Parameters:
- privatekey : The shared PrivateKey secret between your server and MTCaptcha. (Required)
- token : The VerifiedToken string. (Required)
eg : https://service.mtcaptcha.com/mtcv1/api/checktoken?privatekey=&token=
NOTE : To insure the PrivateKey is kept secret this API should only be called from server side.
For server-side environments that require explicit firewall ACLs for outbound traffic, see: Use the service2.mtcaptcha.com Domain API URL below, which allows for explicit IP addresses
URL: https://service2.mtcaptcha.com/mtcv1/api/checktoken
The IPs to white list are:
- 52.214.217.96
- 35.165.137.56
- 13.228.176.242
- 13.234.26.164
- 18.228.103.117
- 18.162.183.0
- 47.52.173.54
- 8.210.253.57
CHECKTOKEN API Response
The API response is a JSON object, sample responses below
{
"success": true,
"tokeninfo": {
"v": "1.0",
"code": 201,
"codeDesc": "valid:captcha-solved",
"tokID": "ae1e60a1e249c217cb7b05c4dba8dd0d",
"timestampSec": 1552185983,
"timestampISO": "2019-03-10T02:46:23Z",
"hostname": "some.example.com",
"isDevHost": false,
"action": "",
"ip": "10.10.10.10"
}
}
Sample Failure Response
{
"success": false,
"fail_codes": [
"token-expired"
],
"tokeninfo": {
"v": "1.0",
"code": 201,
"codeDesc": "valid:captcha-solved",
"tokID": "25eff0c56a227781408a95a053c36b65",
"timestampSec": 1552185729,
"timestampISO": "2019-03-10T02:42:09Z",
"hostname": "some.example.com",
"isDevHost": false,
"action": "",
"ip": "10.10.10.10"
}
}
CHECKTOKEN API Response Fields
Field | Description |
---|---|
success | true if the token is valid. false otherwise. |
fail_codes | The code (reason) for validation failure. This field will only exist if success: false . |
tokeninfo | JSON object with the token metadata decrypted. This field may not exist on certain failures. |
tokeninfo.v | The version of the token format, should be "1.0" . |
tokeninfo.code | The tokencode describing the method of verification. For a full list of possible tokencode codes, see below. |
tokeninfo.codeDesc | The tokencode description. For a full list of possible codes and descriptions, see below. |
tokeninfo.tokID | The unique GUID for the token, 128bits Hex/Base16 encoded. |
tokeninfo.timestampSec | The timestamp when the token was created, in Unix epoch time (in seconds). |
tokeninfo.timestampISO | The time stamp when the token was created, in ISO 8601 UTC format. |
tokeninfo.hostname | The hostname of the webpage the captcha was served under. |
tokeninfo.isDevHost | ‘true’ if the hostname matches ‘development domains’ configured for the site. |
Tokeninfo.action | Tokeninfo.action The action string used on initialization of the captcha. If not defined defaults to empty string. |
tokeninfo.ip | The client IP of the user. In String format. |
Response Token Info Codes & Descriptions
The codes for tokeninfo.code and tokeninfo.codeDesc are listed below:
Token Codes | Code Description | Description |
---|---|---|
201 | valid:captcha-solved | Verified via the captcha challenge was solved. |
211 | valid:ip-whitelisted | Verified via the client coming from an IP matching the IP whitelist for the site. |
212 | valid:low-friction | Verified via the client deemed low risk, and the site has low-friction invisible captcha enabled. |
301 | valid-test:captcha-solved-via-testkey | Verified via the TestKey (for automated testing). |
Response Fail Codes
Possible response fail_codes
Fail Codes | Description |
---|---|
token-expired | The token has expired. Commonly 120 seconds. Can be longer depending on captcha type. |
token-duplicate-cal | The token has been checked already, and thus should not be used. |
bad-request | General error for unexpected bad/malformed requests. |
missing-input-privatekey | The parameter privatekey is missing |
missing-input-token | The parameter token is missing |
invalid-privatekey | The privatekey provided is not valid |
invalid-token | The token is not valid |
invalid-token-faildecrypt | The token is not valid and failed during decryption |
privatekey-mismatch-token | The token and the privatekey do not match. i.e., the token was created from another sitekey. |
expired-sitekey-or-account | The sitekey/privatekey is no longer valid due to expiration or account closure. |
CHECKTOKEN API Optional Parameters
For custom use cases, the CheckToken API supports these optional parameters.
Parameter | Parameter Description |
---|---|
tokenExpireMiniSec | Sets the minimum expiration time (TTL) in seconds for the Verified-Token, which effectively allows the token to be valid for longer than the default 60–120 seconds. This custom expiration duration will only be applied if it is larger than the default MTCaptcha expiration time. The value must be an integer and max allowed value of 1200 (20 minutes). Example: tokenExpireMiniSec=300 . |
tokenDuplicateCallMaxCount | Sets the duplicate call threshold from the default of a single (one) CheckToken call per token to multiple. The value must be an integer and max allowed value of 20. Example: tokenDuplicateCallMaxCount=5 . |
The use of these optional parameters will add the fields token_callcount
and token_agesec
to the CheckToken API response.
{
"success": ...,
"token_callcount": 3,
"token_agesec": 9,
"tokeninfo": {
...
}
}
CHECKTOKEN via Server Side Decryption (Without External API Call)
The standard and easiest method of validating the MTCaptcha verifiedToken
is via the checktoken API, but you can decrypt and decode the token directly on the server side without making any external API calls to mtcaptcha.com. You will need the site PrivateKey and the ability to calculate the MD5 hash and decrypt with AES cipher. Additional checks for timeout and single use will be needed on the server side to ensure proper security.
Decrypt Sample Code
The sample Java code to decrypt and decode the token can be found at the GitHub project here:
https://github.com/mtcaptcha-public/MTCaptcha-Direct-Token-Decryption/
Verified-Token String Structure
"v1([MTCaptcha CheckSum], [Customer Checksum], [Sitekey], [Random Seed], [Encrypted TokenInfo])"
Example: v1(2f03cc7d,1058dfde,MTPublic-hal9000uJ,34715559cd42d3955114303c925c3582,kSdkIYA.....qOCQ**)
Token Parts
Token Part | Example Value |
---|---|
[MTCaptcha CheckSum] | 2f03cc7d |
[Customer Checksum] | 1058dfde |
[Sitekey] | MTPublic-hal9000uJ |
[Random Seed] | 34715559cd42d3955114303c925c3582 |
[Encrypted TokenInfo] | kSdkIYA.....qOCQ** |
Verified Token Decryption Logic
Step | Logic |
---|---|
[CalculatedCustomerCheckSum] | = MD5([Privatekey] + [SiteKey] + [Random Seed] + [Encrypted TokenInfo]).toHexLowercase().substring(0, 8) |
[EncryptedTokenInfoBinary] | = URLSafeBase64.decode([Encrypted TokenInfo].replace("*", "=")); |
[SingleUseDecryptionKey128bit] | = MD5([Privatekey] + [Random Seed]); |
[AesIV] | = [SingleUseDecryptionKey128bit] |
[DecryptedTokenInfoJson] | = AES.decrypt("CBC/PKCS5Padding", [SingleUseDecryptionKey128bit], [AesIV], [EncryptedTokenInfoBinary]); |
Textual Encoding / Decoding Format: UTF-8