Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
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("https://{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();
Comments
- Anonymous
July 15, 2015
Is there a limit for the expireon value? Would it be possible to set the expireon value to 1 year or even non-expire? Thanks