다음을 통해 공유


Authentication using Facebook, Google and Microsoft account in WP8.0 App (MVVM)


Introduction

This sample show how to connect one Windows Phone 8.0 app to Facebook, Google and Microsoft account.

*Main Features: Login/Logout and has an about page with feedback, share in social networks, review and share by email.
*

Building the Sample

You only need Visual Studio 2012/Visual Studio 2013 and Windows 8/Windows 8.1, both the RTM version.

This sample requires the installation for **** Live SDK (http://msdn.microsoft.com/en-US/onedrive/dn630256).*** ***

*Source Code
*

Description

This sample show to connect one Windows Phone 8.0 app to Facebook, Google and Microsoft account.

Main Features:

  • Login/Logout (for logout i added some workaround to fixes the logout providers from sdks!)
  • About page with feedback, share in social networks, review and share by email (not important here, but is included in code)

Note: This sample uses MVVM Light and Cimbalino Windows Phone Toolkit.

For this sample was used:

For each provider is needed to get the app id/client id/client secret in their websites:

For Google go to https://console.developers.google.com/project and create a new project (Apis & auth > credentials)

http://i1.code.msdn.s-msft.com/wpapps/authentication-using-cd382133/image/file/115602/1/auth1.png

For Facebook go to https://developers.facebook.com/and create a new app.

*For Live SDK go to https://account.live.com/developers/applications/index and create one or use an existing app
*

Before you start you should change the Constant file to add client ids / client secret / app id, without it the app fails!!

This file is inside the Resource folder.**
**

C#

/// <summary> 
/// Defines the constants strings used in the app. 
/// </summary> 
public class  Constants 
{ 
        /// <summary> 
        /// The facebook app id. 
        /// </summary> 
        public const  string FacebookAppId = "<app id>"; 
  
        /// <summary> 
        /// The google client identifier. 
        /// </summary> 
        public const  string GoogleClientId = "<client id>"; 
  
        /// <summary> 
        /// The google token file name. 
        /// </summary> 
        public const  string GoogleTokenFileName = "Google.Apis.Auth.OAuth2.Responses.TokenResponse-user"; 
  
        /// <summary> 
        /// The google client secret. 
        /// </summary> 
        public const  string GoogleClientSecret = "<client secret>"; 
  
        /// <summary> 
        /// The microsoft client identifier. 
        /// </summary> 
        public const  string MicrosoftClientId = "<client id>"; 
  
      ... 
}

Now let's see how to connect to each provide. For help, i created a SessionService that manage the Login and Logout using a provider value, this is nice because in LoginView i set the buttons to the same command and for each command i set the provider in commandparameter. With it the LoginView and LoginViewModel are more clear and simple. Another thing is for example if i need to connect to my server to accept the user i can do it in session manager after the authentication, without to add the code to each provider.

The classes created:

  • FacebookService has all code related with authentication with Facebook account;
  • MicrosoftService has all code related with authentication with Microsoft account;
  • GoogleService has all code related with authentication with Google account;
  • SessionService call the methods login or logout for the provide requested;

The FacebookService is:

C#

/// <summary> 
/// Defines the Facebook Service. 
/// </summary> 
public class  FacebookService : IFacebookService 
{ 
        private readonly  ILogManager _logManager; 
        private readonly  FacebookSessionClient _facebookSessionClient; 
  
        /// <summary> 
        /// Initializes a new instance of the <see cref="FacebookService"/> class. 
        /// </summary> 
        /// <param name="logManager"> 
        /// The log manager. 
        /// </param> 
        public FacebookService(ILogManager logManager) 
        { 
            _logManager = logManager; 
            _facebookSessionClient = new  FacebookSessionClient(Constants.FacebookAppId); 
        } 
  
        /// <summary> 
        /// The login sync. 
        /// </summary> 
        /// <returns> 
        /// The <see cref="Task"/> object. 
        /// </returns> 
        public async Task<Session> LoginAsync() 
        { 
            Exception exception; 
            Session sessionToReturn = null; 
            try
            { 
                var session = await _facebookSessionClient.LoginAsync("user_about_me,read_stream"); 
                sessionToReturn = new  Session 
                { 
                    AccessToken = session.AccessToken, 
                    Id = session.FacebookId, 
                    ExpireDate = session.Expires, 
                    Provider = Constants.FacebookProvider 
                }; 
  
                return sessionToReturn; 
            } 
            catch (InvalidOperationException) 
            { 
                throw; 
            } 
            catch (Exception ex) 
            { 
                exception = ex; 
            } 
            await _logManager.LogAsync(exception); 
            return sessionToReturn; 
        } 
  
        /// <summary> 
        /// Logouts this instance. 
        /// </summary> 
        public async void Logout() 
        { 
            Exception exception = null; 
            try
            { 
                _facebookSessionClient.Logout(); 
  
                // clean all cookies from browser, is a workaround 
                await new  WebBrowser().ClearCookiesAsync(); 
            } 
            catch (Exception ex) 
            { 
                exception = ex; 
            } 
            if (exception != null) 
            { 
                await _logManager.LogAsync(exception); 
            } 
        } 
}

Note:  In logout i added a workaround to clear all cookies in browser, if i don´t this in the first time you can login with account you want but in the next time it will use the account used in last login.

The GoogleService is:

C#

/// <summary> 
/// The google service. 
/// </summary> 
public class  GoogleService : IGoogleService 
{ 
        private readonly  ILogManager _logManager; 
        private readonly  IStorageService _storageService; 
        private UserCredential _credential; 
        private Oauth2Service _authService; 
        private Userinfoplus _userinfoplus; 
  
        /// <summary> 
        /// Initializes a new instance of the <see cref="GoogleService" /> class. 
        /// </summary> 
        /// <param name="logManager">The log manager.</param> 
        /// <param name="storageService">The storage service.</param> 
        public GoogleService(ILogManager logManager, IStorageService storageService) 
        { 
            _logManager = logManager; 
            _storageService = storageService; 
        } 
  
        /// <summary> 
        /// The login async. 
        /// </summary> 
        /// <returns> 
        /// The <see cref="Task"/> object. 
        /// </returns> 
        public async Task<Session> LoginAsync() 
        { 
            Exception exception = null; 
            try
            { 
                // Oauth2Service.Scope.UserinfoEmail 
                _credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets 
                { 
                    ClientId = Constants.GoogleClientId, 
                    ClientSecret = Constants.GoogleClientSecret 
                }, new[] { Oauth2Service.Scope.UserinfoProfile }, "user", CancellationToken.None); 
                  
                var session = new  Session 
                { 
                    AccessToken = _credential.Token.AccessToken, 
                    Provider = Constants.GoogleProvider, 
                    ExpireDate = 
                        _credential.Token.ExpiresInSeconds != null
                            ? new  DateTime(_credential.Token.ExpiresInSeconds.Value) 
                            : DateTime.Now.AddYears(1), 
                    Id = string.Empty 
                }; 
  
                return session; 
            } 
            catch (TaskCanceledException taskCanceledException)  
            { 
                throw new  InvalidOperationException("Login canceled.", taskCanceledException); 
            } 
            catch (Exception ex) 
            { 
                exception = ex; 
            } 
            await _logManager.LogAsync(exception); 
            return null; 
        } 
  
        /// <summary> 
        /// Gets the user information. 
        /// </summary> 
        /// <returns> 
        /// The user info. 
        /// </returns> 
        public async Task<Userinfoplus> GetUserInfo() 
        { 
            _authService = new  Oauth2Service(new  BaseClientService.Initializer() 
            { 
                HttpClientInitializer = _credential, 
                ApplicationName = AppResources.ApplicationTitle, 
            }); 
            _userinfoplus = await _authService.Userinfo.V2.Me.Get().ExecuteAsync(); 
  
            return _userinfoplus; 
        } 
  
        /// <summary> 
        /// The logout. 
        /// </summary> 
        public async void Logout() 
        { 
            await new  WebBrowser().ClearCookiesAsync(); 
            if (_storageService.FileExists(Constants.GoogleTokenFileName)) 
            { 
                _storageService.DeleteFile(Constants.GoogleTokenFileName); 
            } 
        } 
}

