Access REST API to send SMS message

Scott Mankowitz 26 Reputation points
2022-03-13T04:18:41.61+00:00

I have the following code in PHP to send an SMS message:

    public static function send(array $phoneNumbers, string $message)  
    {  
        $body = [  
            'from' => config("azure.sms_phone_number"),  
            'message' => $message,  
            'smsRecipients' => array_map(fn ($num) => ['to' => $num], $phoneNumbers)  
        ];      
        $endpoint = parse_url(config("azure.sms_endpoint"));  
        $headers = [  
            'Date' => gmdate("D, d M y H:i:s T"),  
            'host' => $endpoint['host'],  
            'x-ms-content-sha256' => base64_encode[hash('sha256', json_encode($body), true)),  
        ];  
  
        $stringToSign = utf8_encode["POST\n" . $endpoint['path'] . "?" . $endpoint['query'] . "\n" . implode(";", array_values($headers)));  
  
        $headers['Authorization'] =  
            "SignedHeaders=" . implode(";", array_keys($headers)) .  
            '&Signature=' . base64_encode[hash_hmac('sha256', $stringToSign, base64_decode[config("azure.sms_key")), true));  
  
        $client = new Client();  
  
        $client->post(config("azure.sms_endpoint"), [  
            'headers' => $headers,  
            'body' => json_encode($body),  
            'debug' => true  
        ]);  
    }  
  

Based on https://learn.microsoft.com/en-us/azure/azure-app-configuration/rest-api-authentication-hmac. The problem is that when I run it, I get this error:

POST https://scotttestingsms.communication.azure.com/sms?api-version=2021-03-07` resulted in a `401 Unauthorized` response  
Azure Communication Services
Azure Communication Services
An Azure communication platform for deploying applications across devices and platforms.
1,234 questions
{count} vote

Accepted answer
  1. SnehaAgrawal-MSFT 22,706 Reputation points Moderator
    2022-03-16T04:18:05.853+00:00

    Update: The issue is resolved by correcting auth headers.

    Changed to this format: key:'Authorization', value: "HMAC-SHA256 SignedHeaders=date;host;x-ms-content-sha256&Signature=" + signature

    Updated code: Note: please replace in base64_encode text line [ with (

    public static function send(array $phoneNumbers, string $message)  
        {  
            $body = [  
                'from' => config("azure.sms_phone_number"),  
                'message' => $message,  
                'smsRecipients' => array_map(fn ($num) => ['to' => $num], $phoneNumbers)  
            ];  
      
            $endpoint = parse_url(config("azure.sms_endpoint"));  
      
            $headers = [  
                'Date' => gmdate("D, d M Y H:i:s T"),  
                'host' => $endpoint['host'],  
                'x-ms-content-sha256' => base64_encode [hash('sha256', json_encode($body), true)),  
            ];  
      
            $stringToSign = utf8_encode(implode("\n", [  
                "POST",  
                $endpoint['path'] . "?" . $endpoint['query'],  
                implode(";", array_values($headers))  
            ]));  
      
            $headers['Authorization'] = implode("&", [  
                "HMAC-SHA256 SignedHeaders=" . implode(";", array_keys($headers)),  
                'Signature=' . base64_encode [hash_hmac('sha256', $stringToSign, base64_decode [config("azure.sms_key")), true))  
            ]);  
      
            $client = new Client();  // <-- this is guzzle$response = $client->post(config("azure.sms_endpoint"), [  
                'headers' => $headers,  
                'json' => $body  
            ]);  
      
        }  
    

    Referred documentation: Tutorial - Sign and make requests to ACS' SMS API with Postman - An Azure Communication Services tutorial | Microsoft Learn

    With few trial and error changes and it worked!

    Thanks for reaching us through multiple channels and sharing the suggested resolution on Similar SO link

    Let us know if further query.

    0 comments No comments

2 additional answers

Sort by: Most helpful
  1. SnehaAgrawal-MSFT 22,706 Reputation points Moderator
    2022-03-14T11:27:37.827+00:00

    Thanks for asking question! If I am understanding right you are using client generated hash- based message authentication code as authentication method,
    Could you please confirm the below mentioned prerequisites and Steps.

    Please ensure you have:

    • Your Azure Communication Services Access Key
    • Your Azure Communication Service Endpoint
    • The URL Path and HTTP Verb that you're calling
    • A development environment, which can generate HMACs, SHA256 hashes, and Base64 operations.

    Steps:

    1. Specify the UTC timestamp for the request in either the x-ms-date header or in the standard HTTP Date header.
    2. Hash the HTTP request body using the SHA256 algorithm then pass it, with the request, via the x-ms-content-sha256 header.
    3. Construct the string to be signed by concatenating the HTTP Verb (for example, GET or PUT), HTTP request path, and values of the Date, Host and, x-ms content-sha256 HTTP headers in the following format:

    VERB + "\n"
    URLPathAndQuery + "\n"
    DateHeaderValue + ";" + HostHeaderValue + ";" + ContentHashHeaderValue

    1. Generate an HMAC-256 signature of the UTF-8 encoded string that you created in the previous step. Next, encode your results as Base64. You also need to Base64-decode your access key. Use the following format (shown as pseudo-code):

    Signature=Base64(HMAC-SHA256(UTF8(StringToSign), Base64.decode(<your_access_key>)))

    1. Specify the Authorization header as follows:

    Authorization="HMAC-SHA256 SignedHeaders=date;host;x-ms-content-sha256&Signature=<hmac-sha256-signature>"

    For more details check this official document link:

    Let us know if issue remains or further query on this.


  2. GenixPRO 116 Reputation points
    2022-03-17T05:17:19.973+00:00

    @Scott Mankowitz can I ask if you're using SMS service in US or outside U.S. We were told it's only available in US, UK & Canada. Not sure if the service is now available in other geo's.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.