javaazureservicebusshared-access-signatures

Azure Messaging Service Bus Error: Illegal connection string parameter: SharedAccessSignature sr


I am working with the Azure Messaging Service Bus Library version 7.10.0 on my project. I have created some integration tests to verify its functionality and with SaK authentication works like a charm, but with SaS I get the next error:

java.lang.IllegalArgumentException: Illegal connection string parameter name: SharedAccessSignature sr

IllegalArgumentException

/**
 * Creates a new Synchronous Service Bus receiver.
 * @param subscriptionName the name of the subscription to use.
 * @return Service Bus receiver client for topics and subscriptions.
 * @throws AuthorizationException if the token is invalid or has expired when the creation request is done.
 * @throws ChannelException if the token is pointing to a non-existing, disabled, or invalid channel.
 * @throws ConnectionException if the token is pointing to a non-existing or non-AMQP server. Also, if there are connectivity issues on client side.
 * @throws InterruptedThreadException if the thread was interrupted while the client was being created.
 * @throws InvalidTokenException if the token is malformed due to abnormal manipulations when the creation request is done.
 * @throws QuotaExceededException if the server has reached the maximum limit of concurrent connections or operations.
 * @throws RequestTimeoutException if the request timed out while was being processed.
 * @throws ServerBusyException if the server is temporarily overloaded and is rejecting new requests.
 * @throws UnexpectedDisconnectionException if the connection was closed abnormally while the client was being created.
 */
@Override
public ServiceBusReceiverClient createSbReceiver(String subscriptionName) {
    try {
        return new ServiceBusClientBuilder()
                .connectionString(TokenHelper.getConnectionStringBuilder(authToken))
                .receiver()
                .topicName(authToken.getEntityPath())
                .subscriptionName(subscriptionName)
                .receiveMode(ServiceBusReceiveMode.PEEK_LOCK)
                .buildClient();
        } catch (Throwable exception) {
        throw ExceptionHandler.generateClientCreationException(exception, "Error creating receiver client");
    }
}

If we see the method TokenHelper.getConnectionStringBuilder():

/**
 * Returns a String using a valid authentication token.
 * @param authToken Source authentication token.
 * @return String.
 * @throws InvalidTokenException if the encoding of the authentication token is not supported
 */
public static String getConnectionStringBuilder (IAuthenticationProvider authToken) {
    return authToken.getServiceBusToken();
}

And getServiceBusToken():

/**
 * Returns Service Bus Sas token.
 * @return Service Bus Sas token.
 */
@Override
public String getServiceBusToken()
{
    String resourceUri = String.format("%s/%s",getEndpointAddress(),entityPath);
    String sasToken = null;
    try {
        String stringToSign = URLEncoder.encode(resourceUri, "UTF-8") + "\n" + expirationDate;
        String signature = getHMAC256(runtimeSignature, stringToSign);
        sasToken = "SharedAccessSignature sr=" + URLEncoder.encode(resourceUri, "UTF-8") +"&sig=" +
                signature + "&se=" + expirationDate + "&skn=" + policyName;
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }

    return sasToken;
}


public static String getHMAC256(String key, String input) {
    Mac sha256_HMAC;
    String hash = null;
    try {
        sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(), "HmacSHA256");
        sha256_HMAC.init(secret_key);
        Base64.Encoder encoder = Base64.getEncoder();

        hash = new String(encoder.encode(sha256_HMAC.doFinal(input.getBytes(StandardCharsets.UTF_8))));

    } catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e) {
        e.printStackTrace();
    }

    return hash;
}

And the Microsoft documentation that I followed to do the method:

Microsoft Documentation

I have tried different ways to build the SaS connection String meeting the requirements but I didn't get a right Connection String.

SaS Connection String Pattern

Could somebody give me some clue about what is wrong with the SaS Connection String? Thank you in advance!


Solution

  • I believe you are getting this error is because your connection string only contains the SAS Token and does not contain the Service Bus endpoint.

    Your connection string should be of the following format:

    Endpoint=sb://foo.servicebus.windows.net/; SharedAccessSignature=<sas-token>;
    

    Can you try creating a connection string using this?

    Otherwise, you can use credential instead of connection string and use credential(String fullyQualifiedNamespace, AzureSasCredential credential)

    Your code would be something like:

    public ServiceBusReceiverClient createSbReceiver(String subscriptionName) throws MessageHubException {
        try {
            return new ServiceBusClientBuilder()
                    .credential(getEndpointAddress(), new AzureSasCredential(TokenHelper.getConnectionStringBuilder(authToken)))
                    .receiver()
                    .topicName(authToken.getEntityPath())
                    .subscriptionName(subscriptionName)
                    .receiveMode(ServiceBusReceiveMode.PEEK_LOCK)
                    .buildClient();
            } catch (Throwable exception) {
            throw ExceptionHandler.generateClientCreationException(exception, "Error creating receiver client");
        }
    }