If you saw my post on BuildMobile.com you would have seen that I used the “token” response_type when initially specifying the login url. This works well for getting a short lived access token but the wl.offline_access scope is effectively ignored – the expiry time comes back as 3600. This is completely useless for a Windows Phone application where you don’t want to have to reprompt the user every time they run the application. Luckily, despite the failings in the current implementation, there is a work around which involves a few more steps and uses the “code” response_type.
I’m not going to step through the entire process, instead, here is the code that you should be able to use – it’s based on my post Using Windows Live ID in a WP7 Appon BuildMobile.com so should be easy enough to follow.
Notes:
– You need to replace both <your_client_id> and <your_client_secret> with the corresponding values for your application
– In a production application you should not have the client id or client secret in plain text in your application – ideally this should be held on a server and only exposed to the client app over ssl and never persisted in the client app. 
using System;   
using System.Collections.Generic;    
using System.Linq;    
using System.Net;    
using System.Runtime.Serialization;    
using System.Runtime.Serialization.Json;    
using System.Text;    
using System.Windows;    
using System.Windows.Navigation;
namespace WLTest   
{    
    public partial class MainPage    
    {    
        // Constructor    
        public MainPage()    
        {    
            InitializeComponent();    
        }
        private void AuthenticateClick(object sender, RoutedEventArgs e)   
        {    
            var uriParams = new Dictionary<string, string>()    
                                {    
                                    {“client_id”, “<your_client_id>”},    
                                    {“response_type”, “code”},    
                                    {“scope”, “wl.signin,wl.basic,wl.offline_access”},    
                                    {“redirect_uri”, “https://oauth.live.com/desktop”},    
                                    {“display”, “touch”}    
                                };    
            StringBuilder urlBuilder = new StringBuilder();    
            foreach (var current in uriParams)    
            {    
                if (urlBuilder.Length > 0)    
                {    
                    urlBuilder.Append(“&”);    
                }    
                var encoded = HttpUtility.UrlEncode(current.Value);    
                urlBuilder.AppendFormat(“{0}={1}”, current.Key, encoded);    
            }    
            var loginUrl = “https://oauth.live.com/authorize?” + urlBuilder.ToString();
            AuthenticationBrowser.Navigate(new Uri(loginUrl));   
            AuthenticationBrowser.Visibility = Visibility.Visible;
}
        public string AccessToken { get; set; }   
        public string RefreshToken { get; set; }
        private void BrowserNavigated(object sender, NavigationEventArgs e)   
        {    
            if (e.Uri.AbsoluteUri.ToLower().Contains(“https://oauth.live.com/desktop”)) 
            {    
                var query = (from pair in e.Uri.Query.Trim(‘?’).Split(‘&’)    
                             let bits = pair.Split(‘=’)    
                             where bits.Length == 2    
                             select new KeyValuePair<string, string>(bits[0], bits[1])).ToArray();
                var code =   
                    query.Where(kvp => kvp.Key == “code”).Select(kvp => HttpUtility.UrlDecode(kvp.Value)).FirstOrDefault    
                        ();    
                if (string.IsNullOrEmpty(code))    
                {    
                    var error =    
                        query.Where(kvp => kvp.Key == “error”).Select(kvp => HttpUtility.UrlDecode(kvp.Value)).    
                            FirstOrDefault();    
                    var error_desc =    
                        query.Where(kvp => kvp.Key == “error_description”).Select(    
                            kvp => HttpUtility.UrlDecode(kvp.Value)).FirstOrDefault();    
                    MessageBox.Show(“Error: ” + error + “n” + error_desc);    
                    AuthenticationBrowser.Visibility = System.Windows.Visibility.Collapsed;    
                    return;    
                }
                var uriParams = new Dictionary<string, string>()   
                                    {    
                                        {“client_id”, “<your_client_id>”},    
                                        {“client_secret”, “<your_client_secret>”},    
                                        {“redirect_uri”, “https://oauth.live.com/desktop”},    
                                        {“code”, HttpUtility.UrlEncode(code)},    
                                        {“grant_type”, “authorization_code”}    
                                    };    
                StringBuilder urlBuilder = new StringBuilder();    
                foreach (var current in uriParams)    
                {    
                    if (urlBuilder.Length > 0)    
                    {    
                        urlBuilder.Append(“&”);    
                    }    
                    var encoded = HttpUtility.UrlEncode(current.Value);    
                    urlBuilder.AppendFormat(“{0}={1}”, current.Key, encoded);    
                }    
                var tokenUri = “https://oauth.live.com/token?” + urlBuilder.ToString();
                var request = HttpWebRequest.CreateHttp(tokenUri);   
                request.BeginGetResponse(result =>    
                                             {    
                                                 var req = result.AsyncState as HttpWebRequest;    
                                                 using (var resp = req.EndGetResponse(result))
                                                 using (var strm = resp.GetResponseStream())   
                                                 {    
                                                     var serializer =    
                                                         new DataContractJsonSerializer(    
                                                             typeof (WindowsLiveAuthorizationCode));    
                                                     var authorization =    
                                                         serializer.ReadObject(strm) as WindowsLiveAuthorizationCode;    
                                                     AccessToken = authorization.AccessToken;    
                                                     RefreshToken = authorization.RefreshToken;
                                                     this.Dispatcher.BeginInvoke(() => MessageBox.Show(   
                                                         “Access granted”));    
                                                     RequestUserProfile();    
                                                 }    
                                             }, request);
                AuthenticationBrowser.Visibility = System.Windows.Visibility.Collapsed;   
            }    
           
        }
        private void RequestUserProfile()    
        {    
            var profileUrl = string.Format(“https://apis.live.net/v5.0/me?access_token={0}”,    
                                           HttpUtility.UrlEncode(AccessToken));    
            var request = HttpWebRequest.Create(new Uri(profileUrl));    
            request.Method = “GET”;    
            request.BeginGetResponse(result =>    
                                         {    
                                             try    
                                             {    
                                                 var resp = (result.AsyncState as HttpWebRequest).EndGetResponse(result);    
                                                 using (var strm = resp.GetResponseStream())    
                                                 {    
                                                     var serializer =    
                                                         new DataContractJsonSerializer(typeof (WindowsLiveProfile));    
                                                     var profile =    
                                                         serializer.ReadObject(strm) as WindowsLiveProfile;    
                                                     this.Dispatcher.BeginInvoke((Action<WindowsLiveProfile>) ((user) => {    
                                                                            this.UserIdText.Text = user.Id;    
                                                                            this.UserNameText.Text = user.Name;    
                                                                                                                   }),    
                                                                                 profile);    
                                                 }    
                                             }    
                                             catch (Exception ex)    
                                             {    
                                                 this.Dispatcher.BeginInvoke(() =>    
                                                                             MessageBox.Show(“Unable to attain profile information”));    
                                             }    
                                         }, request);    
        }
        [DataContract]   
        public class WindowsLiveProfile    
        {    
            [DataMember(Name = “id”)]    
            public string Id { get; set; }
            [DataMember(Name = “name”)]   
            public string Name { get; set; }    
        }
        [DataContract]   
        public class WindowsLiveAuthorizationCode    
        {    
            [DataMember(Name = “access_token”)]    
            public string AccessToken { get; set; }
            [DataMember(Name = “refresh_token”)]   
            public string RefreshToken { get; set; }
            [DataMember(Name = “scope”)]   
            public string Scope { get; set; }
            [DataMember(Name = “token_type”)]   
            public string TokenType { get; set; }
            [DataMember(Name = “expires_in”)]   
            public string ExpiresIn { get; set; }    
        }
        private void RefreshTokenClick(object sender, RoutedEventArgs e)   
        {
            var uriParams = new Dictionary<string, string>()   
                                {    
                                    {“client_id”, “<your_client_id>”},    
                                    {“client_secret”, “<your_client_secret>”},    
                                    {“redirect_uri”, “https://oauth.live.com/desktop”},    
                                    {“refresh_token”, RefreshToken},    
                                    {“grant_type”, “refresh_token”}    
                                };    
            StringBuilder urlBuilder = new StringBuilder();    
            foreach (var current in uriParams)    
            {    
                if (urlBuilder.Length > 0)    
                {    
                    urlBuilder.Append(“&”);    
                }    
                var encoded = HttpUtility.UrlEncode(current.Value);    
                urlBuilder.AppendFormat(“{0}={1}”, current.Key, encoded);    
            }    
            var tokenUri = “https://oauth.live.com/token?” + urlBuilder.ToString();
            var request = HttpWebRequest.CreateHttp(tokenUri);   
            request.BeginGetResponse(result =>    
                                         {    
                                             var req = result.AsyncState as HttpWebRequest;    
                                             using (var resp = req.EndGetResponse(result))
                                             using (var strm = resp.GetResponseStream())   
                                             {    
                                                 var serializer =    
                                                     new DataContractJsonSerializer(    
                                                         typeof (WindowsLiveAuthorizationCode));    
                                                 var authorization =    
                                                     serializer.ReadObject(strm) as WindowsLiveAuthorizationCode;    
                                                 AccessToken = authorization.AccessToken;    
                                                 RefreshToken = authorization.RefreshToken;
                                                 this.Dispatcher.BeginInvoke(() => MessageBox.Show(   
                                                     “Token refreshed”));    
                                             }    
                                         }, request);    
        }    
    }    
}