Export (0) Print
Expand All

4 - Connecting with Services

This chapter describes the various ways that the Tailspin Surveys mobile client interacts with external services, both custom services created by Tailspin, and services offered by third-party companies. Connecting to external services from a mobile client introduced a set of challenges for the development team at Tailspin to meet in the design and implementation of the mobile client, and in the services hosted in Windows Azure™ technology platform. The mobile client application must do the following:

  • It must operate reliably with variable network connectivity.
  • It must minimize the use of network bandwidth (which may be costly).
  • It must minimize its impact on the phone's battery life.

The online service components must do the following:

  • They must offer an appropriate level of security.
  • They must be easy to develop client applications against.
  • They must support a range of client platforms.

The key areas of functionality in the Tailspin Surveys application that this chapter describes include authenticating with a web service from an application on the phone, pushing notifications to Windows® Phone devices, and transferring data between a Windows Phone device and a web service.

Authenticating with the Surveys Service

You Will Learn

  • How to perform credentials-based authentication between a Windows Phone application and a web service.
  • How to perform claims-based authentication between a Windows Phone application and a web service.

The Surveys service running in Windows Azure needs to know the identity of the user who is using the mobile client application on the Windows Phone device for two reasons. First, when the mobile client requests a list of surveys, the service determines the contents of the list based on the preferences stored in the user's profile. Second, when the mobile client submits a set of survey answers, the Surveys service needs to record who submitted the survey in order to be able to calculate any rewards due the user.

The Windows Azure-based Surveys service needs to identify the user using the mobile client application.

Goals and Requirements

Tailspin wants to externalize as much as possible of the authentication and authorization functionality from the main Surveys application. This will give Tailspin the flexibility to make changes to the way they handle authentication and authorization in the future without affecting the Surveys application itself. For example, Tailspin may want to enable users to identify themselves by using a Windows Live® ID.

Tailspin wants to be able to change the way it authenticates users without requiring major changes to the Surveys application.

It's also important to ensure that the mechanism the mobile client uses to authenticate is easy to implement on the Windows Phone platform and any other mobile platforms that Tailspin may support in the future.

Overview of the Solution

Figure 1 shows a high-level view of the approach adopted by Tailspin.

Gg490769.06739728F0EAAE83977C6D1BE9335FED(en-us,PandP.10).png

Figure 1

Authentication and authorization for the Surveys web services

The approach that Tailspin adopted assumes that the Windows Phone client application can send credentials to the Surveys web service in an HTTP header. The credentials could be a user name and password or a token. Tailspin could easily change the type of credentials in a future version of the application.

Gg490769.note(en-us,PandP.10).gifNote:
In the sample application, the phone sends a user name and password to demonstrate this approach. The mobile client does not perform any validation on the credentials that the user enters on the AppSettingsView page, but it does encrypt the password before it saves the credentials in isolated storage. In a real application, you may decide to enforce a password policy that requires strong passwords and regular password renewals.

In the Surveys web service, the custom authentication and authorization interceptor extracts the header that contains the user's credentials and identifies an authentication module to perform the authentication. It's possible that different client platforms use different authentication schemes, so the interceptor must be able to identify from the HTTP headers which type of authentication is being used, and then pass the credentials to the correct custom authentication module.

Gg490769.note(en-us,PandP.10).gifPoe Says:
Poe Tailspin must be able to handle authentication from other mobile platforms in the future, so choosing a flexible, standards-based approach to authentication is crucial.


Gg490769.note(en-us,PandP.10).gifNote:
The sample application uses a mock authentication module that simply checks for one of several hard-coded user names; it does not verify the password. If you use password-based credentials in your application, you should send a hashed version of the password over the network to compare with a hashed version stored in Windows Azure storage in your authentication module.

After the custom authentication module validates the credentials, it uses Windows Identity Foundation (WIF) to construct an IClaimsPrincipal object that contains the user's identity. In the future, this IClaimsPrincipal object might contain additional claims that the Surveys application could use to perform any authorization it requires.