Note: In the logout for Google provide there isn´t a logout method, the solution is to remove all cookies and remove the file created in login operation.

The MicrosoftService is:

C#

/// <summary> 
/// The microsoft service. 
/// </summary> 
public class  MicrosoftService : IMicrosoftService 
{ 
        private readonly  ILogManager _logManager; 
        private LiveAuthClient _authClient; 
        private LiveConnectSession _liveSession; 
  
        /// <summary> 
        /// Defines the scopes the application needs. 
        /// </summary> 
        private static  readonly string[] Scopes = { "wl.signin",  "wl.basic", "wl.offline_access" }; 
          
        /// <summary> 
        /// Initializes a new instance of the <see cref="MicrosoftService"/> class. 
        /// </summary> 
        /// <param name="logManager"> 
        /// The log manager. 
        /// </param> 
        public MicrosoftService(ILogManager logManager) 
        { 
            _logManager = logManager; 
        } 
  
        /// <summary> 
        /// The login async. 
        /// </summary> 
        /// <returns> 
        /// The <see cref="Task"/> object. 
        /// </returns> 
        public async Task<Session> LoginAsync() 
        { 
            Exception exception = null; 
            try
            { 
                _authClient = new  LiveAuthClient(Constants.MicrosoftClientId); 
                var loginResult = await _authClient.InitializeAsync(Scopes); 
                var result = await _authClient.LoginAsync(Scopes); 
                if (result.Status == LiveConnectSessionStatus.Connected) 
                { 
                    _liveSession = loginResult.Session; 
                    var session = new  Session 
                    { 
                        AccessToken = result.Session.AccessToken, 
                        ExpireDate = result.Session.Expires.DateTime, 
                        Provider = Constants.MicrosoftProvider, 
                    }; 
  
                    return session; 
                } 
            } 
            catch (LiveAuthException ex) 
            { 
                throw new  InvalidOperationException("Login canceled.", ex); 
            } 
            catch (Exception e) 
            { 
                exception = e; 
            } 
  
            await _logManager.LogAsync(exception); 
            return null; 
        } 
  
