Integrating a desktop application with Windows Live

If one searches the Web for samples of how to integrate a desktop application with Windows Live, unfortunately one finds one's way to material that is out-of-date.  So here is some code that works as of July 2011.  The code is for a Windows Form that has a browser control and a text box.  The only modification you will need to make to the code is to alter the ApplicationIdentifier constant to point at the identiifer of your own application registered at https://manage.dev.live.com.  The code navigates the browser control to the Windows Live authentication page.  The browser control handles the navigation event to sniff at the locations to which it is redirected.  Upon navigation to a location that signifies successful authentication, the location is parsed for the access token.  Given the access token, the application can retrieve the user's information.  The DataContractJsonSerializer is used to parse the response to the request for that information. 

 

using System;

using System.Globalization;

using System.IO;

using System.Linq;

using System.Net;

using System.Runtime.Serialization;

using System.Runtime.Serialization.Json;

using System.Windows.Forms;

 

namespace LiveID

{

    public partial class Form1 : Form

    {

        const string ApplicationIdentifier = "0000000000000000"; //YOUR APPLICATION IDENTIFIER GOES HERE

        const string AuthenticationHost = "oauth.live.com";

        const string AuthenticationLocalPathDesktop = "/desktop";

        const string AuthenticationResourceTemplate = @"https://{0}/authorize?client_id={1}&response_type=token&scope=wl.signin%20wl.basic&redirect_uri=https://{0}{2}";

        const string ContentTypeText = "application/text";

        const string KeyAccessToken = "#access_token";

        const string MethodGet = "GET";

        const string ResultTemplate = "User Name: {0}; Identifier {1}";

        const char SeperatorQuery = '&';

        const string UserResourceTemplate = "https://apis.live.net/v5.0/me?{0}";       

 

        public Form1()

        {

            InitializeComponent();

        }

 

        private void Form1_Load(object sender, EventArgs e)

        {

            this.webBrowser1.Url =

                new Uri(

                    string.Format(

                        CultureInfo.InvariantCulture,

                        Form1.AuthenticationResourceTemplate,

                        Form1.AuthenticationHost,

                        Form1.ApplicationIdentifier,

                        Form1.AuthenticationLocalPathDesktop));

        }

 

        private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e)

        {

            Uri location = e.Url;

            if ((location.Host == Form1.AuthenticationHost) && (location.LocalPath == Form1.AuthenticationLocalPathDesktop))

            {

                string[] fragments = location.Fragment.Split(Form1.SeperatorQuery);

                string token = fragments.Where((string item) => item.StartsWith(Form1.KeyAccessToken)).FirstOrDefault();

                if (!(string.IsNullOrEmpty(token)))

                {

                    WebRequest request = WebRequest.Create(new Uri(string.Format(CultureInfo.InvariantCulture,Form1.UserResourceTemplate,token.Substring(1))));

                    request.Method = MethodGet;

                    using(Stream responseStream = request.GetResponse().GetResponseStream())

                    {

                        request.ContentType = Form1.ContentTypeText;

                        User user = (User)new DataContractJsonSerializer(typeof(User)).ReadObject(responseStream);

                        this.textBox1.Text = string.Format(CultureInfo.CurrentUICulture,Form1.ResultTemplate,user.Name,user.Identifier);

                    }

                }

            }

           

        }

    }

 

    [DataContract]

    partial class User : IExtensibleDataObject

    {

        ExtensionDataObject extendedData;

 

        [DataMember(Name = "id")]

        internal string Identifier

        {

            get;

            set;

        }

 

        [DataMember(Name = "name")]

        internal string Name

        {

            get;

            set;

        }

 

        public ExtensionDataObject ExtensionData

        {

            get

            {

                return this.extendedData;

            }

 

            set

            {

                this.extendedData = value;

            }

        }

    }

}