Identiteter, autentisering och säkerhet

I den här episoden prata Daniel och Johan om något som är nödvändigt i nästan alla applikationer, säkerhet. De pratar om att hantera identiteter, autentisering och säkerhet i allmänhet. Områden som de pratar om är bland annat Azure AD B2C, autentisering i .NET Core, autentisering i Xamarin appar och App Service Environments i Azure.

Azure AD B2C: https://azure.microsoft.com/sv-se/services/active-directory/external-identities/b2c/
Identiteter och säkerhet i .NET Core: https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity?view=aspnetcore-3.1&tabs=visual-studio
MSAL: https://github.com/AzureAD/microsoft-authentication-library-for-dotnet
Web Authenticator: https://docs.microsoft.com/en-us/xamarin/essentials/web-authenticator?tabs=android
App Service Environment, https://docs.microsoft.com/sv-se/azure/app-service/environment/intro

Xamarin.Forms Projects – Second Edition

The second edition of Xamarin.Forms Projects is now published. You can buy it from Packt or Amazon. It will also be available in other book stores.

More Information

An example-driven guide to help you build native cross-platform mobile apps using Xamarin, .NET Core 3, and Visual Studio 2019.

Set up Xamarin.Forms for building native apps with code-sharing capabilities

Understand the core aspects of developing a mobile app such as its layout, UX, and rendering

Use custom renderers to gain platform-specific access

Discover how to create custom layouts for your apps with Xamarin.Forms Shell

Use Azure SignalR for implementing serverless services in your Xamarin apps

Create an augmented reality (AR) game for Android and iOS using ARCore and ARKit, respectively

Build and train machine learning models using CoreML, TensorFlow, and Azure Cognitive Services

Xamarin.Forms is a lightweight cross-platform development toolkit for building apps with a rich user interface. Improved and updated to cover the latest features of Xamarin.Forms, this second edition covers CollectionView and Shell, along with interesting concepts such as augmented reality and machine learning.

Starting with an introduction to Xamarin and how it works, this book shares tips for choosing the type of development environment you should strive for when planning cross-platform mobile apps. You’ll build your first Xamarin.Forms app and learn how to use Shell to implement the app architecture. The book gradually increases the level of complexity of the projects, guiding you through creating apps ranging from a location tracker and weather map to an AR game and face recognition. As you advance, the book will take you through modern mobile development frameworks such as SQLite, .NET Core Mono, ARKit, and ARCore. You’ll be able to customize your apps for both Android and iOS platforms to achieve native-like performance and speed. The book is filled with engaging examples, so you can grasp essential concepts by writing code instead of reading through endless theory.

By the end of this book, you’ll be ready to develop your own native apps with Xamarin.Forms and its associated technologies such as .NET Core, Visual Studio 2019, and C#.

Develop mobile apps, AR games, and chatbots of varying complexity with the help of real-world examples

Explore the important features of Xamarin.Forms 4 such as Shell, CollectionView, and CarouselView

Get to grips with advanced concepts such as AR and VR and machine learning for mobile development

Application Insights for Xamarin- and UWP apps with TinyInsights

About two and a half years ago I created a library with the name TinyInsights with the idea to abstract away the underlying provider for diagnostics and analytics. The reason was that I wanted to make it possible to change the provider without that it affected my code more than in the initial setup of the app. Because diagnostics- and analytics services have a tendency to come and go, for example, Xamarin Insights and HockeyApp are no longer with us. Instead, we now have AppCenter, which also was my first provider for TinyInsights. I also wanted to make it possible to use multiple providers at the same time, because I have worked with apps where business analysts want the data to be in Google Analytics and developers want another service because other services are better for finding errors in apps.

My default provider has been AppCenter the last years, but recently I have missed a couple of important features and you can not analyze the data any deeper. You can export the data to Application Insights and then you can create deeper reports etc. But the way AppCenter store data make some questions harder to make in a good way. For example, if you want to track page views, you have to do that as an event. Application Insights is not built to handle page views that way, because it has real support for page views. AppCenter also lacks the future of tracking dependencies.

So what I decided to do was to create a new provider to TinyInsights with support for Application Insights. But I still using AppCenter for crashes and errors, because it also supporting me to upload symbols to it and Application Insights have no good way to distinguish between an error and a crash. But when I am logging crashes to Application Insights I am setting a custom property with the name "IsCrash" to "true".

I have implemented TrackDependency to all providers, but for AppCenter it only saves all data as custom properties and there is no good way to visualize them, but the data is there if you want to export it to your own visualizer.

Below I have written a short introduction about how to get started with the ApplicationInsightsProvider and TinyInsights in general.

Initializing Application Insights Provider

