The smart way to share data between computers and other people is to place it in an online Internet store, which the other parties can access, but you want to make sure only the right people can access your data.
This article will help you understand how the Windows Live delegated authentication system is used to access certain Windows Live data stores and the technologies Microsoft is building to make this work easier for you.
The Internet provides a fantastic backbone for sharing data. For many years Microsoft’s consumer services have helped users manage an assortment of data, such as photos on Spaces and contacts in Messenger and Hotmail. Some of this data you want to share with a set of users; that set can range from the entire user base of the Web to just yourself. An example of data you want to share would be photos of your vacation you put in Spaces for your friends to view. For other data types you have an expectation of privacy and security, for example you don’t want your contacts list to be publicly available. One of the advantages to putting all this data online is that it allows you, the user, to access your data from multiple locations.
There are two distinct types of data that users have stored online and it is important to understand the difference between shared data and private data.
There are two distinct types of data that users have stored online and it is important to understand the difference, even if it is not something the user consciously thinks about:
You should be aware that some data stored in a Windows Live Service might be considered public whereas other data in the same service could be private. In the list of examples above you can see that Virtual Earth collections are both in the shared and in the private data sets. A user might want to share a favorite coastal drive but not the collection of locations of companies they are interviewing with for a new job. As a developer building applications on these platforms your application potentially will have access to data that a user doesn’t want shared. You need to consider very carefully how your application will work with this data.
You Need My Authority (But You Aren’t Me)
If you are building an application that needs to access a user’s data, your application will need to ask the user to authenticate the access. This authentication can happen in several ways, for this article I am going to concentrate on the guidance Microsoft is giving for the way forward.
Windows Live delegated authentication is a technology that allows a user to delegate authority to a particular application for a set of resources. The user is able to specify for how long the application will be able to access the Live resources; this could be a matter of minutes, days, or months.
Some of the services provided by Windows Live will offer open access services, services that allow anonymous calls to be made to access the data. The other service offerings will require that the application accessing the data identifies itself in a unique way. It is entirely possible that the same service will provide both anonymous access and identified access. The anonymous access would contain methods to read public facing data, whereas the identified service method would allow private data and public data to be read and written.
If the service offered requires that you identify your application with an application identifier, you will need to obtain an application ID (or AppID) from the Windows Live Microsoft Service Manager at http://msm.live.com/APP. Here you can register your site for an application identifier. You should remember this identifier is unique to your application not to you as a developer or to your company. For each application that you build to access these services you will need a new AppID.
Windows Live delegated authentication is a technology that allows a user to delegate authority to a particular application for a set of resources.
Once you have an AppID, your application can use this ID to contact the resource provider. The resource providers are the different Windows Live services that support this mechanism of delegated authentication. The number of data sources will expand throughout 2008.
The User Owns Their Data
The number one rule is that the user always owns their data. Your application must never redistribute its copy of the user data without consent from that user. This is important. Any application that breaks the user’s trust or the Windows Live terms of usage (http://dev.live.com/terms/) can have its AppID revoked. Users will decide the length of time your application can continue to access their data. Within this timeframe your application can request the user data over the wire as often as it is needed.
Permissions Granted
Once you have your AppID you will need to build a handler page to receive a token known as a consent token. This consent token will be sent to your application from Microsoft once a user has consented to allow delegated authentication to your application. A consent token contains 4 important pieces of information:
Once you have built a page to receive this token, you will need to add a link from your application to the Microsoft consent page. When your application makes a call to the consent page, it needs to pass in the address of the return page you built, the address of the privacy policy statement for your site, your AppID, and a list of the services you would like to access. It is good practice to provide the user with an explanation before taking them to the consent screen. The user can then decide whether to grant permission for your application to these services and the length of time each service can be accessed.
Once you have a consent token, you can use the delegation token to make server calls from your Web server to the service, typically by passing the delegation token in the HTTP Authentication header of your request. The delegation token will expire in a short time frame, so your application may need to use the refresh token to request a new delegation token. Figure 1 shows the data flow in the delegated authentication process.
If your application knows about a user, for example you use the Live ID Web authentication model to manage logged in users, then you probably want to store the consent token against the user ID. The best approach for this would be to create a new data table in your application database to maintain the refresh token and services (with expiration dates) for each user.
One more thing that you should take into consideration is that the expiration dates you have stored for a user may no longer be valid. At any time a user can change the permissions they have granted to applications. This means that the expiration dates should be used as a guide for your application to determine if you need to present the consent screen to the user again and request a new consent token. If the user has revoked the permission for your application to access their data, your application will receive an unauthorized access response. Your application needs to gracefully handle an unauthorized access response; your application could reroute the user to the consent screen, but it would be smarter to indicate to the user why they are being asked for permission again.
Everything as an Atom
The Atom Publishing Protocol (or AtomPub as it’s often called) defines a simple protocol for performing CRUD (Create, Read, Update, and Delete) operations on data over HTTP. Over the coming months, most of the Windows Live Services will provide offerings that conform to the AtomPub standards. This is a fantastic move towards standardization of the Windows Live Services APIs. In the last few years the APIs emerging from the various Windows Live Services have been varied and numerous. Each product group within Microsoft created their own API set, some were REST based, some were SOAP, others were WebDav. Standardizing on a single technology to access the Windows Live Services will make our lives as developers easier.
In an ASP.NET server-side development world, much of the code needed to access these AtomPub services can be in a template and reused.
The new AtomPub services will be available for access through the delegated authentication mechanism described in the previous section. Combining these two technologies to create a well defined mechanism for accessing, authenticating, and working with the Windows Live Services has the following implications:
ADO.NET Data Services (aka Astoria)
At the MIX07 conference in Las Vegas, a new technology codenamed Astoria was announced. Astoria has since been named ADO.NET Data Services and is currently available as a download as a pre-release (CTP) for Visual Studio 2008 users in the ASP.NET 3.5 Extensions pack.
The ADO.NET Data Services consists of libraries for creating and consuming data services over HTTP. These ADO.NET Data Services can present CRUD operations, which can be invoked through the use of the HTTP verbs (GET, PUT, POST, DELETE). Does this sound familiar yet?
ADO.NET Data Services are designed to work with standard formats such as JSON and AtomPub. This is really lucky for developers who want to use the new Windows Live AtomPub services!
However, there is more goodness to be harvested from the ADO.NET Data Services, as they provide a mechanism for modeling the data into objects. These objects are instances of entities and you can use the ADO.NET Data Service to represent the data as entities, and also the relationships between the entities, as defined in the service schemas.
If the service offered requires that you identify your application with an application identifier, you will need to obtain an application ID from the Windows Live Microsoft Service Manager
For developers consuming services, this means that they can interact with Window Live AtomPub services in terms of .NET objects that can be queried, modified, and sent back to the service. This is a great, natural way of interacting with services from the .NET environment. Since it is all AtomPub under the covers, openness and interoperability are not compromised.
As a related note, developers wanting to create services that follow the same HTTP interface pattern as Windows Live AtomPub services can use ADO.NET Data Services on the server to easily do that.
Microsoft, Do It for Me
By providing the Windows Live Service offerings in the AtomPub open standard, Microsoft has enabled all developers to access the same services in a uniform way. As an ASP.NET developer, you might not care about those other programmers but having a well defined and open standard way of accessing the data benefits you as well. In an ASP.NET server-side development world, much of the code needed to access these AtomPub services can be in a template and reused.
The ADO.NET Data Services provides this templating technology. An ASP.NET AJAX library abstracts all the nasty details of how to make the HTTP calls. This leaves you to focus on how you want to manipulate the data in your application. All you need to do in your ASP.NET AJAX code is create an instance of a Sys.Data.DataService class, passing the URI of the service into the constructor:
var liveService =
new Sys.Data.DataService("<a href="http://xxxxxxx.live.com">xxxxxxx.live.com</a>");
Once you have an instance of the DataService class, you can perform various operations on the data using the following methods:
- Query, retrieve data from the service.
- Insert, create new data records on the service.
- Update, change data that already exists.
- Remove, delete data.
Remember that not all services will allow all of these actions; your application might not have the correct authorization or the services might not support the operation at all.
Standardizing on a single technology to access the Windows Live Services will make our lives as developers easier.
Each of these methods will create an instant request over the wire to carry out the operation. If you would like your application to batch operations together you can use the createActionSequence method on the DataService object. ActionSequence is a class that contains a collection of operations to perform on the service. Once you have created the ActionSequence and added the operations you want to perform, you call the executeActions method on the ActionSequence object and the batched operation requests will be made.
Photos Example
The Windows Live Photos API allows a third party site to request delegated authentication from a user. Once the user has granted authentication privileges to a site, the code on that site can make requests to read and write photos associated with that users Live ID, these are the same photos that are displayed on Windows Live Spaces.
The number one rule is that the user always owns their data.
The code in Listing 1 provides an example of how the ADO.NET Data Services can be used to call the Windows Live Photos API. You can see that, by encapsulating the hard work of accessing the service, the Windows Live Photos API can be addressed as if it was a local set of .NET objects.
The code in Listing 2 shows the details of how the supporting classes can be created to provide this extra layer of encapsulation. The LivePhotos class does the heavy listing, and most of that is done by simply deriving from the WebDataContext class.
Conclusion
Writing an article like this before the technology is released presents some challenges but it also allows me to help you gain insight into how new technologies will impact the way we work in the near future. As more Windows Live Services start to support the AtomPUB format you (with the help of the ADO.NET Data Services) will be able to access the huge quantity of resources, personal data and relationships between people. All of this adds up to a far deeper level of connection between the online applications we build. With the caveat that only the data a user actually wants to expose will be available to our web applications. This is going to become a new important consideration for you to handle in your code. How will your application behave if a user denies access to a set of data? Will you provide a downgraded experience? Will you block that user form your site? Will you provide an equally rich experience? As always, one set of solutions creates its own new set of challenges for us to address.
Whatever solutions you decide for your applications, you can be sure the technologies discussed in this article are starting to open the doors of accessibility to a large number of web developers that have previously found the Windows Live APIs too diverse and complex.
The ADO.NET Data Services provides this template.
Code Listing 1: Using ADO.NET Data Services to get photos.
class LivePhotosSimpleClient
{
static void Main(string[] args)
{
LivePhotos photoSvc = new
LivePhotos("http://sitename/folder/AtomLivePhotos");
// list all albums
foreach (Album a in photoSvc.Albums)
{
Console.WriteLine("{0}\t(photos: {1})", a.Name,
a.Photos == null ? 0 : a.Photos.Count);
}
Album album;
// single album by key w/URL
album =
photoSvc.CreateQuery<Album>("/Albums(434)").Single();
Console.WriteLine(album.Name);
// single album by key w/LINQ
album = (from a in photoSvc.Albums
where a.ID == 434
select a).Single();
Console.WriteLine(album.Name);
// photos is album 371, LINQ style
var photos = from a in photoSvc.Albums
where a.ID == 371
from p in a.Photos
select p;
Photo last = null;
foreach (Photo p in photos)
{
Console.WriteLine("{0}:\t{1}", p.ID, p.Title);
last = p;
}
if (last != null)
{
photoSvc.LoadProperty(last, "PhotoBytes");
Console.WriteLine("Loaded picture of type '{0}'.
Launching in explorer...", last.PhotoMimeType);
string file = Path.GetTempFileName();
File.WriteAllBytes(file, last.PhotoBytes);
System.Diagnostics.Process.Start(file);
}
// create an album
Album myPics = new Album();
myPics.ID = 987;
myPics.Name = "Mix08";
photoSvc.AddObject("Albums", myPics);
photoSvc.SaveChanges();
Console.WriteLine("Created, Album ID " + myPics.ID);
}
}
Code Listing 2: Supporting classes for photos sample.
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Data.WebClient;
using System.Xml.Linq;
public class Album
{
public Album()
{
this.Photos = new List<Photo>();
}
public int ID { get; set; }
public string Name { get; set; }
public List<Photo> Photos { get; set; }
}
[MediaEntry("PhotoBytes")]
public class Photo
{
public int ID { get; set; }
public string Version { get; set; }
public string Title { get; set; }
[MimeTypeProperty("PhotoMimeType")]
public byte[] PhotoBytes { get; set; }
public string PhotoMimeType { get; set; }
}
public class LivePhotos : WebDataContext
{
private readonly XNamespace atomns =
"http://<a href="http://www.w3.org/2005/Ato">www.w3.org/2005/Ato</a>m";
public LivePhotos(string url)
: base(url)
{
this.DataNamespace = "http://<a href="http://dev.live.com/photo">dev.live.com/photo</a>s";
this.SendingRequest += new EventHandler<SendingRequestEventArgs>(SendingRequestHandler);
this.ReadingEntity += new EventHandler<ReadingWritingEntityEventArgs>(ReadingEntityHandler);
}
void ReadingEntityHandler(object sender,
ReadingWritingEntityEventArgs e)
{
if (e.Entity is Photo)
{
((Photo)e.Entity).Title = e.Data.Element(atomns +
"title").Value;
}
}
void SendingRequestHandler(object sender,
SendingRequestEventArgs e)
{
e.Request.Proxy = new System.Net.WebProxy(new
Uri("http://127.0.0.1:8888"));
Console.WriteLine(" --> " +
e.Request.RequestUri.ToString());
}
public IQueryable<Album> Albums
{
get { return this.CreateQuery<Album>("/Albums"); }
}
}