The AppFabric SDK V1.0 July Update SDK has a number of Access Control Service examples demonstrating the requesting of a token from the Access Control Service; however I find myself needing a small snippet to insert into other samples (e.g. Service Bus) just to craft a request token and get a token to Auth with SB. As such, I’m posting this “TokenFactory” code that I’ve been re-using. This is fundamentally the same functionality I’ve demonstrated in previous posts in PHP, Java, and Python.
namespace Microsoft.AccessControl.Client { using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Web; using System.Net; using System.Collections.Specialized; public class TokenFactory { private static string acsHost = "accesscontrol.windows.net"; string serviceNamespace; string issuerName; string signingKey; public TokenFactory(string serviceNamespace, string issuerName, string signingKey) { this.serviceNamespace = serviceNamespace; this.issuerName = issuerName; this.signingKey = signingKey; } public string CreateRequestToken() { return this.CreatRequestToken(new Dictionary<string, string>()); } public string CreatRequestToken(Dictionary<string, string> claims) { // build the claims string StringBuilder builder = new StringBuilder(); foreach (KeyValuePair<string, string> entry in claims) { builder.Append(entry.Key); builder.Append('='); builder.Append(entry.Value); builder.Append('&'); } // add the issuer name builder.Append("Issuer="); builder.Append(this.issuerName); builder.Append('&'); // add the Audience builder.Append("Audience="); builder.Append(string.Format("https://{0}.{1}/WRAPv0.9/&", this.serviceNamespace, acsHost)); // add the expires on date builder.Append("ExpiresOn="); builder.Append(GetExpiresOn(20)); string signature = this.GenerateSignature(builder.ToString(), this.signingKey); builder.Append("&HMACSHA256="); builder.Append(signature); return builder.ToString(); } private string GenerateSignature(string unsignedToken, string signingKey) { HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(signingKey)); byte[] locallyGeneratedSignatureInBytes = hmac.ComputeHash(Encoding.ASCII.GetBytes(unsignedToken)); string locallyGeneratedSignature = HttpUtility.UrlEncode(Convert.ToBase64String(locallyGeneratedSignatureInBytes)); return locallyGeneratedSignature; } private static ulong GetExpiresOn(double minutesFromNow) { TimeSpan expiresOnTimeSpan = TimeSpan.FromMinutes(minutesFromNow); DateTime expiresDate = DateTime.UtcNow + expiresOnTimeSpan; TimeSpan ts = expiresDate - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToUInt64(ts.TotalSeconds); } public string GetACSToken(string swt, string appliesTo) { // request a token from ACS WebClient client = new WebClient(); client.BaseAddress = string.Format(@"https://{0}.{1}/", serviceNamespace, acsHost); NameValueCollection values = new NameValueCollection(); values.Add("wrap_assertion_format", "SWT"); values.Add("wrap_assertion", swt); values.Add("wrap_scope", appliesTo); string response = null; byte[] responseBytes = client.UploadValues("WRAPv0.9/", values); response = Encoding.UTF8.GetString(responseBytes); return HttpUtility.UrlDecode(response .Split('&') .Single(value => value.StartsWith("wrap_access_token=", StringComparison.OrdinalIgnoreCase)) .Split('=')[1]); } } }
Here is a sample that uses the above to get a token from ACS. In this example I am using it specifically for Service Bus (hence “-sb” in the service namespace).
string serviceNamespace = "-"; string issuerName = "-"; string issuerKey = "-"; string baseAddress= string.Format("http://{0}.servicebus.windows.net/",serviceNamespace); string serviceAddress = string.Format("https://{0}.servicebus.windows.net/Text/GetText", serviceNamespace); TokenFactory tf = new TokenFactory(string.Format("{0}-sb",serviceNamespace), issuerName, issuerKey); string requestToken = tf.CreateRequestToken(); string returnToken = tf.GetACSToken(requestToken, baseAddress); Console.WriteLine(requestToken); Console.WriteLine(returnToken); Console.ReadLine();