When initializing TinyInsights you need to specify what provider or providers you want to use. For Application Insights, you only need to give it the IntrumentationKey. If you don't pass different keys for different platforms all data will be collected together and not as in AppCenter where you create one app per platform.

var appInsights = new ApplicationInsightsProvider("{InstrumentationKey}");
var appCenter = new AppCenterProvider("{keyForIOS}", "{keyForAndroid}", {keyForUWP});
appCenter.IsTrackPageViewsEnabled = false;
appCenter.IsTrackEventsEnabled = false;
appCenter.IsTrackDependencyEnabled = false;
 
TinyInsights.Configure(appCenterProvider, applicationInsightsProvider);

Handling exceptions

To track exceptions/errors, just use the TrackErrorAsync method. Crashes will automatcially be tracked and sent to Application Insights next time the user is starting the app.

catch(Ecception ex)
{
     await TinyInsights.TrackErrorAsync(ex);
}
 
//with properties
var properties = new  Dictionarty<string, string>();
properties.Add("MyFirstProperty", "MyFirstValue");
properties.Add("MySecondProperty", "MySeconndValue");
 
catch(Ecception ex)
{
     await TinyInsights.TrackErrorAsync(ex, properties);
}

Tracking dependencies

There are a two of ways to track dependencies with TinyInsights.
The first and the basic method is TrackDependencyAsync, and is also used in the background by the other way to do it.

var startTime = DateTimeOffset.Now;
 
var success = await GetData();
 
var duration = DateTimeOffset.Now - startTime
 
await TinyInsights.TrackDependencyAsync("api.mydomain.se", "https://api/mydomain.se/v1/data/get", startTime, duration, success);

The second way is to create a TinyDependency object that handles most of the tracking for you. You will do that by just by wrapping your code for the dependency in a using statement.

using (var tracker = TinyInsights.CreateDependencyTracker("api.mydomain.se", "https://api/mydomain.se/v1/data/get"))
{
     await GetData();
}

If the dependency succeded that is fine, but if it not you need to handle that on your own, using the Finish method of the TinyDependency object.

using (var tracker = TinyInsights.CreateDependencyTracker("api.mydomain.se", "https://api/mydomain.se/v1/data/get"))
{
     try
     {
          var repsonse = await GetData();
 
          if(!response.IsSuccessStatusCode)
          {
               await tracker.Finish(false, (int)response.StatusCode);
          }
     }
     catch(Exception ex)
     {
          tracker.Finish(false, ex);
     }
}

Tracking page views

To track page views, just use the TrackPageViewAsync method.

await TinyInsights.TrackPageViewAsync("SuperCoolView");
 
//with properties
var properties = new  Dictionarty<string, string>();
properties.Add("MyFirstProperty", "MyFirstValue");
properties.Add("MySecondProperty", "MySeconndValue");
 
await TinyInsights.TrackPageViewAsync("SuperCoolView", properties);

Tracking events

To track events, just use the TrackEventAync method.

await TinyInsights.TrackEventAsync("SuperCoolEvent");
 
//with properties
var properties = new  Dictionarty<string, string>();
properties.Add("MyFirstProperty", "MyFirstValue");
properties.Add("MySecondProperty", "MySeconndValue");
 
await TinyInsights.TrackEventAsync("SuperCoolEvent", properties);

Feedback

If you have any feedback, please create an issue on GitHub. You will also be welcome to contribute to the library with improvments or/and other providers.
 

Azure Static Websites: Navigate to routes in a SPA using URL

I and my colleagues recently developed an app with Rect that we hosting using Static Websites in Azure. When we ran the application on our development machines everything works well when we navigated to route using a URL., but when we deployed it to Azure, that stopped to work. The only thing we could do was to navigate to the root route.

When you are building a SPA application you want the application to handle all routes for you. And if we only specify an "Index document name" in the settings or the static websites, we will get back an ugly 404 page for all routes other then the root route. The reason is that Azure is trying to serve us a file with that name because it thinks we want another document than the index.html.

The solutions are to specify the index.html file as an "Error document path". When we have done so, our application can handle the routing for us!

 

Xamarin ♥ Azure SignalR Service

Azure SignalR Service is a service in Microsoft Azure that makes it possible for developers to build applications with real-time communications without having to think about how to host it. Azure will handle all that for us.

If you are interested to learn more about SignarlR service and Xamarin apps there is a chapter in the Xamarin.Forms project, the book that I have written together with Johan Karlsson that cover the subject. In the book, you will get step-by-step guidance on how to set up the backend and how to write the app from "file new" to a full app. Read more about the book here, https://www.packtpub.com/application-development/xamarinforms-projects.

This post will cover:

  • How to set up a simple backend built with Azure functions and Azure SignalR service
  • How to use SignalR in a Xamarin App.

Setting up a backend

