After authenticating the user by using active federation as described in the Implement active
federation and claims-based authorization for the mobile client section, the client can send its request
to the service endpoint. We now need to use the AuthenticationProvider object within the Windows Phone app.
1. As is shown in the ContosoMobileApp application, when the user clicks the Submit/Save button, we will handle the UploadClick event in the following way.
C#
private void UploadClick(object sender, EventArgs e) {
Submit(); }
2. In the Submit method, we initialize the AuthenticationProvider object, subscribe to its
AuthenticationCompleted event, and then call the IssueToken method.
We pass in the user data that we collect from the Settings.xaml page to initialize the
AuthenticationProvider object; the following code shows an example of the user input that can
The IssueToken method is the starting point for the multiple asynchronous calls.
C#
public void Submit() {
// parameters are domain\\userAlias, user's password, Azure Namespace & ADFS endpoint URL authenticator = new AuthenticationProvider("contoso\\userAlias", "password",
"contosmobile", "https://contosoadfs.com/adfs/services/trust/13/usernamemixed"); authenticator.AuthenticationCompleted += authenticator_AuthenticationCompleted; authenticator.IssueToken(); } C# /// <summary>
/// Handle the Authentication completed event and then submit the expense using the tokens /// if the authentication was successful
/// </summary>
private void authenticator_AuthenticationCompleted(object sender, AuthenticationMessageArgs e)
{
if (e.AuthenticationMessage.IsSuccess) {
// Authentication was successful. Now submit the expense through service bus, // using the SWT and SAML token values exposed by the AuthenticationProvider CreateExpense(); } else { RaiseSubmitCompleted(new Exception(e.AuthenticationMessage.Message)); } }
3. After the IssueToken asynchronous method is completed, the AuthenticationCompleted event is fired. We then check whether the authentication was successful.
If the authentication was successful, the app is now in possession of the SWT (the token to authenticate to the Service Bus) and the SAML token (the token containing the
windowsaccountname claim that is used to set the call context of the AIF service call). We then
insert the two tokens into a custom SOAP header of the message. The body of the message will contain the expense data we want to send to the middle-tier WCF service.
4. Add a method named CreateExpense that creates the message as described in the previous step and sends it to the actual service endpoint on the Service Bus—that is, https://<AzureNamespace >servicebus.windows.net/Expense/.
A call is then made to the CreateExpenseAsync service operation by using the middle-tier service’s ExpenseServiceContractClient client proxy.
C#
private void CreateExpense() {
ExpenseServiceReference.ExpenseServiceContractClient expenseService = new ExpenseServiceReference.ExpenseServiceContractClient();
expenseService.Endpoint.Address = new System.ServiceModel.EndpointAddress( new Uri(SettingsViewModel.ServiceEndpoint));
expenseService.CreateExpenseCompleted +=
new EventHandler<CreateExpenseCompletedEventArgs>(OnCreateExpenseCompleted);
C# {
// Grab the raw SAML token and stuff it in a byte array
byte[] binToken = Encoding.UTF8.GetBytes(authenticator.SamlAssertionToken);
// Add the SAML token to a custom SOAP header var customSecurityHeader =
MessageHeader.CreateHeader("PassthroughBinarySecurityToken", "", Convert.ToBase64String(binToken));
OperationContext.Current.OutgoingMessageHeaders.Add(customSecurityHeader);
// Add the SWT token to a SOAP header as SB is expecting OperationContext.Current.OutgoingMessageHeaders.Add( new AcsHeader(authenticator.SwtAcsToken));
// Finally, call the actual service to create our expense. expenseService.CreateExpenseAsync(
ExpenseDate, Amount, Amount == 0? null : Currency, Comment); }
} C#
/// <summary>
/// This is the Custom (SOAP header) format that Service Bus requires a token /// from ACS to exist in the message. This header will be stripped out by SB /// and thus will not exist when the message gets to the service.
/// </summary> /// <remarks>
/// Leave all these hard-coded values alone, SB is expecting /// a very particular format for this header.
/// </remarks>
private class AcsHeader : MessageHeader {
private string token;
public AcsHeader(string token) {
this.token = token; }
public override string Name {
get { return "RelayAccessToken"; } }
public override string Namespace {
get { return "http://schemas.microsoft.com/netservices/2009/05/servicebus/connect"; } }
C#
protected override void OnWriteHeaderContents(
XmlDictionaryWriter writer, MessageVersion messageVersion) { writer.WriteStartElement("BinarySecurityToken", "http://docs.oasis- open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); writer.WriteAttributeString("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");
byte[] binToken = Encoding.UTF8.GetBytes(token); writer.WriteBase64(binToken, 0, binToken.Length);
writer.WriteEndElement(); }
}
The request is then sent to the endpoint on the Service Bus. The Service Bus authorizes the incoming message to be relayed through it to the middle-tier WCF service, by examining the SWT. The expense data and the SAML token are then passed to the middle-tier service.
The Service Bus also relays back the response from the WCF service after the operation is completed. An event is raised to notify about completion.
In this example, you can also create a custom completed notification event to handle the response (success or error messages) within the application and send a message that can be viewed by the user. In the preceding code sample, we subscribe to a custom event, CreateExpenseCompleted, to accomplish this.