        /// <summary> 
        /// The logout. 
        /// </summary> 
        public async void Logout() 
        { 
            if (_authClient == null) 
            { 
                _authClient = new  LiveAuthClient(Constants.MicrosoftClientId); 
                var loginResult = await _authClient.InitializeAsync(Scopes); 
            } 
  
            _authClient.Logout(); 
        } 
}

The SessionService is:

C#

/// <summary> 
/// The service session. 
/// </summary> 
public class  SessionService : ISessionService 
{ 
        private readonly  IApplicationSettingsService _applicationSettings; 
        private readonly  IFacebookService _facebookService; 
        private readonly  IMicrosoftService _microsoftService; 
        private readonly  IGoogleService _googleService; 
        private readonly  ILogManager _logManager; 
          
        /// <summary> 
        /// Initializes a new instance of the <see cref="SessionService" /> class. 
        /// </summary> 
        /// <param name="applicationSettings">The application settings.</param> 
        /// <param name="facebookService">The facebook service.</param> 
        /// <param name="microsoftService">The microsoft service.</param> 
        /// <param name="googleService">The google service.</param> 
        /// <param name="logManager">The log manager.</param> 
        public SessionService(IApplicationSettingsService applicationSettings, 
            IFacebookService facebookService, 
            IMicrosoftService microsoftService, 
            IGoogleService googleService, ILogManager logManager) 
        { 
            _applicationSettings = applicationSettings; 
            _facebookService = facebookService; 
            _microsoftService = microsoftService; 
            _googleService = googleService; 
            _logManager = logManager; 
        } 
  