The surveys web service includes the IClaimsPrincipal.Claims.Name value when it invokes any methods in the Tailspin Surveys core application. The Tailspin Surveys core application returns data for the user. In the future, the web service could also perform any necessary authorization before it invokes a method in the core application.

Gg490769.note(en-us,PandP.10).gifJana Says:
Jana To change the authentication method for the mobile client application, Tailspin must make two changes to the application; they must:
1. Modify the mobile client to send the credentials in a custom HTTP header.
2. Add a new custom authentication module to validate the credentials and create an IClaimsPrincipal object.

A Future Claims-Based Approach

In the future, Tailspin is considering replacing the simple user name and password authentication scheme with a claims-based approach. One option is to use Simple Web Token (SWT) and the Open Authentication (OAuth) 2.0 protocol. This approach offers the following benefits:

Gg490769.note(en-us,PandP.10).gifChristine Says:
Christine When Tailspin developers were developing the mobile client, new versions of the OAuth and SWT standards were anticipated, so they decided to wait for these new releases.

  • The authentication process is managed externally from the Tailspin Surveys application.
  • The authentication process uses established standards.
  • The Surveys application can use a claims-based approach to handle any future authorization requirements.

Figure 2 illustrates this approach, showing the external token issuer.

Gg490769.58C6C45A02E3D8636C0D9C25DBB05F78(en-us,PandP.10).png

Figure 2

An authentication approach using SWT for the Surveys web service

In this scenario, before the mobile client application invokes a Surveys web service, it must obtain an SWT. It does this by sending a request to a token issuer that can issue SWTs; for example, Windows Azure Access Control Services (ACS). The request includes the items of information described in the following table.

Field

Description

Client ID

The client ID is an identifier for the consumer application, which is the Surveys service in this case.

Client Secret

A piece of information that proves that it is your application.

User Name

The user name of the person who wants to authenticate with the Surveys service. The application will prompt the user to enter this name in the user interface (UI).

Password

The user's password. The application will prompt the user to enter this password in the UI.

The client ID and client secret enable the issuer to determine which application is requesting an SWT. The issuer uses the user name and password to authenticate the user.

Gg490769.note(en-us,PandP.10).gifPoe Says:
Poe You should keep the Client ID and Client Secret secure on the phone. If someone discovers them, they could create an application that impersonates the Tailspin mobile client application.

The token issuer then constructs an SWT containing the user's identity and any other claims that the consumer application (Tailspin Surveys) might require. The issuer also attaches a hash value generated using a secret key shared with the Tailspin Surveys service.

Gg490769.note(en-us,PandP.10).gifPoe Says:
Poe The OAuth protocol uses a shared key to generate a hash of the SWT. This shared secret key must be known by the issuer and the Surveys service.

When the client application requests data from the Surveys service, it attaches the SWT to the request in the request's authorization header.

When the Surveys service receives the request, a custom authentication module extracts the SWT from the authorization header, validates the SWT, and then extracts the claims from the SWT. The Surveys service can then use the claims with its authorization rules to determine what data, if any, it should return to the user.

The validation of the SWT in the custom authentication module performs the following steps.

  • It verifies the hash of the SWT by using the shared secret key. This enables the Surveys service to verify the data integrity and the authenticity of the message.
  • It verifies that the SWT has not expired. The token issuer sets the expiration time when it creates the SWT.
  • It checks that the issuer that created the SWT is an issuer that the service is configured to trust.
  • It checks that the client application that is making the request is a client that the service is configured to trust.

Inside the Implementation

Now is a good time to walk through the code that implements the authentication process in more detail. As you go through this section, you may want to download the Windows Phone Tailspin Surveys application from the Microsoft Download Center.

The CustomServiceHostFactory class in the TailSpin.Services.Surveys project initializes the Surveys service. The following code example shows how this factory class creates the authorization manager.

public class CustomServiceHostFactory : WebServiceHostFactory
{
  private readonly IUnityContainer container;

  public CustomServiceHostFactory(IUnityContainer container)
  {
    this.container = container;
  }

