Language: JavaScript and HTML | VB/C#/C++ and XAML
6 out of 11 rated this helpful - Rate this topic

Guidelines for the Microsoft account sign-in experience (Windows Store apps using C#/VB/C++ and XAML)

Your Windows Store apps using C++, C#, or Visual Basic can sign users in and out with their Microsoft accounts so that your app can access their data in Microsoft cloud services like Hotmail and Microsoft SkyDrive.

Apply these guidelines when you design your app's sign-in and sign-out experience so that it provides a user experience that's consistent with other Windows Store apps. These guidelines also help your app keep the user's data secure.

Overview

Accessing users' data from Microsoft cloud services like Hotmail and SkyDrive requires that users sign in with their Microsoft account and give consent to access the data that the app requires. To help users keep their data secure from other users of their computer, your Windows Store app should also make it possible for the user to sign out of the app. This topic describes how to do that.

Important  If your app does not enable users to sign out, it will be able access the users' data whenever they open the app from the user account with which they first signed in. Although this provides a great convenience to users who never share or lose their computer, it presents a possible security vulnerability if the computer is used by another person or if the computer is stolen. For these reasons, your Windows Store app should always indicate when it is signed in to a user's account and provide the option for the user to sign out.

These steps describe at a high level how your app can access the user's profile info. To see the detailed instructions, start here.

  1. Add the required settings commands to your app

    If your app is a Windows Store app that uses Microsoft cloud services like Hotmail and SkyDrive, it must have these two entries in its Settings pane.

    • Account

      The Account command in the Settings pane shows the Flyout in which users can sign in to and sign out of their Microsoft account.

    • Privacy statement

      The Privacy statement command in the Settings pane shows the Flyout that contains your app's privacy statement. Because your app will be accessing users' personal data, it must have a privacy statement.

  2. Provide a privacy statement

    Important  If your Windows Store app accesses users' personal data, you must provide a privacy statement when you submit your app to the Windows Store and the privacy statement must also be available from within your app. For more info about this and other Windows Store app requirements, see the Windows 8 app certification requirements.

  3. Sign the user in

    Your app can do this automatically when it starts, or it can allow the user to sign in only when it needs access to data that is stored in Microsoft cloud services like Hotmail and SkyDrive. The procedure for each method is described later in Signing users in.

  4. Sign the user out

    Consider how your app will be used. If it accesses data that the user might consider sensitive, your app should sign the user out automatically to prevent unauthorized access. But if the app is used in a more secure environment, you could leave it up to the user to sign out manually by using the Account settings command. The procedure for each method is described later in Signing users out.

    Important  

    Users should always understand when the app is connected to their Microsoft account and when it isn't.

  5. Show the sign-in state in the app's UI

    Add some type of indication to your app's UI to show users when they are signed in and the app can access their info.

    Note  It's important for your app to let users know when they are signed in. This could be done as simply as by displaying their name or by listing elements that come from data that is stored in their Microsoft cloud service. For example, if your app displays users' photos from their SkyDrive, it could display a list of their photos when they are signed in, and a message that they need to sign in if they are not signed in.

Add the required settings

This section describes how to add the required settings commands to the Settings pane.

  1. Create the Privacy Flyout.

    1. In Microsoft Visual Studio Express 2012 for Windows 8, in Solution Explorer, right-click the app and use the Add > New Item... command to add a new user control.
    2. In the Add New Item browser, select Installed > Visual C# > Windows Store to list the available items.
    3. Select User Control from the list, enter Privacy.xaml in the Name field, and click Add.
    4. Open Privacy.xaml, replace the UserControl element with this one, and change the specified elements to match your app.
      
      <!-- Replace the app class name in x:Class and xmlns:local    -->
      <!--   with the class name of your app                        -->
       <UserControl  
          x:Class="App1CS.Privacy"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:local="using:App1CS"
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
          mc:Ignorable="d"
          d:DesignHeight="768"
          d:DesignWidth="346">
        <!-- Modify this layout to match your app -->
          <UserControl.Resources>
              <Style x:Key="SettingsBackButtonStyle" TargetType="Button">
                  <Setter Property="MinWidth" Value="0"/>
                  <Setter Property="FontFamily" Value="Segoe UI Symbol"/>
                  <Setter Property="FontWeight" Value="Normal"/>
                  <Setter Property="FontSize" Value="26.66667"/>
                  <Setter Property="AutomationProperties.AutomationId" Value="BackButton"/>
                  <Setter Property="AutomationProperties.Name" Value="Back"/>
                  <Setter Property="AutomationProperties.ItemType" Value="Navigation Button"/>
                  <Setter Property="Template">
                      <Setter.Value>
                          <!-- This next block defines the back arrow used in the header -->
                          <ControlTemplate TargetType="Button">
                              <Grid x:Name="RootGrid" Width="30" Height="30">
                                  <Grid Margin="-6,-6,0,0">
                                      <TextBlock x:Name="BackgroundGlyph" Text="&amp;#xE0D4;" Foreground="Black"/>
                                      <TextBlock x:Name="NormalGlyph" Text="{StaticResource BackButtonSnappedGlyph}" Foreground="White"/>
                                      <TextBlock x:Name="ArrowGlyph" Text="&amp;#xE0C4;" Foreground="LightGray" Opacity="0"/>
                                  </Grid>
                                  <Rectangle
                                  x:Name="FocusVisualWhite"
                                  IsHitTestVisible="False"
                                  Stroke="White"
                                  StrokeEndLineCap="Square"
                                  StrokeDashArray="1,1"
                                  Opacity="0"
                                  StrokeDashOffset="1.5"/>
                                  <Rectangle
                                  x:Name="FocusVisualBlack"
                                  IsHitTestVisible="False"
                                  Stroke="Black"
                                  StrokeEndLineCap="Square"
                                  StrokeDashArray="1,1"
                                  Opacity="0"
                                  StrokeDashOffset="0.5"/>
      
                                  <VisualStateManager.VisualStateGroups>
                                      <VisualStateGroup x:Name="CommonStates">
                                          <VisualState x:Name="Normal" />
                                          <VisualState x:Name="PointerOver">
                                              <Storyboard>
                                                  <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
                                                      <DiscreteObjectKeyFrame KeyTime="0" Value="DarkGray"/>
                                                  </ObjectAnimationUsingKeyFrames>
                                                  <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalGlyph" Storyboard.TargetProperty="Foreground">
                                                      <DiscreteObjectKeyFrame KeyTime="0" Value="LightGray"/>
                                                  </ObjectAnimationUsingKeyFrames>
                                              </Storyboard>
                                          </VisualState>
                                          <VisualState x:Name="Pressed">
                                              <Storyboard>
                                                  <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
                                                      <DiscreteObjectKeyFrame KeyTime="0" Value="White"/>
                                                  </ObjectAnimationUsingKeyFrames>
                                                  <DoubleAnimation
                                                  Storyboard.TargetName="ArrowGlyph"
                                                  Storyboard.TargetProperty="Opacity"
                                                  To="1"
                                                  Duration="0"/>
                                                  <DoubleAnimation
                                                  Storyboard.TargetName="NormalGlyph"
                                                  Storyboard.TargetProperty="Opacity"
                                                  To="0"
                                                  Duration="0"/>
                                              </Storyboard>
                                          </VisualState>
                                          <VisualState x:Name="Disabled">
                                              <Storyboard>
                                                  <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Visibility">
                                                      <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                                                  </ObjectAnimationUsingKeyFrames>
                                              </Storyboard>
                                          </VisualState>
                                      </VisualStateGroup>
                                      <VisualStateGroup x:Name="FocusStates">
                                          <VisualState x:Name="Focused">
                                              <Storyboard>
                                                  <DoubleAnimation
                                                  Storyboard.TargetName="FocusVisualWhite"
                                                  Storyboard.TargetProperty="Opacity"
                                                  To="1"
                                                  Duration="0"/>
                                                  <DoubleAnimation
                                                  Storyboard.TargetName="FocusVisualBlack"
                                                  Storyboard.TargetProperty="Opacity"
                                                  To="1"
                                                  Duration="0"/>
                                              </Storyboard>
                                          </VisualState>
                                          <VisualState x:Name="Unfocused" />
                                          <VisualState x:Name="PointerFocused" />
                                      </VisualStateGroup>
                                  </VisualStateManager.VisualStateGroups>
                              </Grid>
                          </ControlTemplate>
                      </Setter.Value>
                  </Setter>
              </Style>
          </UserControl.Resources>
        <!-- This section describes the text and layout of the elements that are -->
        <!-- displayed in the Flyout window.                                     -->
          <Border BorderBrush="Black" BorderThickness="1,0,0,0">
              <Grid Background="Gray" VerticalAlignment="Stretch">
                  <!-- Root grid definition -->
                  <Grid.RowDefinitions>
                      <RowDefinition Height="80" />
                      <RowDefinition Height="*" />
                  </Grid.RowDefinitions>
      
                  <!-- Header area for panel -->
                  <Grid Background="Black" Grid.Row="0">
      
                      <Grid Margin="40,32,17,13">
      
                          <Grid.Transitions>
                              <TransitionCollection>
                                  <EntranceThemeTransition FromHorizontalOffset="50" />
                              </TransitionCollection>
                          </Grid.Transitions>
      
                          <Grid.ColumnDefinitions>
                              <ColumnDefinition Width="30" />
                              <ColumnDefinition Width="*" />
                              <ColumnDefinition />
                          </Grid.ColumnDefinitions>
      
                          <Button Click="PrivacyBackClicked" Margin="0,3,0,0" Grid.Column="0" Style="{StaticResource SettingsBackButtonStyle}" HorizontalAlignment="Left"   />
      
                          <TextBlock Margin="10,0,0,0" Grid.Column="1" FontFamily="Segoe UI" FontWeight="SemiLight" FontSize="24.6667" Text="Privacy" HorizontalAlignment="Left" />
      
                          <Image Source="Assets/SmallLogo.png" HorizontalAlignment="Right" Grid.Column="2" Margin="0,0,6,0" />
      
                      </Grid>
      
                  </Grid>
      
                  <!-- Settings panel content -->
                  <Grid Grid.Row="1" Margin="40,24,23,0" VerticalAlignment="Top">
                      <Grid.Transitions>
                          <TransitionCollection>
                              <EntranceThemeTransition FromHorizontalOffset="120" />
                          </TransitionCollection>
                      </Grid.Transitions>
                  <!-- Add your privacy statement text or a link to your privacy statement here  -->
                      <TextBlock x:Name="privacyStatementText">How we protect your data...</TextBlock>
                 </Grid>
      
              </Grid>
          </Border>
      </UserControl>
      
      
      
    5. Modify the contents of the privacyStatementText element to include your privacy statement.
    6. Finally, add the assembly reference and the arrow-button handler to the control's code-behind file, Privacy.xaml.cs, so the user can close the Flyout and return to the Settings pane.

      
      // add the assembly for the settings flyout
      using Windows.UI.ApplicationSettings;
      
      
      
      
      private void PrivacyBackClicked(object sender, RoutedEventArgs e)
      {
          if (this.Parent.GetType() == typeof(Popup))
          {
              ((Popup)this.Parent).IsOpen = false;
          }
          SettingsPane.Show();
      }
      
      

    Note  You can build your app now to make sure everything is OK so far. However, you won't yet see the Privacy command in the Settings pane.

  2. Create the Account Flyout.

    The code in this step defines the layout for the Account Flyout shown in this screen shot.

    Screen shot of the Account Flyout that is created in this step.
    1. In Solution Explorer, right-click the app and use the Add > New Item command to add a new user control.
    2. In the Add New Item browser, select Installed > Visual C# > Windows Store to list the available items.
    3. Select User Control from the list, enter Account.xaml in the Name field, and click Add.
    4. Open Account.xaml, replace the UserControl element with this one, and change the specified elements to match your app.
      
      <!-- Replace the app class name in x:Class and xmlns:local    -->
      <!--   with the class name of your app                        -->
      <UserControl
          x:Class="App1CS.Account"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:local="using:App1CS"
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
          mc:Ignorable="d"
          d:DesignHeight="768"
          d:DesignWidth="346">
          <!-- Modify this layout to match your app -->
          <UserControl.Resources>
              <Style x:Key="SettingsBackButtonStyle" TargetType="Button">
                  <Setter Property="MinWidth" Value="0"/>
                  <Setter Property="FontFamily" Value="Segoe UI Symbol"/>
                  <Setter Property="FontWeight" Value="Normal"/>
                  <Setter Property="FontSize" Value="26.66667"/>
                  <Setter Property="AutomationProperties.AutomationId" Value="BackButton"/>
                  <Setter Property="AutomationProperties.Name" Value="Back"/>
                  <Setter Property="AutomationProperties.ItemType" Value="Navigation Button"/>
                  <Setter Property="Template">
                      <Setter.Value>
                          <!-- This next block defines the back arrow used in the header -->
                          <ControlTemplate TargetType="Button">
                              <Grid x:Name="RootGrid" Width="30" Height="30">
                                  <Grid Margin="-6,-6,0,0">
                                      <TextBlock x:Name="BackgroundGlyph" Text="&#xE0D4;" Foreground="Black"/>
                                      <TextBlock x:Name="NormalGlyph" Text="{StaticResource BackButtonSnappedGlyph}" Foreground="White"/>
                                      <TextBlock x:Name="ArrowGlyph" Text="&#xE0C4;" Foreground="LightGray" Opacity="0"/>
                                  </Grid>
                                  <Rectangle
                                  x:Name="FocusVisualWhite"
                                  IsHitTestVisible="False"
                                  Stroke="White"
                                  StrokeEndLineCap="Square"
                                  StrokeDashArray="1,1"
                                  Opacity="0"
                                  StrokeDashOffset="1.5"/>
                                  <Rectangle
                                  x:Name="FocusVisualBlack"
                                  IsHitTestVisible="False"
                                  Stroke="Black"
                                  StrokeEndLineCap="Square"
                                  StrokeDashArray="1,1"
                                  Opacity="0"
                                  StrokeDashOffset="0.5"/>
      
                                  <VisualStateManager.VisualStateGroups>
                                      <VisualStateGroup x:Name="CommonStates">
                                          <VisualState x:Name="Normal" />
                                          <VisualState x:Name="PointerOver">
                                              <Storyboard>
                                                  <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
                                                      <DiscreteObjectKeyFrame KeyTime="0" Value="DarkGray"/>
                                                  </ObjectAnimationUsingKeyFrames>
                                                  <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalGlyph" Storyboard.TargetProperty="Foreground">
                                                      <DiscreteObjectKeyFrame KeyTime="0" Value="LightGray"/>
                                                  </ObjectAnimationUsingKeyFrames>
                                              </Storyboard>
                                          </VisualState>
                                          <VisualState x:Name="Pressed">
                                              <Storyboard>
                                                  <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
                                                      <DiscreteObjectKeyFrame KeyTime="0" Value="White"/>
                                                  </ObjectAnimationUsingKeyFrames>
                                                  <DoubleAnimation
                                                  Storyboard.TargetName="ArrowGlyph"
                                                  Storyboard.TargetProperty="Opacity"
                                                  To="1"
                                                  Duration="0"/>
                                                  <DoubleAnimation
                                                  Storyboard.TargetName="NormalGlyph"
                                                  Storyboard.TargetProperty="Opacity"
                                                  To="0"
                                                  Duration="0"/>
                                              </Storyboard>
                                          </VisualState>
                                          <VisualState x:Name="Disabled">
                                              <Storyboard>
                                                  <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Visibility">
                                                      <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                                                  </ObjectAnimationUsingKeyFrames>
                                              </Storyboard>
                                          </VisualState>
                                      </VisualStateGroup>
                                      <VisualStateGroup x:Name="FocusStates">
                                          <VisualState x:Name="Focused">
                                              <Storyboard>
                                                  <DoubleAnimation
                                                  Storyboard.TargetName="FocusVisualWhite"
                                                  Storyboard.TargetProperty="Opacity"
                                                  To="1"
                                                  Duration="0"/>
                                                  <DoubleAnimation
                                                  Storyboard.TargetName="FocusVisualBlack"
                                                  Storyboard.TargetProperty="Opacity"
                                                  To="1"
                                                  Duration="0"/>
                                              </Storyboard>
                                          </VisualState>
                                          <VisualState x:Name="Unfocused" />
                                          <VisualState x:Name="PointerFocused" />
                                      </VisualStateGroup>
                                  </VisualStateManager.VisualStateGroups>
                              </Grid>
                          </ControlTemplate>
                      </Setter.Value>
                  </Setter>
              </Style>
          </UserControl.Resources>
        <!-- This section describes the text and layout of the elements that are -->
        <!-- displayed in the Flyout window.                                     -->
          <Border BorderBrush="Black" BorderThickness="1,0,0,0">
              <Grid Background="Gray" VerticalAlignment="Stretch">
                  <!-- Root grid definition -->
                  <Grid.RowDefinitions>
                      <RowDefinition Height="80" />
                      <RowDefinition Height="*" />
                  </Grid.RowDefinitions>
      
                  <!-- Header area for panel -->
                  <Grid Background="Black" Grid.Row="0">
      
                      <Grid Margin="40,32,17,13">
      
                          <Grid.Transitions>
                              <TransitionCollection>
                                  <EntranceThemeTransition FromHorizontalOffset="50" />
                              </TransitionCollection>
                          </Grid.Transitions>
      
                          <Grid.ColumnDefinitions>
                              <ColumnDefinition Width="30" />
                              <ColumnDefinition Width="*" />
                              <ColumnDefinition />
                          </Grid.ColumnDefinitions>
      
                          <Button Click="AccountBackClicked" Margin="0,3,0,0" Grid.Column="0" Style="{StaticResource SettingsBackButtonStyle}" HorizontalAlignment="Left"   />
      
                          <TextBlock Margin="10,0,0,0" Grid.Column="1" FontFamily="Segoe UI" FontWeight="SemiLight" FontSize="24.6667" Text="Account" HorizontalAlignment="Left" />
      
                          <Image Source="Assets/SmallLogo.png" HorizontalAlignment="Right" Grid.Column="2" Margin="0,0,6,0" />
      
                      </Grid>
      
                  </Grid>
      
                  <!-- Settings panel content -->
                  <Grid Grid.Row="1" Margin="40,24,23,0" VerticalAlignment="Top" Height="Auto">
                      <Grid.RowDefinitions>
                          <RowDefinition Height="*" />
                          <RowDefinition Height="*" />                    
                      </Grid.RowDefinitions>
                      <Grid.Transitions>
                          <TransitionCollection>
                              <EntranceThemeTransition FromHorizontalOffset="120" />
                          </TransitionCollection>
                      </Grid.Transitions>
                      <TextBlock x:Name="userName" Grid.Row="1" Margin="0,0,0,0" >You're not signed in.</TextBlock>
                      <!-- both buttons are defined to occupy the same place in the UI;            -->
                      <!-- however only one is visible at a time. To prevent flicker or confusion -->
                      <!-- they are defined as Collapsed so neither is visible by default          -->
                      <Button x:Name="signInBtn"  Click="SignInClick"  Content="Sign in"  Grid.Row="1" Margin="0,20,0,-38" Visibility="Collapsed"/>
                      <Button x:Name="signOutBtn" Click="SignOutClick" Content="Sign out" Grid.Row="1" Margin="0,20,0,-38" Visibility="Collapsed"/>
                  </Grid>
              </Grid>
          </Border>
       </UserControl>
      
      
      
    5. Finally, add the assembly reference and the arrow-button handler to the control's code-behind file, Account.xaml.cs, so the user can close the Flyout and return to the Settings pane.

      
      // Add the assembly for the <mark type="ui_item">Settings</mark> pane.
      using Windows.UI.ApplicationSettings;
      
      
      
      
      private void AccountBackClicked(object sender, RoutedEventArgs e)
      {
          if (this.Parent.GetType() == typeof(Popup))
          {
              ((Popup)this.Parent).IsOpen = false;
          }
          SettingsPane.Show();
      }
      
      

    Note  You can't build your app yet because you must first add the handlers for the Sign in and Sign out buttons. This is described in the next steps.

  3. This step describes how to get info from the user's profile so you can use that info to fill in the text fields and show the correct button on the Account Flyout.

    Add the references to the Live Software Development Kit (SDK), and then create a method to get the user's name from his or her Microsoft account profile and write it to a TextBlock object in the UI. The method will sign the user in, if requested.

    Define this method in the app's main code file—App.xaml.cs, for example. This enables all the pages in your app to call the method to display the user's name (if the user is signed in to his or her Microsoft account), or display the message that the user isn't signed in (if her or she is not).

    This example signs the user in with a wl_basic scope, which is the smallest scope necessary to access the user's profile info. To protect the user's data from unauthorized access, your app should request the most restrictive scope that allows access to the desired data.

    Important  It's important that your app get the user's sign-in status directly from the Live SDK and that it doesn't cache the value. This practice prevents your app's view of the user's sign-in state from getting out of sync with the user's actual sign-in state, which is managed by the Live SDK.

    
    using Microsoft.Live;
    using System.Threading.Tasks;
    
    
    
    
    public static async Task updateUserName (TextBlock userName, Boolean signIn)
    {
        try
        {
            // Open Live Connect SDK client.
            LiveAuthClient LCAuth = new LiveAuthClient();
            LiveLoginResult LCLoginResult = await LCAuth.InitializeAsync();
            try
            {
                LiveLoginResult loginResult = null;
                if (signIn)
                {
                    // Sign in to the user's Microsoft account with the required scope.
                    //  
                    //  This call will display the Microsoft account sign-in screen if 
                    //   the user is not already signed in to their Microsoft account 
                    //   through Windows 8.
                    // 
                    //  This call will also display the consent dialog, if the user has 
                    //   has not already given consent to this app to access the data 
                    //   described by the scope.
                    // 
                    //  Change the parameter of LoginAsync to include the scopes 
                    //   required by your app.
                    loginResult = await LCAuth.LoginAsync(new string[] { "wl.basic" });
                }
                else
                {
                    // If we don't want the user to sign in, continue with the current 
                    //  sign-in state.
                    loginResult = LCLoginResult;
                }
                if (loginResult.Status == LiveConnectSessionStatus.Connected)
                {
                    // Create a client session to get the profile data.
                    LiveConnectClient connect = new LiveConnectClient(LCAuth.Session);
    
                    // Get the profile info of the user.
                    LiveOperationResult operationResult = await connect.GetAsync("me");
                    dynamic result = operationResult.Result;
                    if (result != null)
                    {
                        // Update the text of the object passed in to the method. 
                        userName.Text = string.Join(" ", "Hello", result.name, "!");
                    }
                    else
                    {
                        // Handle the case where the user name was not returned. 
                    }
                }
                else
                {
                    // The user hasn't signed in so display this text 
                    //  in place of his or her name.
                    userName.Text = "You're not signed in.";
                }
            }
            catch (LiveAuthException exception)
            {
                // Handle the exception. 
            }
        }
        catch (LiveAuthException exception)
        {
                // Handle the exception. 
        }
        catch (LiveConnectException exception)
        {
                // Handle the exception. 
        }
    }
    
    
    

    Tip  You can call this method from the code behind your display pages to show the user whether they are signed in to their Microsoft account or not.

  4. Add the sign-in and sign-out logic to the Account.xaml.cs code-behind file.

    1. Add the references to the Live SDK, and create a method to query the user's sign-in state and update the UI of the Account Flyout to match.

      
      using Microsoft.Live;
      using System.Threading.Tasks;
      
      
      
      
      private async Task SetNameField(Boolean login) {
          // If login == false, just update the name field. 
          await App.updateUserName(this.userName, login);
      
          // Test to see if the user can sign out.
          Boolean userCanSignOut = true;
      
          LiveAuthClient LCAuth = new LiveAuthClient();
          LiveLoginResult LCLoginResult = await LCAuth.InitializeAsync();
      
          if (LCLoginResult.Status == LiveConnectSessionStatus.Connected)
          {
              userCanSignOut = LCAuth.CanLogout;
          }
          
          if (this.userName.Text.Equals("You're not signed in."))
          {
              // Show sign-in button.
              signInBtn.Visibility = Windows.UI.Xaml.Visibility.Visible;
              signOutBtn.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
          }
          else
          {
              // Show sign-out button if they can sign out.
              signOutBtn.Visibility = (userCanSignOut ? Windows.UI.Xaml.Visibility.Visible : Windows.UI.Xaml.Visibility.Collapsed);
              signInBtn.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
          }
      }
      
      
      
    2. Add this method call to the constructor Account() to initialize the Flyout when a user opens it from the Settings pane.
      
      SetNameField(false);
       
      
      
    3. Add the code to handle the event that fires when the Sign in button is tapped.

      This method calls SetNameField to sign the user in and update the Account Flyout UI.

      
      private async void SignInClick(object sender, RoutedEventArgs e)
      {
        // This call will sign the user in and update the Account flyout UI.
        await SetNameField(true);
      }
      
      
    4. Add the code to sign the user out when the Sign out button is tapped.

      
      private async void SignOutClick(object sender, RoutedEventArgs e)
      {
          try
          {
              // Initialize access to the Live Connect SDK.
              LiveAuthClient LCAuth = new LiveAuthClient();
              LiveLoginResult LCLoginResult = await LCAuth.InitializeAsync();
              // Sign the user out, if he or she is connected;
              //  if not connected, skip this and just update the UI
              if (LCLoginResult.Status == LiveConnectSessionStatus.Connected)
              {
                  LCAuth.Logout();
              }
      
              // At this point, the user should be disconnected and signed out, so
              //  update the UI.
              this.userName.Text = "You're not signed in.";
      
              // Show sign-in button.
              signInBtn.Visibility = Windows.UI.Xaml.Visibility.Visible;
              signOutBtn.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
          }
          catch (LiveConnectException x)
          {
              // Handle exception.
          }
      }
      
      
      

    At this point, you should be able to build your app. However, the commands for the Account and Privacy Flyouts will not yet appear in the Settings pane. They are defined in the next step.

  5. Add the commands to the Settings pane and register the settings event handler.

    The code in this step adds the Account and Privacy commands to the Settings pane as shown in this screen shot.

    Settings charm showing Account and Privacy commands that are added in this step.

    In the app's main program file—for example, App.xaml.cs—add this code to handle the event that is fired when the Settings pane is opened.

    
    // Add the assembly for the Settings Flyout.
    using Windows.UI.ApplicationSettings;
    
    
    
    
    
    // Declare these class variables 
    //  for the Settings Flyouts to use.
    Rect _windowBounds;
    double _settingsWidth = 346;
    Popup _settingsPopup;
    
    
    
    
    
    // Define the event handler to add the new commands to the Settings pane
    //  when it opens.
    void AppCommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
    {
        // If your app already has some settings defined, add these blocks of code
        //  to your existing event handler in the order you want them to appear
        //  in the Settings pane.
    
        // Account settings command
        SettingsCommand cmd = new SettingsCommand("account", "Account", (x) =>
        {
            _settingsPopup = new Popup();
            _settingsPopup.Closed += OnPopupClosed;
            Window.Current.Activated += OnWindowActivated;
            _settingsPopup.IsLightDismissEnabled = true;
            _settingsPopup.Width = _settingsWidth;
            _settingsPopup.Height = _windowBounds.Height;
    
            Account mypane = new Account();
            mypane.Width = _settingsWidth;
            mypane.Height = _windowBounds.Height;
    
            _settingsPopup.Child = mypane;
            _settingsPopup.SetValue(Canvas.LeftProperty, _windowBounds.Width - _settingsWidth);
            _settingsPopup.SetValue(Canvas.TopProperty, 0);
            _settingsPopup.IsOpen = true;
        });
        args.Request.ApplicationCommands.Add(cmd);
    
        // Privacy settings command.
        cmd = new SettingsCommand("privacy", "Privacy", (x) =>
        {
            _settingsPopup = new Popup();
            _settingsPopup.Closed += OnPopupClosed;
            Window.Current.Activated += OnWindowActivated;
            _settingsPopup.IsLightDismissEnabled = true;
            _settingsPopup.Width = _settingsWidth;
            _settingsPopup.Height = _windowBounds.Height;
    
            Privacy mypane = new Privacy();
            mypane.Width = _settingsWidth;
            mypane.Height = _windowBounds.Height;
    
            _settingsPopup.Child = mypane;
            _settingsPopup.SetValue(Canvas.LeftProperty, _windowBounds.Width - _settingsWidth);
            _settingsPopup.SetValue(Canvas.TopProperty, 0);
            _settingsPopup.IsOpen = true;
        });
        args.Request.ApplicationCommands.Add(cmd);
    }
    
    
    
    
    
    // Catch resize events to update the Flyout window size.
    void OnWindowSizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
    {
      _windowBounds = Window.Current.Bounds;
    }
    
    // Handle Flyout window activation. 
    private void OnWindowActivated(object sender, Windows.UI.Core.WindowActivatedEventArgs e)
    {
      if (e.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.Deactivated)
      {
         _settingsPopup.IsOpen = false;
      }
    }
    
    // Handle Flyout window closing.
    private void OnPopupClosed(object sender, object e)
    {
      Window.Current.Activated -= OnWindowActivated;
    }
    
    
    
    
    // After the call to Window.Current.Activate() in the OnLaunched event handler,
    //  add this code to initialize the Flyout window size and register the event 
    //  handler methods.
    _windowBounds = Window.Current.Bounds;
    Window.Current.SizeChanged += OnWindowSizeChanged;
    SettingsPane.GetForCurrentView().CommandsRequested += AppCommandsRequested;
    
    

    Build your app and test the Flyouts that you just added.

  6. When the app runs and the user isn't signed in to his or her Microsoft account, the user will see a Flyout similar to this one when he or she taps the Account command in the Settings pane.

    Screen shot showing the user sign-in experience.

    If the user taps the Sign in button, the following screens appear.

    1. The Microsoft account sign-in UI.

      Screen shot of the Microsoft account sign-in UI.

    2. The Live Connect consent UI, if the user hasn't already given consent to this app.

      Screen shot  of Live Connect consent UI.

    3. After the user has signed in and given consent, he or she returns to the app.
  7. If the user is already signed in to a Microsoft account and is able to sign out, a Flyout similar to this one appears.

    Screen shot showing the user sign-out experience when the user can sign out.

  8. If the user is already signed in to a Microsoft account and is not able to sign out, a Flyout similar to this one appears.

    Screen shot showing the user sign-out experience when the user cannot sign out.

  9. After the user has signed in, update the app's UI to show the user's name.

    Screen shot of app with user name displayed.

Note  This code examples in this step just define the Flyouts for the Settings pane. You'll need to add the markup and the code to your app's display pages to show the user's name.

Signing users in

There are two approaches to signing users in to your Windows Store app. The one you pick depends on when your app needs the user to sign in.

  • If your app works when the user is not signed in, but the user must sign in to enable specific scenarios or features, have them sign in through an Account UI from the Settings pane described earlier.

    For more info about signing users in, see Signing users in in the Live Connect documentation.

  • If your app doesn't work or doesn't provide a complete experience until the user signs in, show the Microsoft account sign-in dialog immediately after the app starts. To show this dialog, call the Microsoft.Live.LiveAuthClient.LoginAsync method.

    Here's an example.

    
    public LiveConnectSession Session
    {
         get
         {
             return _session;
         }
         set
         {
             _session = value;
         }
    }
    
    private async void InitAuth()
    {
        if (!Windows.ApplicationModel.DesignMode.DesignModeEnabled)
        {
           authClient = new LiveAuthClient();
           LiveLoginResult authResult = 
               await authClient.LoginAsync(new List<string>() { "wl.signin", "wl.basic", "wl.skydrive" });
           if (authResult.Status == LiveConnectSessionStatus.Connected)
           {
               this.Session = authResult.Session;
           }
        }
    }
    
    

    For more info, see Signing users in in the Live Connect documentation.

  • If your app works without needing the user to sign in first, but provides specific commands that integrate with Microsoft cloud services like Hotmail and SkyDrive, your app can show the Microsoft account sign-in UI when such a command is given. For example, a photo-editing app might have a Save photo to SkyDrive command in its app bar. To support this scenario, add the code from this example to the app bar command handler for that command to sign the user in to his or her Microsoft account just before the code to save the photo. (The photo-saving code is not shown in this example.)

    Here's an example that signs the user in from an app bar command.

    
    private void AppBarSaveButton_Click(object sender, RoutedEventArgs e)
    {
        InitAuth();
    }
    
    private async void InitAuth()
    {
        if (!Windows.ApplicationModel.DesignMode.DesignModeEnabled)
        {
            authClient = new LiveAuthClient();
            LiveLoginResult authResult = 
                await authClient.LoginAsync(new List<string>() { "wl.signin", "wl.basic", "wl.skydrive" });
            if (authResult.Status == LiveConnectSessionStatus.Connected)
            {
                // An app-level property for the session.
                App.Session = authResult.Session;
            }
        }
    }
    
    

    With single sign-on, users see the sign-in UI or the consent UI only if they need to sign in or grant consent. If they are already signed in to their Microsoft account and have given consent for the app to access their data, they don't see any additional UI.

    Important  

    Make sure it is clear to the user when they are signed in to their Microsoft account.

    For more info, see Signing users in in the Live Connect documentation.

    To customize the appearance of an app bar button, see Live Connect Implementation and Branding guidelines for a zip file containing approved icons.

Signing users out

In Windows 8, if an app can connect to resources by using the user's Microsoft account, it should provide the user with a way to sign out.

Note  If the user signs in to Windows 8 with a Microsoft account or a local or domain account that is connected to a Microsoft account, providing a custom sign-out button has no effect.

To sign a user out, call the Microsoft.Live.LiveAuthClient.Logout() method.

Things to avoid

Make sure your app:

  • Doesn't display text, controls, or sign-in and sign-out dialogs other than those previously described here. Using the Microsoft account sign-in experience helps reassure your users that your app can't directly access their Microsoft account credentials.
  • Doesn't display custom sign-in or sign-out controls anywhere other than the Settings pane or as part of the app's task-command flow.

 

 

Build date: 3/5/2013

© 2013 Microsoft. All rights reserved.