        /// <summary> 
        /// Gets the session. 
        /// </summary> 
        /// <returns>The session object.</returns> 
        public Session GetSession() 
        { 
            var expiryValue = DateTime.MinValue; 
            string expiryTicks = LoadEncryptedSettingValue("session_expiredate"); 
            if (!string.IsNullOrWhiteSpace(expiryTicks)) 
            { 
                long expiryTicksValue; 
                if (long.TryParse(expiryTicks, out  expiryTicksValue)) 
                { 
                    expiryValue = new  DateTime(expiryTicksValue); 
                } 
            } 
  
            var session = new  Session 
            { 
                AccessToken = LoadEncryptedSettingValue("session_token"), 
                Id = LoadEncryptedSettingValue("session_id"), 
                ExpireDate = expiryValue, 
                Provider = LoadEncryptedSettingValue("session_provider") 
            }; 
  
            _applicationSettings.Set(Constants.LoginToken, true); 
            _applicationSettings.Save(); 
            return session; 
        } 
  
        /// <summary> 
        /// The save session. 
        /// </summary> 
        /// <param name="session"> 
        /// The session. 
        /// </param> 
        private void  Save(Session session) 
        { 
            SaveEncryptedSettingValue("session_token", session.AccessToken); 
            SaveEncryptedSettingValue("session_id", session.Id); 
            SaveEncryptedSettingValue("session_expiredate", session.ExpireDate.Ticks.ToString(CultureInfo.InvariantCulture)); 
            SaveEncryptedSettingValue("session_provider", session.Provider); 
            _applicationSettings.Set(Constants.LoginToken, true); 
            _applicationSettings.Save(); 
        } 
  
        /// <summary> 
        /// The clean session. 
        /// </summary> 
        private void  CleanSession() 
        { 
            _applicationSettings.Reset("session_token"); 
            _applicationSettings.Reset("session_id"); 
            _applicationSettings.Reset("session_expiredate"); 
            _applicationSettings.Reset("session_provider"); 
            _applicationSettings.Reset(Constants.LoginToken); 
            _applicationSettings.Save(); 
        } 
  
        /// <summary> 
        /// The login async. 
        /// </summary> 
        /// <param name="provider"> 
        /// The provider. 
        /// </param> 
        /// <returns> 
        /// The <see cref="Task"/> object. 
        /// </returns> 
        public async Task<bool> LoginAsync(string provider) 
        { 
            Exception exception = null; 
            try
            { 
                Session session = null; 
                switch (provider) 
                { 
                    case Constants.FacebookProvider: 
                        session = await _facebookService.LoginAsync(); 
                        break; 
                    case Constants.MicrosoftProvider: 
                        session = await _microsoftService.LoginAsync(); 
                        break; 
                    case Constants.GoogleProvider: 
                        session = await _googleService.LoginAsync(); 
                        break; 
                } 
                if (session != null) 
                { 
                    Save(session); 
                } 
  
                return true; 
            } 
            catch (InvalidOperationException e) 
            { 
                throw; 
            } 
            catch (Exception ex) 
            { 
                exception = ex; 
            } 
            await _logManager.LogAsync(exception); 
  
            return false; 
        } 
  
        /// <summary> 
        /// The logout. 
        /// </summary> 
        public async void Logout() 
        { 
            Exception exception = null; 
            try
            { 
                var session = GetSession(); 
                switch (session.Provider) 
                { 
                    case Constants.FacebookProvider: 
                        _facebookService.Logout(); 
                        break; 
                    case Constants.MicrosoftProvider: 
                        _microsoftService.Logout(); 
                        break; 
                    case Constants.GoogleProvider: 
                        _googleService.Logout(); 
                        break; 
                } 
                CleanSession(); 
            } 
            catch (Exception ex) 
            { 
                exception = ex; 
            } 
            if (exception != null) 
            { 
                await _logManager.LogAsync(exception); 
            } 
        } 
  
