"Relay security token is required."
-
Dienstag, 9. August 2011 18:45
I have a problem getting ACS to work with my Silverlight application. (For simplicity, I’ve used a normal console app to illustrate what I’m trying to do. But I am using basicHttpBinding on the client side.)
Everything works fine calling a REST service:
string realm = "https://[ns].servicebus.appfabriclabs.com/RESTService.svc/";
WebClient client = new WebClient();
string token = GetTokenFromACS(realm);
string headerValue = string.Format("WRAP access_token=\"{0}\"", token);
client.Headers.Add("Authorization", headerValue);
Stream stream = client.OpenRead(realm+"Customers");
However, when trying to call a regular WCF Service (basicHttpRelayBinding on server side), I get a “Relay security token is required.” exception. I’ve tried adding the header using WebOperationContext:
Service1Client client = new Service1Client("Cloud");
using (new OperationContextScope(client.InnerChannel))
{
string token = GetTokenFromACS(realm); // Same token as when calling the REST service
string tokenHeader = string.Format("WRAP access_token=\"{0}\"", token);
WebOperationContext.Current.OutgoingRequest.Headers.Add("Authorization",tokenHeader);
string ret = client.GetData(123); // “Relay security token is required” Exception
}
Trace:
POST /Service1.svc HTTP/1.1
Content-Type: text/xml; charset=utf-8
Authorization: WRAP access_token="net.windows.servicebus.action=Listen%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2fbLogical-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2fblogical.servicebus.appfabriclabs.com%2f&ExpiresOn=1312914390&Issuer=https%3a%2f%2fblogical-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=1K7gscu5FxCGWlFLWhHEGj5359jyH%2bW6DFOe8MQNnMM%3d"
I’ve also tried using OperationContext to add the envelope header…
Service1Client client = new Service1Client("Cloud");
using (new OperationContextScope(client.InnerChannel))
{
string token = GetTokenFromACS(realm); // Same token as when calling the REST service
string tokenHeader = string.Format("WRAP access_token=\"{0}\"", token);
OperationContext.Current.OutgoingMessageHeaders.Add(new ACSHeader(tokenHeader));
string ret = client.GetData(123); // “Relay security token is required” Exception
}
Trace:
POST /Service1.svc HTTP/1.1
Content-Type: text/xml; charset=utf-8
VsDebuggerCausalityData: uIDPozOWNE8J2a9CrpfKtndoEv8AAAAAfqwOWuc5SkaKtNffqNBLOoINjcIBjNRGkRGb0TvcRtkACQAA
SOAPAction: "http://tempuri.org/IService1/GetData"
Host: localhost:8789
Content-Length: 711
Expect: 100-continue
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Header><Authorization xmlns="http://bLogical.se/ACSHeader"><Key>WRAP access_token="net.windows.servicebus.action=Listen%2cSend&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2fbLogical-sb.accesscontrol.appfabriclabs.com%2f&Audience=http%3a%2f%2fblogical.servicebus.appfabriclabs.com%2f&ExpiresOn=1312915757&Issuer=https%3a%2f%2fblogical-sb.accesscontrol.appfabriclabs.com%2f&HMACSHA256=y3ZuRQwVEVpO2g6lUtYcjwcda6A5eOJi5kmopyjhZdk%3d"</Key></Authorization></s:Header><s:Body><GetData xmlns="http://tempuri.org/"><value>123</value></GetData></s:Body></s:Envelope>
So bottom-line, how do I add a header to the WCF call when I can only using basicHttpBinding? Is it supposed to be in the header of the envelope header? If in the envelope header, what header value and jey should I use?
Thanks
//Mikael
If this answers your question, please use the "Answer" button to say so... Mikael - http://blogical.se/blogs/mikael
Alle Antworten
-
Donnerstag, 11. August 2011 03:02
Mikael,
It looks like you are SOOOO CLOSE! Not too sure where AcsHeader is coming from, but the implementation should look like this.
After getting the token, store it like so:
_token = HttpUtility.UrlDecode(reader.ReadToEnd().Split('=')[1]).Replace("&wrap_access_token_expires_in", string.Empty); var bytes = Encoding.UTF8.GetBytes(_token); _token = Convert.ToBase64String(bytes);
Then insert as you show above with an AcsHeader implementation that looks exactly like this:
public class AcsHeader : MessageHeader { private string _token; public AcsHeader(string token) { _token = token; } public override string Name { get { return "RelayAccessToken"; } } public override string Namespace { get { return "http://schemas.microsoft.com/netservices/2009/05/servicebus/connect"; } } protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion) { writer.WriteStartElement("wsse", "BinarySecurityToken", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); writer.WriteAttributeString("wsu", "Id", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", string.Format("uuid:{0}", Guid.NewGuid().ToString("D"))); writer.WriteAttributeString("ValueType", "http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0"); writer.WriteAttributeString("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"); writer.WriteString(_token); writer.WriteEndElement(); } }
Scott Seely- Als Antwort markiert Mikael HåkanssonMVP Freitag, 12. August 2011 10:51