  protected override ServiceHost CreateServiceHost(
    Type serviceType, Uri[] baseAddresses)
  {
    var host = new CustomServiceHost(
      serviceType, baseAddresses, this.container);

    host.Authorization.ServiceAuthorizationManager =
      new SimulatedWebServiceAuthorizationManager();
    host.Authorization.PrincipalPermissionMode = 
      PrincipalPermissionMode.Custom;

    return host;
  }
} 
Gg490769.note(en-us,PandP.10).gifNote:
The sample Surveys application uses a simulated authorization manager. You must replace this with a real authorization manager in a production application.

The following code example from the SimulatedWebServiceAuthorizationManager class shows how to override the CheckAccessCore method in the ServiceAuthorizationManager class to provide a custom authorization decision.

protected override bool CheckAccessCore(
  OperationContext operationContext)
{
  try
  {
    if (WebOperationContext.Current != null)
    {
      var headers = 
        WebOperationContext.Current.IncomingRequest.Headers;
      if (headers != null)
      {
        var authorizationHeader = 
          headers[HttpRequestHeader.Authorization];
        if (!string.IsNullOrEmpty(authorizationHeader))
        {
          if (authorizationHeader.StartsWith("user", 
            StringComparison.OrdinalIgnoreCase))
          {
            var userRegex = new Regex(@"(\w+):([^\s]+)", 
              RegexOptions.Singleline);
            var username = userRegex.Match(authorizationHeader)
              .Groups[1].Value;
            var password = userRegex.Match(authorizationHeader)
              .Groups[2].Value;
            if (ValidateUserAndPassword(username, password))
            {
              var identity = new ClaimsIdentity(new[]
              {
                new Claim(System.IdentityModel.Claims.ClaimTypes.Name, 
                  username)
              }, "TailSpin");

              var principal = 
                ClaimsPrincipal.CreateFromIdentity(identity);
              operationContext.ServiceSecurityContext
                .AuthorizationContext.Properties["Principal"] = 
                principal;

              return true;
            }
          }
        }
      }
    }
  }
  catch (Exception)
  {
    if (WebOperationContext.Current != null)
    {
      WebOperationContext.Current.OutgoingResponse.StatusCode = 
        HttpStatusCode.Unauthorized;
    }
    return false;
  }
  if (WebOperationContext.Current != null)
  {
    WebOperationContext.Current.OutgoingResponse.StatusCode = 
      HttpStatusCode.Unauthorized;
  }
  return false;
}

In this simulated authorization manager class, the CheckAccessCore method extracts the user name and password from the authorization header, calls a validation routine, and if the validation routine succeeds, it attaches a ClaimsPrincipal object to the web service context.

Gg490769.note(en-us,PandP.10).gifMarkus Says:
Markus In a real implementation, Tailspin could extract a token from the authorization header and use a validation routine that verifies the token.

In the sample application, the validation routine does nothing more than check that the user name is one of several hard-coded values.

The IHttpWebRequest interface, in the TailSpin.Phone.Adapters project, defines method signatures and properties that are implemented by the HttpWebRequestAdapter class. This class adapts the HttpWebRequest class from the API. The purpose of adapting the HttpWebRequest class with a class that implements IHttpWebRequest is to create a loosely coupled class that is testable.

When SurveysServiceClient calls the GetRequest method in the HttpClient class, it passes in a new instance of HttpWebRequestAdapter, which in turn creates an instance of WebRequest.

Gg490769.note(en-us,PandP.10).gifMarkus Says:
Markus The HttpWebRequest class provides an HTTP-specific implementation of the WebRequest class.

The following code example shows how the GetRequest method in the HttpClient class adds the authorization header with the user name and password credentials to the HTTP request that the mobile client sends to the various Tailspin web services.

public IHttpWebRequest GetRequest(IHttpWebRequest httpWebRequest, 
  string userName, string password)
{
  var authHeader = string.Format(CultureInfo.InvariantCulture,
    "user {0}:{1}", userName, password);
  httpWebRequest.Headers[HttpRequestHeader.Authorization] = authHeader;
  return httpWebRequest;
}

Last built: May 25, 2012

Show:
© 2014 Microsoft