Windows desktop apps

The Live SDK uses industry standard protocols such as OAuth 2.0 and JavaScript Object Notation (JSON) to make it easy to access and integrate Microsoft OneDrive into your mobile or desktop app.

In this article
Creating a new app
App overview
Building an app

This walkthrough demonstrates how to create a desktop app that can access user data by using the Live SDK. In addition, there are code samples available on GitHub that show how to use Live SDK from a variety of mobile platforms.

Creating a new app

When you get a client ID from the Live SDK app management site, leave the Redirect Domain field blank. By doing so, you configure your app to use a special redirect URL(https://login.live.com/oauth20\_desktop.srf), which enables the app to handle redirects after the user has given authorization and facilitates refreshing the access token.

Accessing data from OneDrive using your platform of choice requires the availability of a web browser component that can be used to authenticate the user. The app in this example is a Windows Presentation Foundation (WPF) app that is written in C# and the .NET Framework version 4. You can build and run it by using either Microsoft Visual Studio 2010 or Microsoft Visual Studio 2008.

Note

Because Windows Store apps and Windows Phone apps have built-in support for user sign-in and consent, the info presented in this walkthrough is not applicable to them. For these types of apps, see Windows Runtime apps (HTML) and Windows Runtime apps (XAML).

App overview

To implement the client-side authentication flow, desktop apps must use a web browser control. Most development languages include such a control. In this example, our app uses the System.Windows.Forms.WebBrowser class. After sign in is complete, all subsequent Live SDK calls can be accomplished by using the System.Net.WebRequest class. Use the web browser control to start the sign-in, passing a URL similar to this one.

https://login.live.com/oauth20_authorize.srf?client_id=YOUR_CLIENT_ID&scope=YOUR_SCOPE_STRING&response_type=code&redirect_uri=https://login.live.com/oauth20_desktop.srf

This URL displays the standard Microsoft account sign-in page. Note that the redirect_uri parameter specifies the service URL that is designed for desktop apps as described in the previous section. Use this URL whenever you need to supply a redirect Uniform Resource Identifier (URI). The response_type and scope parameters are also required. The value of the response_type parameter must be set to code.

After the user grants consent, the Live SDK returns a URI that contains the authorization code. It looks like the URI in the following example.

https://login.live.com/oauth20_desktop.srf#code=AUTHORIZATION_CODE

Note

If the wl.offline_access scope is specified, a refresh token is also provided.

Your app can read the authorization code from the returned URL, and use it to retrieve an access token by making a call that passes a URL similar to this one.

POST https://login.live.com/oauth20_token.srf

Content-type: application/x-www-form-urlencoded

client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&redirect_uri=https://login.live.com/oauth20_desktop.srf&code=AUTHORIZATION_CODE&grant_type=authorization_code

Finally, your app can read the token data from the returned URL and use that data to make further requests from the Live SDK by using the System.Net.WebRequest class.

If the wl.offline_accessscope was specified in the initial request, your app can convert the refresh token into an access token by making an HTTPPOST request like the one shown here.

POST https://login.live.com/oauth20_token.srf

Content-type: application/x-www-form-urlencoded

client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&redirect_uri=https://login.live.com/oauth20_desktop.srf&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

Building an app

In this walkthrough, you build a simple WPF app that enables signing in to a service, and then retrieves some user data after sign in is complete. The app also displays the access token. Before you start this exercise, you must visit the Microsoft account Developer Center to get a client ID and a client secret, if you don't have them already. Be sure to leave the Redirect Domain field blank, select Yes for the Mobile client app option, and make a note of your client ID and client secret.

Create a new project

  1. Start Visual Studio.

  2. Click File > New Project.

  3. In Installed Templates, click Visual C# > WPF Application.

  4. In the Name field, type DesktopDemo.

  5. Click OK to create the project.

Add the browser window

  1. In Solution Explorer, right-click the project name, select Add, then select New Item.

  2. In the Add New Item dialog box, select Window (WPF).

  3. In the Name field, enter BrowserWindow.xaml.

  4. Click Add to add the window to the project.

  5. Open BrowserWindow.xaml and replace the file's contents with the following Extensible Application Markup Language (XAML) code.

    <Window x:Class="DesktopDemo.BrowserWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Sign In" Height="460" Width="400">
        <Grid>
            <WebBrowser Height="420" HorizontalAlignment="Left" Name="webBrowser" VerticalAlignment="Top" Width="380" LoadCompleted="webBrowser_LoadCompleted" />
        </Grid>
    </Window>
    

    BrowserWindow.xaml contains a WebBrowser control, which is used to display the Microsoft account consent page.

  6. Open BrowserWindow.xaml.cs and replace the file's contents with the following code. Be sure to substitute your own client ID for the value of client_id.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Shapes;
    using System.Text.RegularExpressions;
    
    namespace DesktopDemo
    {
        public partial class BrowserWindow : Window
        {
            static string scope = "wl.basic";
            static string client_id = "YOUR_CLIENT_ID";
            static Uri signInUrl = new Uri(String.Format(@"https://login.live.com/oauth20_authorize.srf?client_id={0}&redirect_uri=https://login.live.com/oauth20_desktop.srf&response_type=code&scope={1}", client_id, scope));
            MainWindow mainWindow = new MainWindow();
    
            public BrowserWindow()
            {
                InitializeComponent();
                webBrowser.Navigate(signInUrl);
            }
    
            private void webBrowser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
            {
                if (e.Uri.AbsoluteUri.Contains("code="))
                {
                    if (App.Current.Properties.Contains("auth_code"))
                    {
                        App.Current.Properties.Clear();
                    }
                    string auth_code = Regex.Split(e.Uri.AbsoluteUri, "code=")[1];
                    App.Current.Properties.Add("auth_code", auth_code);
                    this.Close();
                }
            }
        }
    }
    

    The code in BrowserWindow.xaml.cs handles two basic tasks. When the window opens, BrowserWindow.xaml.cs directs the WebBrowser control to the Microsoft account sign-in page by using the URI value defined in the signInUrl variable. It then monitors the webBrowser_LoadCompleted event handler. After the user signs in, it parses the Representational State Transfer (REST) response to find the authorization code and then adds it to App.Current.Properties. Note that App.Current.Properties was used to keep this example simple. In an actual app, you would persist data by using a different mechanism, such as a database.

  7. Save the project.

Add the main window controls

  1. In Solution Explorer, right-click the project name, and then click Properties.

  2. On the Application tab, in the Target framework list, click .NET Framework 4. If you are prompted to enable Visual Studio to close and then reopen the project, click Yes.

  3. In Solution Explorer, right-click References, and then click Add Reference.

  4. In the .NET tab, click System.Web.Extensions.

  5. Click Add to add the reference.

  6. Open MainWindow.xaml to view the default form.

  7. Replace the file's contents with the following XAML code.

    <Window x:Class="DesktopDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Desktop App Demo" Height="500" Width="700" Unloaded="Window_Unloaded">
        <Grid>
            <Image Height="110" HorizontalAlignment="Left" Margin="12,12,0,0" Name="imgUser" Stretch="Fill" VerticalAlignment="Top" Width="110" />
            <TextBox Height="110" HorizontalAlignment="Left" Margin="12,128,0,0" Name="txtUserInfo" VerticalAlignment="Top" Width="654" TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" />
            <Button Content="Click to Sign In" Height="23" HorizontalAlignment="Center" Margin="261,99,260,0" Name="btnSignIn" VerticalAlignment="Top" Width="157" Click="btnSignIn_Click" />
            <TextBox Height="172" HorizontalAlignment="Left" Margin="12,244,0,0" Name="txtToken" VerticalAlignment="Top" Width="654" TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" />
            <Button Content="Clear App Settings" Height="23" HorizontalAlignment="Left" Margin="12,426,0,0" Name="btnClear" VerticalAlignment="Top" Width="162" Click="btnClear_Click" />
        </Grid>
    </Window>
    
  8. Save and close MainWindow.xaml.

Add initialization and request code

  1. In Solution Explorer, open MainWindow.xaml.cs.

  2. Add the following using statements after the default using statements but before the DesktopDemo namespace declaration.

    using System.Web.Script.Serialization;
    using System.Net;
    using System.IO;
    
  3. After the MainWindow class declaration, but before the MainWindow constructor, add the following variables.

    static string client_id = "YOUR CLIENT ID";
    static string client_secret = "YOUR CLIENT SECRET";
    static string accessTokenUrl = String.Format(@"https://login.live.com/oauth20_token.srf?client_id={0}&client_secret={1}&redirect_uri=https://login.live.com/oauth20_desktop.srf&grant_type=authorization_code&code=", client_id, client_secret);
    static string apiUrl = @"https://apis.live.net/v5.0/";
    public Dictionary<string, string> tokenData = new Dictionary<string, string>();
    
    

    The client_id and client_secret variables, as their names imply, represent your client ID and client secret. (Be sure to substitute your own client ID for the value of client_id and your own client secret for the value of client_secret.) The accessTokenUrl variable represents the base call to retrieve an access token. The tokenData variable is used to retrieve the access token to be stored for use later. The apiUrl variable represents the base call to retrieve user info.

  4. Add the following functions immediately after the MainWindow constructor.

    private void getAccessToken()
    {
        if (App.Current.Properties.Contains("auth_code"))
        {
            makeAccessTokenRequest(accessTokenUrl + App.Current.Properties["auth_code"]);
        }
    }
    
    private void makeAccessTokenRequest(string requestUrl)
    {
        WebClient wc = new WebClient();
        wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(accessToken_DownloadStringCompleted);
        wc.DownloadStringAsync(new Uri(requestUrl));
    }
    
    void accessToken_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
        tokenData = deserializeJson(e.Result);
        if (tokenData.ContainsKey("access_token"))
        {
            App.Current.Properties.Add("access_token", tokenData["access_token"]);
            getUserInfo();
        }
    }
    
    private Dictionary<string, string> deserializeJson(string json)
    {
        var jss = new JavaScriptSerializer();
        var d = jss.Deserialize<Dictionary<string, string>>(json);
        return d;
    }
    
    private void getUserInfo()
    {
        if (App.Current.Properties.Contains("access_token"))
        {
            makeApiRequest(apiUrl + "me?access_token=" + App.Current.Properties["access_token"]);
        }
    }
    
    private void makeApiRequest(string requestUrl)
    {
        WebClient wc = new WebClient();
        wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
        wc.DownloadStringAsync(new Uri(requestUrl));
    }
    
    void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
        changeView(e.Result);
    }
    
    

    The getAccessToken function uses the authorization code that was retrieved after the user signed in, along with calls to the makeAccessTokenRequest function, the accessToken_DownloadStringCompleted event handler, and the deserializeJson function, to get an access token. After the code gets the access token, the getUserInfo function calls the makeApiRequest function and the client_DownloadStringCompleted event handler to get the user's info. After the code gets the user's info, the changeView function displays the user's info, as described in the next section.

    Note

    If you are migrating from the legacy Windows Live ID Web Authentication SDK, you can use the techniques described in Single sign-on for apps and websites to return a uid value from the authentication_token property in the JSONtokenData variable that's referenced within the accessToken_DownloadStringCompleted event handler.

  5. Save MainWindow.xaml.cs.