        /// <summary> 
        /// Loads an encrypted setting value for a given key. 
        /// </summary> 
        /// <param name="key"> 
        /// The key to load. 
        /// </param> 
        /// <returns> 
        /// The value of the key. 
        /// </returns> 
        private string  LoadEncryptedSettingValue(string key) 
        { 
            string value = null; 
  
            var protectedBytes = _applicationSettings.Get<byte[]>(key); 
            if (protectedBytes != null) 
            { 
                byte[] valueBytes = ProtectedData.Unprotect(protectedBytes, null); 
                value = Encoding.UTF8.GetString(valueBytes, 0, valueBytes.Length); 
            } 
  
            return value; 
        } 
  
        /// <summary> 
        /// Saves a setting value against a given key, encrypted. 
        /// </summary> 
        /// <param name="key"> 
        /// The key to save against. 
        /// </param> 
        /// <param name="value"> 
        /// The value to save against. 
        /// </param> 
        /// <exception cref="System.ArgumentOutOfRangeException"> 
        /// The key or value provided is unexpected. 
        /// </exception> 
        private void  SaveEncryptedSettingValue(string key, string value) 
        { 
            if (!string.IsNullOrWhiteSpace(key) && !string.IsNullOrWhiteSpace(value)) 
            { 
                byte[] valueBytes = Encoding.UTF8.GetBytes(value); 
  
                // Encrypt the value by using the Protect() method. 
                byte[] protectedBytes = ProtectedData.Protect(valueBytes, null); 
                _applicationSettings.Set(key, protectedBytes); 
                _applicationSettings.Save(); 
            } 
        } 
}

Now is time to build the User Interface, and because i am using MVVM, i created a LoginViewModel to binding to the LoginView.
**
**

The LoginViewModel is:

C#

/// <summary> 
/// The login view model. 
/// </summary> 
public class  LoginViewModel : ViewModelBase 
{ 
        private readonly  ILogManager _logManager; 
        private readonly  IMessageBoxService _messageBox; 
        private readonly  INavigationService _navigationService; 
        private readonly  ISessionService _sessionService; 
        private bool  _inProgress; 
  
        /// <summary> 
        /// Initializes a new instance of the <see cref="LoginViewModel"/> class. 
        /// </summary> 
        /// <param name="navigationService"> 
        /// The navigation service. 
        /// </param> 
        /// <param name="sessionService"> 
        /// The session service. 
        /// </param> 
        /// <param name="messageBox"> 
        /// The message box. 
        /// </param> 
        /// <param name="logManager"> 
        /// The log manager. 
        /// </param> 
        public LoginViewModel(INavigationService navigationService,  
            ISessionService sessionService, 
            IMessageBoxService messageBox, 
            ILogManager logManager) 
        { 
            _navigationService = navigationService; 
            _sessionService = sessionService; 
            _messageBox = messageBox; 
            _logManager = logManager; 
            LoginCommand = new  RelayCommand<string>(LoginAction); 
        } 
  
        /// <summary> 
        /// Gets or sets a value indicating whether in progress. 
        /// </summary> 
        /// <value> 
        /// The in progress. 
        /// </value> 
        public bool  InProgress 
        { 
            get { return _inProgress; } 
            set { Set(() => InProgress, ref _inProgress, value); } 
        } 
  
        /// <summary> 
        /// Gets the facebook login command. 
        /// </summary> 
        /// <value> 
        /// The facebook login command. 
        /// </value> 
        public ICommand LoginCommand { get; private  set; } 
  
