A Shared Access Signature (SAS) is the primary means of authenticating a client when connecting to many Azure services. It is a (relatively) newer authentication scheme, replacing Access Control Service (ACS).
Even though SAS has been around for several years, the Azure SDK for PHP only supports ACS. There is an open issue to add SAS support to the SDK, but until that support is added, you will not be able to use the SDK if your Azure service does not have ACS enabled, and in the past few years, Microsoft has been defaulting services to not use ACS.
Real Life Example
For a recent project, I needed to send messages to an Azure Service Bus queue from PHP code. My initial approach was to use the Azure SDK for PHP, as unfortunately, the documentation did not make it clear the SDK does not support SAS authentication.
I did not discover this fact until I tried authenticating in my code and received an error that the host mynamespace-sb.accesscontrol.windows.net could not be found.
The accesscontrol.windows.net indicates the SDK was trying to use ACS. I could have used a PowerShell command to enable ACS authentication for my Service Bus, but since Microsoft is encouraging SAS over ACS, I opted to create my own SAS routine for PHP.
I found .NET code for generating the token on MSDN, but one important factor when translating this code to PHP is that the .NET HttpUtility.UrlEncode function returns the hexadecimal encodings as lowercase letters (e.g. %2f) whereas PHP UrlEncode uses uppercase letters (%2F). This doesn’t usually matter, but it does matter when using the output for a hashing function.
Solution
The following code will generate a Shared Access Signature that can be used with Service Bus (and probably other Azure services as well):
function lower_urlencode($str) {
return preg_replace_callback('/%[0-9A-F]{2}/',
function(array $matches) {
return strtolower($matches[0]);
}, urlencode($str));
}
function generateSharedAccessSignature($url, $policy, $key) {
$expiry = time() + 3600;
$encodedUrl = lower_urlencode($url);
$scope = $encodedUrl . "\n" . $expiry;
$signature = base64_encode(hash_hmac('sha256', $scope, $key, true));
return "SharedAccessSignature sig="
. lower_urlencode($signature)
. "&se=$expiry&skn=$policy&sr=$encodedUrl";
}
$url references the endpoint you are trying to access, so if you’re trying to post to a queue, it would be e.g. https://yournamespace.servicebus.windows.net/yourqueue/messages
$policy is the name of the Shared access policy you want to use. You configure these within the Azure:
So for example, if I’m trying to use send a message to a queue, I could use the above sendmessage policy.
$key is the key associated with the policy, you can use either the primary or secondary:
Use the string returned from the generateSharedAccessSignature function as the value for the Authorization HTTP header.
Conclusion
One of the great features of Azure platform services such as Service Bus is that they are not tightly coupled to the Microsoft stack. In this case, using the above code, it was easy to send messages to a Service Bus queue using PHP.
Learn more about our Microsoft Azure Cloud Solutions and Services.