Add code to update the UI

  1. Paste the following code after the client_DownloadStringCompleted event handler.

    private void changeView(string result)
    {
        btnSignIn.Visibility = Visibility.Collapsed;
        txtUserInfo.Text = result;
        string imgUrl = apiUrl + "me/picture?access_token=" + App.Current.Properties["access_token"];
        imgUser.Source = new BitmapImage(new Uri(imgUrl, UriKind.RelativeOrAbsolute));
        txtToken.Text += "access_token = " + App.Current.Properties["access_token"] + "\r\n\r\n";
    }
    
    

    The changeView function updates the UI to display the user data that is returned by the request.

  2. Paste the code for the following two functions after the changeView function.

    private void btnSignIn_Click(object sender, RoutedEventArgs e)
    {
        BrowserWindow browser = new BrowserWindow();
        browser.Closed += new EventHandler(browser_Closed);
        browser.Show();
    }
    
    private void btnClear_Click(object sender, RoutedEventArgs e)
    {
        App.Current.Properties.Clear();
        btnSignIn.Visibility = Visibility.Visible;
        txtToken.Text = "";
        imgUser.Source = null;
        txtUserInfo.Text = "";
    }
    

    These are the event handlers for each of the buttons. The btnSignIn_Click handler launches the BrowserWindow window, and the btnClear_Click handler deletes all session data and refreshes the UI. (btnClear_Click is intended as a convenience while you are experimenting with the code).

  3. Paste the following code after btnClear_Click.

    void browser_Closed(object sender, EventArgs e)
    {
        getAccessToken();
    }
    
    private void Window_Unloaded(object sender, RoutedEventArgs e)
    {
        Application.Current.Shutdown();
    }
    

    The browser_Closed event handler calls getAccessToken, which uses the authorization code to get the access token. (The Window_Unloaded event simply quits the app.)

  4. Now it's time to build and test the project. Press F5 to build and run the project. Click the Click to Sign In button. Sign in with a Microsoft account email address and password. The app displays the user's photo and other info along with the access token value.