Security

Both in Windows Azure and in Windows Server, the Service Bus requires access tokens for authorizing access to its entities. Since the Windows Azure Active Directory Access Control (also known as Access Control Service or ACS) is not available on Windows Server, the Service Bus for Windows Server includes a simple Service Bus Security Token Service (SBSTS). The SBSTS is integrated with the Windows security model, and can issue Simple Web Tokens (SWTs) based on Windows identities (stored in the local Windows identity store or in Active Directory).

Service Bus for Windows Server Configuration

The SBSTS is part of the Service Bus for Windows Server gateway and runs on each of the Service Bus for Windows Server farm hosts. The SBSTS settings are initialized when the service namespace is created.

There are two places in the Service Bus for Windows Server in which you can specify authorization rules:

  1. At the Service Bus for Windows Server service namespace level, an administrator specifies a list of users who have manage, send, and receive permissions on all the underlying Service Bus messaging entities (queues, topics, and subscriptions). You can grant these permissions to a security principal (a user or a security group) during creation of the service namespace, and you can modify them later using a PowerShell command. For more information, see the New-SBNamespace and the Set-SBNamespace cmdlets.

  2. At the Service Bus for Windows Server messaging entity level (queue or topic), you can specify authorization rules for that entity. The Manage rule controls whether the user can manage permissions as well as create, change, or delete entities. The Send rule controls whether the user can send messages to a Service Bus for Windows Server entity, and Receive controls whether the user can receive messages from the Service Bus for Windows Server entity. To configure the access rights for an entity, the administrator must configure authorization rules. This action requires the Manage permission on the service namespace.

A user with the Manage permission on the service namespace can then add authorization rules to the entities within the service namespace. For example, once you have created a NamespaceManager instance, you can add the authorization rules when an entity is created, or you can modify them on an existing entity. The following example adds the authorization rules when creating a queue:

// Example of allowing a domain group manage and send permissions to a queue
QueueDescription sourceQ = new QueueDescription(sourceQName);
string domainGroup = “MyGroup@" + Environment.GetEnvironmentVariable("USERDNSDOMAIN"); 
AuthorizationRule sourceQRule = new AllowRule("owner", RoleClaimType, domainGroup, new List<string>() {"Manage", "Send" });
sourceQ.Authorization.Add(sourceQRule );

// Example of granting a domain user listen permissions to a queue
string domainUser = “MyUserName@" + Environment.GetEnvironmentVariable("USERDNSDOMAIN");
AuthorizationRule ListenRule = new AllowRule("owner", IdentityClaimType, domainUser, new List<string>() { "Listen" });
sourceQ.Authorization.Add(ListenRule);
namespaceManager.CreateQueue(sourceQ);

The previous example created a queue (sourceQ) with two authorization rules: granting the group (MYGroup) manage and send permissions, and granting the user (MyUserName) listen permission.

Accessing Service Bus for Windows Server

Clients accessing a service namespace or entity on the Service Bus for Windows Server must acquire a token from the SBSTS for any operation.

Note

The default lifetime for the tokens that the SBSTS issues is 20 minutes.

Using the Service Bus for Windows Server SDK

You can obtain access to a Service Bus entity by obtaining a token from the STS. By default, an $STS used in the Service Bus for Windows Server listens on port 9355.

Clients that use the Service Bus for Windows Server can create a token provider to use with their NamespaceManager and MessagingFactory classes. For example:

stsUris= new List<Uri>() { new Uri(string.Format(CultureInfo.InvariantCulture, 
    "sb://{0}:9355/", <hostname>)) };
TokenProvider tokenProvider = TokenProvider.CreateWindowsTokenProvider(stsUris);

string runtimeAddress = string.Format("sb://{0}:9354/{1}/", <hostname>,  
    <serviceNamespace>);
MessagingFactory messagingFactory = MessagingFactory.Create(runtimeAddress, 
    new MessagingFactorySettings() { TokenProvider = this.tokenProvider, 
    OperationTimeout = TimeSpan.FromMinutes(30) });

In the previous example, replace <hostname> with the name of the server that hosts the Service Bus for Windows Server. Replace <serviceNamespace> with the name of the service namespace you want to access.

Subsequent operations using MessagingFactory automatically acquire the token through the TokenProvider object, and include it in all operations. This class also manages the token caching and renewal based on the token expiry time.

Using HTTP

The following example illustrates access token acquisition by using HTTP from the SBSTS, which resides at the $STS address.

public static void Usage()
{
    string token = GetOAuthAccessToken(new 
        Uri("https://<hostname.domain.com>:9355/<namespace> /"), 
        "user@corp.domain. com", "<password>", TimeSpan.FromMinutes(10)); 
}

public static string GetOAuthAccessToken(Uri namespaceBaseAddress, string userName, string userPassword, TimeSpan timeout)
{
    const int ServicePointMaxIdleTimeMilliSeconds = 50000;
    const string OAuthTokenServicePath = "$STS/OAuth/";
    const string ClientPasswordFormat = 
        "grant_type=authorization_code&client_id={0}&client_secret={1}&scope={2}";

    Uri requestUri = new Uri(namespaceBaseAddress, OAuthTokenServicePath);
    string requestContent = string.Format(CultureInfo.InvariantCulture, 
        ClientPasswordFormat, HttpUtility.UrlEncode(userName), 
        HttpUtility.UrlEncode(userPassword), 
        HttpUtility.UrlEncode(namespaceBaseAddress.AbsoluteUri));
    byte[] body = Encoding.UTF8.GetBytes(requestContent);

    HttpWebRequest request = WebRequest.Create(requestUri) as HttpWebRequest;
    request.ServicePoint.MaxIdleTime = ServicePointMaxIdleTimeMilliSeconds;
    request.AllowAutoRedirect = true;
    request.MaximumAutomaticRedirections = 1;
    request.Method = "POST";
    request.ContentType = "application/x-www-form-urlencoded";
    request.ContentLength = body.Length;
    request.Timeout = Convert.ToInt32(timeout.TotalMilliseconds, 
        CultureInfo.InvariantCulture);

    using (Stream requestStream = request.GetRequestStream())
    {
        requestStream.Write(body, 0, body.Length);
    }

    string rawAccessToken = null;
    using (var response = request.GetResponse() as HttpWebResponse)
    {
        using (Stream stream = response.GetResponseStream())
        {
            using (var reader = new StreamReader(stream, Encoding.UTF8))
            {
                rawAccessToken = reader.ReadToEnd();
            }
        }
    }

    string simpleWebToken = string.Format(CultureInfo.InvariantCulture, 
        "WRAP access_token=\"{0}\"", rawAccessToken);
    return simpleWebToken;
}

In this example, you can substitute the hostname, namespace, and username values in the format shown.

In subsequent messages to the Service Bus for Windows Server, the client can set the HTTP Authorization header to the token obtained from the call to the GetOAuthAccessToken() method in the preceding example.

Note

Clients using HTTP are responsible for managing the token caching and renewal based on the token expiry time.

Build Date:

2013-10-18