You can use signatures with Nexmo when both sending and receiving SMS messages. When sending, you generate a signature to send with your message. When receiving, the incoming webhook will include the signature and all the fields you need to generate the signature in your application to verify that the two signatures match.
You use a signature to:
- Verify that a request originates from a trusted source
- Ensure that the message has not been tampered with en-route
- Defend against interception and later replay
To send a message with a signature, you will need to use the
SIGNATURE_SECRET instead of your
API_SECRET when sending the message. You can find the signature secret and choose which signing algorithm to use by visiting the dashboard. The default algorithm is'MD5 hash' and we also support
SHA-256 HMAC and
Nexmo strongly recommends you use one of our client libraries to generate or validate signatures. If you can't do this for some reason, you can generate and validate signatures yourself, but this can be complicated and potentially error-prone. Refer to the section on manually generating signatures.
The process for sending a signed message is as follows:
- Create a signed request to send an SMS.
- Check the response codes and ensure that you sent the request correctly.
- Your message is delivered to the handset. The user's handset returns a delivery receipt.
- (optional) If you requested signed delivery receipts and inbound messages, you will want to validate the signature for each incoming request.
It is possible to require that all outgoing SMS use message signing. Contact email@example.com to enable or disable this setting on your account.
In order to verify the origin of incoming webhooks to your SMS endpoint, you can enable message signing for incoming messages - contact firstname.lastname@example.org to request incoming messages be accompanied by a signature. With this setting enabled, the webhooks for both incoming SMS and delivery receipts will include a
sig parameter. Use the other parameters in the request with your signature secret to generate the signature and compare it to the signature that was sent. If the two match, the request is valid.
Contact support to enable message signing on your account: email@example.com
It is highly recommended that you use your Nexmo library's existing functionality for generating and validating signatures. If you aren't using a library with this functionality, you'll need to generate the signature yourself. The technique is slightly different if are generating an 'MD5 hash' signature or one of the HMAC signatures.
If you're generating a signature: Add the current timestamp to the parameters list with the key
timestamp. This should be an integer containing the number of seconds since the epoch (this is sometimes also known as UNIX time)
If you're validating a signature from Nexmo: Remove the
sig parameter before generating your signature, and use the
timestamp provided in the request parameters.
- Loop through each of the parameters, sorted by key
- For every value in the parameter list, replace all instances of
=with an underscore
- Generate a string consisting of
&akey=value&bkey=value. Note that there is an ampersand
&at the start of the string!
At this point, the process for hash and HMAC will differ, so use the "Step 2" section that fits your needs:
- Add an ampersand
&and the signature secret to the end of the string. It should now look something like this:
- Now run the string through an md5 hash function and convert the resulting bytes to a string of hexadecimal digits. This is your MD5 hash signature, and should be added to the HTTP parameters of your request as the
- Create an HMAC generator with your desired algorithm and your signature secret as the key.
- Now run the string through an hmac generator and convert the resulting bytes to a string of hexadecimal digits. This is your HMAC signature, and should be added to the HTTP parameters of your request as the
sigparameter (e.g. for PHP this looks like
hash_hmac($algorithm, $data, $secret)).
Bear in mind that although you changed the parameter values while generating the signature, the values passed as HTTP parameters should be unchanged when sending those parameters to the SMS API.
Here are some tips and pitfalls to look out for when working with signed messages.
If the message isn't sent as expected, check the response for any error codes that were returned. This will usually give you more detail on what to do next.
If the text being sent includes any special characters such as
& (ampersand) or
= (equals), then these need to be replaced in the text used to create the signature.
A general approach would be:
- Detect that the text includes
- Create a version of the text that uses
_(underscore) in place of these special characters.
- Use the sanitised version of the text to create the signature.
The original text can be still be sent/received, the character replacements are only needed to generate the signature.