        /// <summary> 
        /// Facebook's login action. 
        /// </summary> 
        /// <param name="provider"> 
        /// The provider. 
        /// </param> 
        private async void LoginAction(string provider) 
        { 
            Exception exception = null; 
            bool isToShowMessage = false; 
            try
            { 
                InProgress = true; 
                var auth = await _sessionService.LoginAsync(provider); 
                if (!auth) 
                { 
                    await _messageBox.ShowAsync(AppResources.LoginView_LoginNotAllowed_Message, 
                        AppResources.MessageBox_Title, 
                        new List<string> 
                    { 
                        AppResources.Button_OK 
                    }); 
                } 
                else
                { 
                    _navigationService.NavigateTo(new Uri(Constants.MainView, UriKind.Relative)); 
                } 
  
                InProgress = false; 
            } 
            catch (InvalidOperationException e) 
            { 
                InProgress = false; 
                isToShowMessage = true; 
            } 
            catch (Exception ex) 
            { 
                exception = ex; 
            } 
            if (isToShowMessage) 
            { 
                await _messageBox.ShowAsync(AppResources.LoginView_AuthFail, AppResources.ApplicationTitle, new  List<string> { AppResources.Button_OK }); 
            } 
            if (exception != null) 
            { 
                await _logManager.LogAsync(exception); 
            } 
        } 
}

Note: in LoginAction the parameter provider is the value of the CommandParameter received in LoginCommand, this is set in the login page.

The LoginPage.xaml is:

XAML

<phone:PhoneApplicationPage x:Class="AuthenticationSample.WP80.Views.LoginView"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:Command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP8"
     xmlns:controls="clr-namespace:Facebook.Client.Controls;assembly=Facebook.Client"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
     xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
     xmlns:converters="clr-namespace:Cimbalino.Phone.Toolkit.Converters;assembly=Cimbalino.Phone.Toolkit"
     Orientation="Portrait"
     SupportedOrientations="Portrait"
     shell:SystemTray.IsVisible="True"
     mc:Ignorable="d"> 
    <phone:PhoneApplicationPage.DataContext> 
        <Binding Mode="OneWay"
                 Path="LoginViewModel"
                 Source="{StaticResource Locator}" /> 
    </phone:PhoneApplicationPage.DataContext> 
    <phone:PhoneApplicationPage.Resources> 
        <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/> 
    </phone:PhoneApplicationPage.Resources> 
    <phone:PhoneApplicationPage.FontFamily> 
        <StaticResource ResourceKey="PhoneFontFamilyNormal" /> 
    </phone:PhoneApplicationPage.FontFamily> 
    <phone:PhoneApplicationPage.FontSize> 
        <StaticResource ResourceKey="PhoneFontSizeNormal" /> 
    </phone:PhoneApplicationPage.FontSize> 
    <phone:PhoneApplicationPage.Foreground> 
        <StaticResource ResourceKey="PhoneForegroundBrush" /> 
    </phone:PhoneApplicationPage.Foreground> 
    <!--  LayoutRoot is the root grid where all page content is placed  -->
    <Grid x:Name="LayoutRoot" Background="Transparent"> 
        <Grid.RowDefinitions> 
            <RowDefinition Height="Auto" /> 
            <RowDefinition Height="*" /> 
        </Grid.RowDefinitions> 
  
        <!--  TitlePanel contains the name of the application and page title  -->
        <StackPanel x:Name="TitlePanel"
                    Grid.Row="0"
                    Margin="12,17,0,28"> 
            <TextBlock Margin="12,0"
                       Style="{StaticResource PhoneTextNormalStyle}"
                       Text="{Binding LocalizedResources.ApplicationTitle, 
                                      Mode=OneWay, 
                                      Source={StaticResource LocalizedStrings}}" /> 
            <TextBlock Margin="9,-7,0,0"
                       Style="{StaticResource PhoneTextTitle1Style}"
                       Text="{Binding LocalizedResources.LoginView_Title, 
                                      Mode=OneWay, 
                                      Source={StaticResource LocalizedStrings}}" /> 
        </StackPanel> 
  
        <!--  ContentPanel - place additional content here  -->
        <Grid x:Name="ContentPanel"
              Grid.Row="1"
              Margin="24,0,0,-40"> 
            <Grid.RowDefinitions> 
                <RowDefinition Height="Auto" /> 
                <RowDefinition Height="Auto" /> 
                <RowDefinition Height="Auto" /> 
                <RowDefinition Height="Auto" /> 
                <RowDefinition Height="Auto" /> 
            </Grid.RowDefinitions> 
            <TextBlock Grid.Row="0"
                       Style="{StaticResource PhoneTextTitle2Style}"
                       Text="{Binding LocalizedResources.LoginView_UserAccount, 
                                      Mode=OneWay, 
                                      Source={StaticResource LocalizedStrings}}" /> 
            <Button Grid.Row="1"
                    Margin="10"
                    Command="{Binding LoginCommand}"
                    CommandParameter="facebook"
                    Content="Facebook" /> 
            <Button Grid.Row="2"
                    Margin="10"
                    Command="{Binding LoginCommand}"
                    CommandParameter="microsoft"
                    Content="Microsoft" /> 
            <Button Grid.Row="3"
                    Margin="10"
                    Command="{Binding LoginCommand}"
                    CommandParameter="google"
                    Content="Google" /> 
       </Grid> 
        <Grid Visibility="{Binding InProgress, Converter={StaticResource BooleanToVisibilityConverter}}"
            Grid.Row="0"
                   Grid.RowSpan="2"> 
            <Rectangle 
                   Fill="Black"
                   Opacity="0.75" /> 
            <TextBlock 
                   HorizontalAlignment="Center"
                   VerticalAlignment="Center"
                   Text="{Binding LocalizedResources.LoginView_AuthMessage, 
                                  Mode=OneWay, 
                                  Source={StaticResource LocalizedStrings}}" /> 
            <ProgressBar IsIndeterminate="True" IsEnabled="True" Margin="0,60,0,0"/> 
        </Grid> 
      
    </Grid> 
