Deploying a NodeJS server with SocketIO to Docker using Azure IoT Edge

The current Azure IoT Edge public preview uses Docker to deploy logic from the cloud into local gateways. It’s currently featuring:

  • C# modules written in .Net standard
  • Python modules
  • Azure Function built on your machine
  • Azure Stream Analytics jobs built and deployed in the cloud
  • Azure Machine Learning

We can expect Microsoft will support other types of modules soon as they have proven with other recent projects. An Azure Cognitive Services module is a good example, it’s put in every IoT Edge presentation.

The IoT Edge portal makes it possible to deploy modules which are available in private or public image repositories.

Could it be possible to build and deploy images to the gateway which are not specifically designed for IoT Edge?

It turns out, it is possible.

Let’s deploy a NodeJS server which serves SocketIO.

Doorgaan met het lezen van “Deploying a NodeJS server with SocketIO to Docker using Azure IoT Edge”

Advertentie

Azure CLI made easy. Using a shell

In a previous blog, I introduced you to the Azure Command Line Interface. This is a powerful tool for generating and controlling Azure resources.

This CLI has only one weak spot, the sheer limitless amount of features and settings. You have to remember a lot!

But with the introduction of the new Azure CLI shell, most of that pain is taken away.

Let’s check this out.

Doorgaan met het lezen van “Azure CLI made easy. Using a shell”

Push notification for groups of users in Azure Mobile Services

Push notification is one of the most important features of mobile apps. Users use it a lot and take it for granted that you incorporate this feature in your app. But underneath the apparently realtime popup/toast of a message, lives a whole system of providers and notification hubs to make that possible.

p01

First of all, there are three major notification providers: Google, Apple and Microsoft. It looks like pushing message to all three stores is hard but AMS makes it easy.