For the backend, we need to create two services in the Azure portal.

  1. Create a SignalRServcie in a new resource group
  2. Create a Function App in the same resouce group.

Open Visual Studio and create a new Azure Functions projects.

Install the NuGet package, Microsoft.Azure.WebJobs.Extensions.SignalRService. We need to check the "Show prereleases" checkbox to find the package, because it is still just a pre-release.

Create a new function with the name GetSignalRConnectionInfo.

public class GetSignalRConnectionInfo
{
        [FunctionName("GetSignalRConnectionInfo")]
        public static SignalRConnectionInfo Run(
            [HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequest req,
            [SignalRConnectionInfo(HubName = "chat")] SignalRConnectionInfo connectionInfo)
        {
            return connectionInfo;
        }
}

The SignalRConnectionInfo attribute is used to read the information from the configuration and to generate an access token. If the function should be able to read the information from the configuration we need to add it. What we should add is the connection string that we will find in the Azure Portal in the Keys tab under the SignalR Service. It will be added with the key AzureSignalRConnectionString to the ApplicationSettings of the Function App or to the local.settings.json file in our Visual Studio project if we want to run the function locally. It is also with the attribute we can set the name of the hub that we want to use, we can have multiple hubs in a SignalR Service.

Next step is to create a function that will add messages to the SignalR Service. Create a new function with the name SendMessages.

public class SendMessages
{
        [FunctionName("SendMessages")]
        public async static Task Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post")] object message,
            [SignalR(HubName = "chat")] IAsyncCollector<SignalRMessage> signalRMessages)
        {
            await signalRMessages.AddAsync(
                new SignalRMessage
                {
                    Target = "chatMessage",
                Arguments = new[] { message }
                });
        }
}

Use the SignalR attribute and an IAsyncCollector parameter to get a collection that you can use for adding messages to the SignalR Service. Target is a key that we can listen after in the app.

If we want to add some logic, for example, some type of validation we can do it here, before we add the message to the collection. In the app we are building in the book can the users upload photos. Then we use Azure Cognitive Services to make sure that the photos not are classified as adult photos.

Authentication

If we want to add authentication to our SignalR Service we should add it to the function that returns the connection info.

Building the app

To build an app with Xamarin we need to install the Microsoft.AspNetCore.SignalR.Client NuGet package.

Create a connection and start listening for messages

First we will create a model for connection information:

public class ConnectionInfo
{
     public string Url { get; set; }
     public string AccessToken { get; set; }
}

Now we can make an HTTP call to the function we created for getting connection information. When we get an answer we will serialize it to a ConnectionInfo model.

var result = await httpClient.GetStringAsync("https://{name-of-your-function}.azurewebsites.net/api/GetSignalRConnectionInfo");
var info = JsonConvert.DeserializeObject<Models.ConnectionInfo>(result);

Now we have all the information that we need to connect to the SignalR Service. To create a connection we will use the HubConnectionBuilder.

var connectionBuilder = new HubConnectionBuilder();
connectionBuilder.WithUrl(info.Url, (Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionOptions obj) =>
{
     obj.AccessTokenProvider = () => Task.Run(() => info.AccessToken);
});
 
var hub = connectionBuilder.Build();

To subscribe for messages we will use the On<object> method on the hub. We will pass the key that we specified in the message and an Action, in this case, we using an expression for the action.

In the expression body, we will handle the message, the message will come as a string so we need to convert the object to a string and then we can deserialize it to the type of message that we will receive. In this case, I have created a model with the name Message.

The last thing to do to start to listen for messages is to call the StartAsync method on the hub.

hub.On<object>("chatMessage", (message) =>
{
      var json = message.ToString();
      var obj = JsonConvert.DeserializeObject<Message>(json);
 
      //Handle the message here
});
 
await hub.StartAsync();

Sending a message

To sending a message is just a simple POST to the SendMessages function.

public async Task SendMessage(Message message)
{
     var json = JsonConvert.SerializeObject(message);
 
     var content = new StringContent(json, Encoding.UTF8, "application/json");
 
     var response = await httpClient.PostAsync("https://xfbook.azurewebsites.net/api/SendMessages", content);
}

OnSuspend and OnResume

It is important to handle the suspend and resumes events. The best way to that is to override OnSuspend and OnResume in App.xaml.cs. I recommended that you create a Dispose method in the same class as we have the other code that is related to SignalR. In this method, we will stop listening for messages and dispose the hub.

public async Task Dispose()
{
     if(hub != null)
     {
          await hub.StopAsync();
          await hub.DisposeAsync();
     }
}

And then we can call the Dispose method from the OnSuspend method. In the OnResume method, we can start the connection again.

Xamarin Month

This blog post is a part of Xamarin Month. Follow this link to read all the other blog post of the Xamarin Month.