Adding a sign in page

In order to add sign in capabilities to our app, we will need to create a new Page and a new ViewModel. The ViewModel will be pretty straightforward, containing just a single command that handles signing in to Facebook via the IAuthService interface, passing the received Facebook token to the Azure backend service through the ITripLogDataService, and then storing the Azure access token in local settings.

There are a couple of ways to tap into the local storage platform-specific APIs to store settings. One way is to roll your own, similar to how we did the geolocation service: creating a core interface that is implemented uniquely per platform. Another alternative is to leverage a plugin or other third-party library that has already been created and published. In this section, we will use a plugin called Settings Plugin for Xamarin and Windows, available on NuGet as Xam.Plugins.Settings by James Montemagno:

  1. Add the Xam.Plugins.Settings NuGet package to the core library and each of the platform-specific projects, and update the Settings static helper class in the core library according to the package's README file to include a string setting property named TripLogApiAuthToken, as follows:
      public static class Settings
{
private static ISettings AppSettings
{
get => CrossSettings.Current;
}

private const string ApiAuthTokenKey = "apitoken_key";
private static readonly string AuthTokenDefault = string.Empty;

public static string TripLogApiAuthToken
{
get => AppSettings.GetValueOrDefault(ApiAuthTokenKey, AuthTokenDefault);
set => AppSettings.AddOrUpdateValue(ApiAuthTokenKey, value);
}
}
  1. Create a new class that inherits from BaseViewModel named SignInViewModel in the ViewModels folder in the core library:
      public class SignInViewModel : BaseViewModel 
{
}
  1. Update the SignInViewModel with a constructor that takes in INavService, IAuthService, and ITripLogDataService parameters:
      public class SignInViewModel : BaseViewModel
{
readonly IAuthService _authService;
readonly ITripLogDataService _tripLogService;

public SignInViewModel(INavService navService,
IAuthService authService,
ITripLogDataService tripLogService)

:base(navService)
{
_authService = authService;
_tripLogService = tripLogService;
}
}
  1. Next, add a new ICommand property named SignInCommand to the
    SignInViewModel along with its execute Action:
      public class SignInViewModel : BaseViewModel
{
// ...

ICommand _signInCommand;
public ICommand SignInCommand
{
get
{
return _signInCommand
?? (_signInCommand = new Command(
async () => await ExecuteSignInCommand()));

}
}

async Task ExecuteSignInCommand()
{
// TODO: Update with your Facebook Client Id
await _authService.SignInAsync("YOUR_FACEBOOK_CLIENTID",
new Uri("https://m.facebook.com/dialog/oauth"),
new Uri("https://<your-service-name>.azurewebsites.net/.auth/login/facebook/callback"),
tokenCallback: async t =>
{
// Use Facebook token to get Azure auth token
var response = await _tripLogService
.GetAuthTokenAsync("facebook", t);


// Save auth token in local settings
Helpers.Settings.TripLogApiAuthToken =
response.AuthenticationToken;

// Navigate to Main
await NavService.NavigateTo<MainViewModel>();
await NavService.RemoveLastView ();
},
errorCallback: e =>
{
// TODO: Handle invalid authentication here
});
}
}
  1. Override the BaseViewModel Init() method to clear the navigation back stack anytime the SignInViewModel is loaded: 
      public override async Task Init()
{
await NavService.ClearBackStack();
}
  1. Update the TripLogCoreModule Ninject module to add SignInViewModel to the IoC container:
      public class TripLogCoreModule : NinjectModule
{
public override void Load()
{
// ViewModels
Bind<SignInViewModel>().ToSelf();
Bind<MainViewModel>().ToSelf();
Bind<DetailViewModel>().ToSelf();
Bind<NewEntryViewModel>().ToSelf();

// ...


}
}
  1. Update the TripLogCoreModule to account for the updated TripLogApiDataService constructor and pass in the auth token stored in local settings:
      public class TripLogCoreModule : Ninject.Modules.NinjectModule
{
public override void Load()
{

// ...

var tripLogService = new TripLogApiDataService(
new
Uri("https://<your-service-name>.azurewebsites.net"),
Helpers.Settings.TripLogApiAuthToken
);

// ...
}
}

Next, we will need to create the actual sign in page, which will use the SignInViewModel as its data context:

  1. Create a new XAML page in the Views folder in the core library named SignInPage.

 

  1. Update the XAML of the SignInPage to add a button that is bound to SignInCommand of SignInViewModel:
      <ContentPage.Content>
<Button Text="Sign in with Facebook"
BackgroundColor="#455c9f"
TextColor="White"
Command="{Binding SignInCommand}"
Margin="20"
VerticalOptions="Center" />
</ContentPage.Content>
  1. Next, register the SignInPage and SignInViewModel mappings in the navigation service in the TripLogNavModule Ninject module:
      public class TripLogNavModule : NinjectModule
{

// ...

public override void Load()
{
var navService = new XamarinFormsNavService();
navService.XamarinFormsNav = _xfNav;

// Register view mappings
navService.RegisterViewMapping(
typeof(SignInViewModel), typeof(SignInPage));

navService.RegisterViewMapping(
typeof(MainViewModel),
typeof(MainPage));

navService.RegisterViewMapping(
typeof(DetailViewModel),
typeof(DetailPage));

navService.RegisterViewMapping(
typeof(NewEntryViewModel),
typeof(NewEntryPage));

Bind<INavService>()
.ToMethod(x => navService)
.InSingletonScope();
}
}

Finally, we will need to make two minor adjustments to the app so that users will go directly to the SignInPage if an auth token does not exist in local settings:

  1. First, add a public bool property to the App class in App.xaml.cs that indicates whether an auth token is present by checking the Settings helper class:
      public partial class App : Application
{

// ...

public bool IsSignedIn
{
get
{
return
!string.IsNullOrWhiteSpace
(Helpers.Settings.TripLogApiAuthToken);

}
}

// ...

}
  1. Next, update the Init method of the MainViewModel to forward the user to the SignInViewModel if the IsSignedIn property is false:
      public override async Task Init()
{
if (!((App)Application.Current).IsSignedIn)
{
await NavService.NavigateTo<SignInViewModel>();

}
else

{
LoadEntries();
}
}

Now, when the app is launched for the first time and an auth token is not present in the local settings, you will see the SignInPage. Clicking on the sign in button will launch the Xamarin.Auth dialog, prompting for Facebook credentials and permission to grant access to the TripLog app, as shown in the following screenshots:

Upon successfully authenticating with Facebook, you should be automatically brought to the MainPage and the list of the Entry objects will be loaded from the API.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.13.180