</phone:PhoneApplicationPage>

 

Login User Interface

http://i1.code.msdn.s-msft.com/wpapps/authentication-using-cd382133/image/file/115617/1/wp_ss_20140529_0001.png

Source Code Files

  • IFacebookService interface for FacebookService
  • IGoogleService interface for GoogleService
  • ILogManager interface for LogManager
  • IMicrosoftService interface for MicrosoftService
  • ISessionProvider interface for all providers interface (common methods)
  • ISessionService for SessionService
  • Session class for save the information about the session (provider, token, expired date)
  • FacebookService class that has all logic about the login / logout using Facebook provider
  • GoogleService class that has all logic about the login / logout using Google provider
  • MicrosoftService class that has all logic about the login / logout using Microsoft provider
  • SessionService class for manage login/logout (it will use all services provides described before)
  • LoginViewModel class for binding to LoginView.xaml
  • LoginView class that represent the page for login
  • MainViewModel class for binding to MainView.xaml
  • MainView class that appear after the login is ok
  • AboutViewModel class for binding to the AboutView.xaml
  • AboutView class that represents the about page
  • ViewModelLocator class contains static references to all the view model in  application and provides an entry point for the bindings.

Build the Sample

  1. Start Visual Studio Express 2012 for Windows 8 and select File > Open > Project/Solution.
  2. Go to the directory in which you unzipped the sample. Go to the directory named for the sample, and double-click the Visual Studio Express 2012 for Windows 8 Solution (.sln) file.
  3. Press F7 or use Build > Build Solution to build the sample.

 Note: you can use Visual Studio 2013 in Windows 8.1.

Run the sample

To debug the app and then run it, press F5 or use Debug > Start Debugging. To run the app without   debugging, press Ctrl+F5 or use Debug > Start Without Debugging.

Code Samples

All of this sample can be found and downloaded in Windows Phone Dev center:


See Also

Another important place to find a huge amount of Windows Phone related articles is the TechNet Wiki itself. The best entry point is Windows Phone Resources on the TechNet Wiki. http://c.statcounter.com/10000094/0/b3447b65/1/