In the previous posts I demonstrated requesting tokens from the Access Control Service using both Simple Web Token and Shared Secret requests in Java and in PHP. In this little example I am only showing the Shared Secret request in Python.
import sys, httplib, urllib
def MakeSTSRequest(claimSet,stsUrl):
headers = {"Content-type":"application/x-www-form-urlencoded"}
conn = httplib.HTTPSConnection(stsUri)
conn.request("POST","/WRAPv0.8/",claimSet,headers)
response = conn.getresponse()
data = response.read()
conn.close()
return data
def GetTokenBySharedSecret(stsUrl,claimSet,issuerName,issuerKey,rpURL):
claimSet = urllib.urlencode({"applies_to":rpUri,
"wrap_name":issuerName,
"wrap_password":issuerKey})
responseString=MakeSTSRequest(claimSet,stsUrl)
return ExtractTokenFromResponse(responseString)
def ExtractTokenFromResponse(stringResponse):
claims=stringResponse.split("&")
for claim in claims:
keyValue=claim.split("=")
if(keyValue[0]=="wrap_token"):
return keyValue[1]
return stringResponse
stsUri="[service namespace].accesscontrol.windows.net"
rpUri="[scope applies_to]"
issuerName="[issuer name]"
issuerKey="[issuer key]"
claimSet={"sample_claim_type":"sample_claim_value"}
print GetTokenBySharedSecret(stsUri,claimSet,issuerName,issuerKey,rpUri)
Following demonstrates requesting a token from the .NET Services Access Control Services using a Shared Secret and another using a Simple Web Token.
You'll also need these three libraries to help in the encoding process and the HTTP calls. There are some hacky pieces of code here, but that's mostly due to my ignorance in Java. Feedback to make this better quality code is welcome.
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
public class RequestACSToken {
private static final String HMAC_SHA256 = "HmacSHA256";
public static void main(String[] args) throws ClientProtocolException, NoSuchAlgorithmException, IllegalStateException, IOException, Exception
{
String stsUrl="https://[service namespace].accesscontrol.windows.net/WRAPv0.8/";
String rpUrl="[scope applies_to]";
String issuerKey="[issuer key]";
String issuerName="[issuer name]";
List<NameValuePair> claimSetSharedSecret = new ArrayList<NameValuePair>();
claimSetSharedSecret.add(new BasicNameValuePair("sample_in_claim_type","sample_in_claim_value"));
String tokenSharedSecret=GetTokenBySharedSecret(stsUrl,claimSetSharedSecret,issuerName,issuerKey,rpUrl);
System.out.println("Shared Secret: " + tokenSharedSecret);
List<NameValuePair> claimSetSimpleWebToken = new ArrayList<NameValuePair>();
claimSetSimpleWebToken.add(new BasicNameValuePair("sample_in_claim_type","sample_in_claim_value"));
String tokenSimpleWebToken=GetTokenBySimpleWebToken(stsUrl,claimSetSimpleWebToken,issuerName,issuerKey,rpUrl);
System.out.println("Simple Web Token: " + tokenSimpleWebToken);
}
public static String ExtractTokenFromResponse(String stringResponse)
{
String[] returnClaimSet=stringResponse.split("&");
for(int i=0; i<returnClaimSet.length; i++)
{
String[] claimItem=returnClaimSet[i].split("=");
if(claimItem[0].equals("wrap_token"))
{
return claimItem[1];
}
}
// this is an error case, but the body does contain the error details so useful to display
return stringResponse;
}
public static String MakeSTSRequest(List<NameValuePair> claimSet, String stsUrl) throws ClientProtocolException, IOException
{
// encode the claim set
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(claimSet, "UTF-8");
// make the request to the STS
HttpPost httpPost = new HttpPost(stsUrl);
httpPost.setEntity(entity);
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(httpPost);
// capture the response into a string
HttpEntity responseEntity = response.getEntity();
String stringResponse = entity!=null ? EntityUtils.toString(responseEntity) : "";
return stringResponse;
}
public static String GetTokenBySharedSecret(String stsUrl, List<NameValuePair> claimSet, String issuerName, String issuerKey, String rpUrl) throws ClientProtocolException, IOException
{
claimSet.add(new BasicNameValuePair("wrap_name",issuerName));
claimSet.add(new BasicNameValuePair("wrap_password",issuerKey));
claimSet.add(new BasicNameValuePair("applies_to",rpUrl));
String stringResponse=MakeSTSRequest(claimSet,stsUrl);
// extract the value for wrap_token and return
return ExtractTokenFromResponse(stringResponse);
}
public static String GetTokenBySimpleWebToken(String stsUrl, List<NameValuePair> claimSet, String issuerName, String issuerKey, String rpUrl) throws ClientProtocolException, IOException, Exception, NoSuchAlgorithmException, IllegalStateException
{
claimSet.add(new BasicNameValuePair("Issuer",issuerName));
claimSet.add(new BasicNameValuePair("Audience",stsUrl));
claimSet.add(new BasicNameValuePair("HMACSHA256",CreateSignature(EncodeQueryString(claimSet),issuerKey)));
List<NameValuePair> newClaimSet = new ArrayList<NameValuePair>();
String wrapToken=EncodeQueryString(claimSet);
newClaimSet.add(new BasicNameValuePair("wrap_SWT",wrapToken));
newClaimSet.add(new BasicNameValuePair("applies_to",rpUrl));
String stringResponse=MakeSTSRequest(newClaimSet,stsUrl);
// extract the value for wrap_token and return
return ExtractTokenFromResponse(stringResponse);
}
public static String CreateSignature(String hmacFreeClaimSet, String key) throws NoSuchAlgorithmException, InvalidKeyException, IllegalStateException, UnsupportedEncodingException
{
SecretKeySpec signingKey = new SecretKeySpec(Base64.decodeBase64(key), HMAC_SHA256);
Mac mac = Mac.getInstance(HMAC_SHA256);
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(hmacFreeClaimSet.getBytes("ASCII"));
return Base64.encodeBase64String(rawHmac);
}
public static String EncodeQueryString(List<NameValuePair> claimSet) throws UnsupportedEncodingException
{
List<String> claims = new ArrayList<String>();
for(Iterator<NameValuePair> i = claimSet.iterator(); i.hasNext();)
{
NameValuePair item = (NameValuePair)i.next();
claims.add(item.getName() + "=" + URLEncoder.encode(item.getValue().trim(),"UTF-8"));
}
return StringUtils.join(claims,"&");
}
Following demonstrates requesting a token from the .NET Services Access Control Services using a Shared Secret and another using a Simple Web Token.
<?php
$stsUrl="https://[service namespace].accesscontrol.windows.net/WRAPv0.8/";
$rpUrl="[scope applies_to]";
$issuerKey="[issuer key]";
$issuerName="[issuer name]";
$claims = array("sample_in_claim_type"=>"sample_in_claim_value");
echo("<b>Shared Secret</b>: " . GetTokenBySharedSecret($stsUrl,$claims,$issuerName,$issuerKey,$rpUrl) . "<br/>");
echo("<b>Simple Web Token</b>: " . GetTokenBySimpleWebToken($stsUrl,$claims,$issuerName,$issuerKey,$rpUrl) . "<br/>");
function GetTokenBySharedSecret($stsUrl, $claimSet, $issuerName, $issuerKey, $rpUrl)
{
$claimSet["wrap_name"]=$issuerName;
$claimSet["wrap_password"]=$issuerKey;
$claimSet["applies_to"]=$rpUrl;
$stringResponse = MakeSTSRequest($claimSet,$stsUrl);
return ExtractTokenFromResponse($stringResponse);
}
function GetTokenBySimpleWebToken($stsUrl, $claimSet, $issuerName, $issuerKey, $rpUrl)
{
$claimSet["Issuer"]=$issuerName;
$claimSet["Audience"]=$stsUrl;
$claimSet["HMACSHA256"]=CreateSignature($claimSet,$issuerKey);
$requestSet=array();
$requestSet["wrap_SWT"]=http_build_query($claimSet);
$requestSet["applies_to"]=$rpUrl;
$stringResponse = MakeSTSRequest($requestSet,$stsUrl);
return ExtractTokenFromResponse($stringResponse);
}
function MakeSTSRequest($claimSet, $stsUrl)
{
// encode the claimset
$tokenRequestBody=http_build_query($claimSet);
// make the request to the STS
$options = array(
"http"=>array(
"method"=>"POST",
"header"=>"Content-Type: application/x-www-form-urlencoded",
"content"=>$tokenRequestBody));
$context=stream_context_create($options);
$fp = fopen($stsUrl,'r',false,$context);
// capture the response into a string
return stream_get_contents($fp);
}
function ExtractTokenFromResponse($stringResponse)
{
parse_str($stringResponse,$Values);
return $Values["wrap_token"];
}
function CreateSignature($claimSet, $key)
{
$hmacFreeClaimSet=http_build_query($claimSet);
$key64Encoded=base64_decode($key);
return base64_encode(hash_hmac("sha256",$hmacFreeClaimSet,$key64Encoded,true));
}
?>
While attending the WCF TechEd booth the most frequent asked question we get is "What is WinFx". This question is asked because our big sign has that as the title and each sub-group has a sub title, in my case "Windows Communication Foundation."
I started writing the answer in my own words but I believe that the .NET Framework 3.0 website can answer that question better. http://www.netfx3.com/content/WhatIsNetFx3.aspx
In addition to the information on that website I can only add this tiny piece of information: Windows Communication Foundation and Windows Presentation Foundation formerly were codenamed Indigo and Avalon respectfully. Numerous developers still know those technologies by their old codename.
The .NET Framework 3.0 (netfx3) is currently in Beta2 with a go-live license. NetFx3 is planned to be released with Vista AND for Windows XP as well as 2003.