In this example we push to a Windows Store app (part of the default generated AMS example solution). But It’s almost the same on eg IOS or Android. Apart from the client code which differs on each platform (See http://azure.microsoft.com/en-us/documentation/articles/mobile-services-dotnet-backend-windows-phone-get-started-push/ for different client support) the AMS server code is all the same.

Coding! Let us start with the first, most important step: reserve your future app name in the store of choice. In return you will be granted some secret key(s) which you have to use for push notification to the users of your app.

Fill these secret keys in on the Push tab in the Azure Mobile Services portal. There is plenty of room for all the settings (Facebook, Google, MSFT). There is rather no push notification from Twitter 🙂

p02

So let’s add some code in the service which will push messages. In this example I push a notification if a note is inserted in the database by the default available TableController (part of the generated code when the service was created initially).

p03

Although this is an example using a WNS native toast, it is clear we only have to define the message and we have to push it once. AMS will take the message and distribute it over all the notification hubs configured.

Did you notice the “DATABASE” tag? I have given this message a conditional tag. So only clients which are registered (interested) for messages with this tag, will receive it. It should be possible to send one message specifically to one user!

So now let’s go to the client, because we want to receive that message. We have to register for push messages.

p04

Here we do a couple of things. First we unregister for any tags we could be registered to already. This is nice if the tags change often. Afterwards we register for the messages with tag “DATABASE”. We can enter any amount of tags but for now it’s this one.

Why do we register? Because the push notification messages will be shown, whether we are using the app (it is currently opened, in use) or we are not. As long the app is installed on the machine (and run once), push notification from that app could reach us. And if so, if the user tabs on the toast, the app will be instantiated (if not already open).

But maybe you do not want the notification to be shown while the app is open. Or you want to present it in a whole new way (with sound of something blinking). That’s why I added the event handler and added the function.

Inside that function I can parse the message and decide if I want to show it the regular way or not (using the args.Cancel).

So call the Initialize function when you know which kinds of messages you want to receive. Or omit the tag if you want them all 🙂 I have put it inside the Onlaunched event in app.xaml.cs.

But there is still one thing to do!

We must have permissions from the user to receive push notification for our app. Or at least, the user must be made aware of the fact we are using push notifications. This is done with the ‘toast capability’. Double-click the Package.appxmanifest in the Windows Store app, and on the application tab, select Yes for Toast Capable!

p05

And this is all there is to tell about Push Notification support (at least the most important part).

Start the AMS app and insert a Todo Item. Within minutes, usually seconds or mostly within a second, a popup will appear.

p08

Is this cool or not?

Push notification is part of all versions of Azure Mobile Services. But the free version has some restrictions (What do you expect? It’s free…) See the pricing for more information.

Getting the token expiration date in Azure Mobile Services

Azure Mobile Services support storing the Oauth user credentials token in the PasswordVault of the OS a client app is running in. This is supported in Windows Universal apps, Xamarin, etc.

See here for the details regarding user credentials from the AMS documentation.

And this is a good thing, now the user does not have to supply the Oauth credentials every time the app is started. We can check if the vault contains the credentials we need and this saves a round trip to the server and an extra input screen. If it is not in the vault, just let the user login using Facebook, Google etc.  and store the token.

But wait: these stored credential tokens are not valid until the end of times. For example, Google credentials are valid for 30+ days. After that, the token stored in the vault is worthless.

Therefor, in the AMS example above a simple check is done by calling the AMS service with a trivial request:

...
try 
{ 
  // Try to return an item now to determine if the cached credential has expired. 
  await App.MobileService.GetTable<TodoItem>().Take(1).ToListAsync();
               // <<-- WHY??? 
} 
catch (MobileServiceInvalidOperationException ex) 
{ 
  if (ex.Response.StatusCode == System.Net.HttpStatusCode.Unauthorized) 
  { 
    // Remove the credential with the expired token. 
    vault.Remove(credential); credential = null; continue; 
   } 
}
...

Here a simple GET is done to check the validity of the token. If it is not valid, it is deleted and the user must login again.

But this is a web call I do not like.

This is done every time user logs in / starts the app, even in an offline scenario!

In an offline scenario I am not even interested in the expiration date…

Is there a better way?

Well, what we get from the Oauth providers, when the user logs in successfully, is a Json Web Token (JWT). And this token can be decoded following the JWT specifications.

This will result in something like:

public class Token
{
    [JsonProperty(PropertyName = "ver")]
    public string Ver { get; set; }
 
    [JsonProperty(PropertyName = "uid")]
    public string Uid { get; set; }
 
    [JsonProperty(PropertyName = "exp")]
    public string Exp { get; set; }
 
    [JsonProperty(PropertyName = "nbf")]
    public string Nbf { get; set; }
 
    [JsonProperty(PropertyName = "aud")]
    public string Aud { get; set; }
}

This token is available on the server as:

App.MobileService.CurrentUser.MobileServiceAuthenticationToken

And the token can be decoded using a Nuget package. The only drawback is that this package is not available on the Universal apps client, only on the Azure Mobile Services server, the backend.

So I wrote this extra API controller:

public class DecodeExpirationController : ApiController
{
  public ApiServices Services { get; set; }
 
  // GET api/DecodeExpiration
  [AuthorizeLevel(AuthorizationLevel.User)]
  public DateTime? Get(string token)
  {
    string adminKey;
 
    if (!Services.Settings.TryGetValue("ADMIN_KEY", out adminKey))
    {
      return null;
    }
 
    try
    {
      var jsonPayload = JWT.JsonWebToken.Decode(token, adminKey, false);
 
      var result = JsonConvert.DeserializeObject<Token>(jsonPayload);
 
      var startOfUtcCount = 
        new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
 
      var expirationDate = startOfUtcCount.
                             AddSeconds(Convert.ToInt32(result.Exp));
 
      return expirationDate;
    }
    catch (JWT.SignatureVerificationException)
    {
      return null;
    }
    catch (Exception ex)
    {
      return null;
    }
  }
}

Note the level of authorization, the user should be logged in by now…

And we can call this WebApi GET on the client:

try
{
  var parameters = new Dictionary<string, string>();
  parameters.Add("token",
    App.MobileService.CurrentUser.MobileServiceAuthenticationToken);
  var result = await App.MobileService.
        InvokeApiAsync<DateTime?>("DecodeExpiration", HttpMethod.Get, parameters);
 
  message = result.HasValue ? result.Value.ToString() : "Nothing returned.";
}
catch (Exception ex)
{
  message = "Exception: " + ex.Message;
}

This should work using with every provider.

The Admin Key is coming from the portal. I have added this appsetting to the configuration of the AMS.

Using this call we get the UTC time of the token expiration date. So store this on the client and check this value every time (give or take a few hours due to correct daylight savings when applicable).

Emails versturen via Azure

De afgelopen paar jaar is Azure steeds completer geworden als het om functionaliteit gaat. Hoewel MSFT nog een heleboel functionaliteit kan toevoegen, wordt er ook samengewerkt met derde partijen voor sgn. Add-Ins.

Hierbij levert een andere partij een dienst die samenwerkt met Azure en waarbijde kosten via Azure verrekend wordt. Een goed voorbeeld is SendGrid.

Zij bieden de mogelijkheid om op grote schaal email te versturen naar de door jou bepaalde emailadressen. Het mooie is dat ze adverteren met: “Send up to 200 emails a day. No credit card needed. No expiration.”

Het is aardig om te zien dat er ook een mooi dachboard bijaangeboden wordt. Daar kun je zien hoe de mail aankomen bij klanten en of die geopend worden. Maar je kunt bv. ook je ‘credibility’ zien. In hoe verre wordt je als spammer gezien?

Maar de Add-in van Azure biedt een andere mogelijkheid: als jevoor 0 (nul) Euro de add-in koopt, mag je 25000 berichten versturen (“25000 credits monthly”).

Maar hoe werkt het implementeren? Dat is een beetje rommelig.

Als je link 1 volgt dan wordt in eerste instantie netjes vertelt hoe je een account aanmaakt en wat je naam/wachtwoord combinatie voor het versturen is. Daarna wordt verteld hoe je de code schrijft dmv. een Nuget package. Helaas is dit artikel gebaseerd op een oudere versie (1.0) terwijl inmiddels versie 4.0 wordt aangeboden en er tussendoor een ‘breaking api change’ is doorgevoerd. Ga dus naar link 2 voor het consumeren van de Nuget package.

Hier moet je echt een eind mee komen.

En mocht je email willen versturen vanuit de Javascript scripts van Azure Mobile Services, dat kan! MSFT heeft een Sendgrid bibliotheek beschikbaar gesteld binnen NodeJs. Via deze link kom je bij de voorbeelden.

Het opzetten van deze emailfunctie was binnen een uurtje gefixed nadat ik begreep dat de eerste voorbeeld-broncode niet met de breaking change kon omgaan.

Overigens kan het gebeuren dat MSFT binnenkort ook met een email functie komt. Dit heb ik ook zien gebeuren met de Azure Scheduler. Die werd eerst ook alleen maar door derde partijen aangeboden. Maar omdat MSFT deze zelf ook broodnodig had (de scheduler achter Webjobs is geïmplementeerd in Azure Scheduler), hebben we er nu ook een van MSFT zelf.

Tenslotte: een overzicht van de verschillende licenties is hier te vinden.

EN: Interested in this article but Google Translate is not enough? Please contact me for more (English) in-dept information.