Palaver XMPP client

It’s more than 20 years since I got involved with chat technologies. In the late 90’s I got hired by company for developing a chat client. We did this by reverse engineering the ICQ and AIM protocols and created a compatible client. Then Jabber was announced, we switched to it immediately, using the gateway feature to talk to the proprietary systems.

Later I worked for SLTS Communications on the myJabber client, which was very popular on the Windows platform. Also one of the first clients which bridged Jabber and SIP for VOIP integration.

Then I became self employed and focused mostly on libraries which helped many companies to bring their Jabber/XMPP products faster to market. I also did lots of consulting and custom development on clients, servers and other Jabber/XMPP related products.
Also many products which were not IM related, but using the realtime capabilities and other modern XMPP features.

Working on chat clients was always one of the tasks I enjoyed most. I missed the client work over the last 10+ years. So I thought its time to get back to it ;-)

Over the last 12+ month I did lots research on clients and their UIs. This includes XMPP, other open IM protocols and proprietary chat systems.
I worked on several prototypes with different toolsets and technologies. The aim was to evaluate languages and their frameworks. As well as available XMPP libraries for creating a modern cross platform client using the latest compliance suites.

The focus was on desktop clients only. While we have pretty good mobile clients, we are lacking on good desktop clients these days. Especially on Windows. Many people still spend most of their time on the desktop.

I created prototypes with:

  • various Javascript SPA frameworks, as PWA and Electron application
  • Different cross platform native UI-kits and programming languages
  • WASM
  • Java
  • .NET

I got the best results with technologies that have good implementations of the MVVM pattern. This narrowed it down to some web frameworks and the .NET platform for me.

With netCore the .NET platform became finally open source and cross platform. What’s still missing is an official cross platform GUI from Microsoft. But there is the open source XAML framework Avalonia, supporting all major platforms. And my own MatriX library is available for netCore for a while now, also open source, licensed under the GPL.

Because of the great Avalonia UI framework I decided on the netCore stack using for the new Palaver XMPP client.

Its still in very early stages. Once I can stabilize the prototype into a working client for daily usage all code will be published under the GPL license on GitHub. If anyone is already interested to contribute to this project then feel free to contact me.

Here you can see some early screenshots



XMPP websocket connection manager

For a new project I am working on (more to be announced) I was looking for a standalone websocket connection manager. Because still many public and private XMPP servers offer only the TCP transport or BOSH.

There are already existing projects websocket connection managers. But I ran into some issues with them for my current use case. Usually I am not trying to re-invent the wheels ;-)

After WebSocket support came to DotNetty which one of the latest releases, and MatriX vNext of course having full support for XMPP XML streams and clients I was considering creating my own proxy.

So it took only a 90 minute flight to come up with a working solution. I would not consider this solution as production ready yet. But the current design using DotNetty and MatriX vNext can support this at high scale.

When you are interested you can checkout the project on GitHub here:
https://github.com/matrix-xmpp/xmpp-websocket-proxy

MatriX vNext 2.0 released

we are thrilled to announce MatriX vNext 2.0

main changes in 2.0 are:

  • minor API changes which force major version bump (semver)
  • Direct TLS support (XEP-0368)
  • netstandard 2.0 support
  • new NameResolver wich allows to specify IP addresses of the XMPP server manual
  • new Matrix.Extensions package with extensions and helper functions
  • myget feed for latest dev builds

There is a new website for MatriX vNext and the documentation at:
https://matrix-xmpp.io/

All source code is available on Github now at:
https://github.com/matrix-xmpp/matrix-vnext

There is a WPF example client based on MatriX vNext available on Github here: https://github.com/matrix-xmpp/matrix-client

Introducing MatriX vNext

We are thrilled to announce the next generation of the MatriX XMPP libraries.
15 years elapsed already since we started our first .NET/c# XMPP library agsXMPP with .NET 1.0. Our XMPP libraries and the .NET technologies had many major evolutions over the years.

With the switch to .Net Core we also took the opportunity for a major rewrite and redesign of the codebase. The API for clients, servers and components is not backwards compatible, but all XMPP protocol classes remain the same. Updating existing code bases to MatriX vNext should be pretty straightforward.

Some highlights

  • new software design and more modern API
  • target .Net Core
  • high performance sockets using Azure DotNetty
  • Completly Task based using the TAP pattern (async/await)
  • more Linq extensions
  • Rx (Reactive Extensions)
  • will be open source and available under a dual license (Open Source and commercial)

Here is some demo client code using MatriX vNext:

var xmppClient = new XmppClient
{
    Username = "alex",
    Password = "secret",
    XmppDomain = "server.com",
};

xmppClient
	.XmppXElementStream
	.Where(el => el.OfType<Presence>())
	.Subscribe(el =>
	{
		// Handle incoming presence
		Debug.WriteLine(el.Cast<Presence>().From);
	});

xmppClient
	.XmppXElementStream
	.Where(el => el.OfType<Message>())
	.Subscribe(el =>
	{
		// Handle incoming messages	    
		Debug.WriteLine(el.Cast<Message>().Body);
	});

xmppClient
	.XmppXElementStream
		.Where(el => 
		el.OfType<Iq>
		&& el.Cast<T>().Type == IqType.Get
		&& el.Cast<T>().Query.OfType<Ping>()
	.Subscribe(el =>
	{
		// handle and reply to incoming pings
		var iq = xmppXElement.Cast<T>();

		var resIq = Factory.GetElement<T>();
		resIq.Id    = iq.Id;
		resIq.To    = iq.From;
		resIq.Type  = IqType.Result;

		await xmppClient.SendAsync(resIq);
	});

// connect, secure, authenticate and bind
await xmppClient.ConnectAsync();

// request roster (contact list)
var roster = await xmppClient.RequestRosterAsync();

// send own presence to the server
xmppClient.SendPresenceAsync(Show.Chat, "free for Chat");

Releases are available as a Nuget packages here: https://www.nuget.org/packages/Matrix.vNext

Firebase Cloud Messaging with MatriX XMPP SDK

We get a lot of requests on howto use the MatriX XMPP SDK with Google Firebase Cloud Messaging.

The following are the settings for your XmppClient object

  • The XMPP domain is: gcm.googleapis.com
  • The hostname is: fcm-xmpp.googleapis.com
  • It looks like there are no SRV records in place, this is why you need to set the hostname manual and disable SRV record lookups
  • Firebase does not support XMPP’s StartTls feature and requires to initiate a TLS connection. This is how we have done it in the old days when the protocol still was called Jabber. The OldStyleSsl property takes care of this in MatriX’s XmppClient.
  • Firebase is using a non standard XMPP port, because no SRV records are in place we have to set port 5236 manual in the code
  • the username is your Firebase Sender Id and the password is your server key. You find them in the Firebase portal under Settings => Cloud Messagging
  • the contact list and presence feature is not require. So we can disable it by setting AutoRoster and AutoPresence to false
XmppClient xmppClient = new XmppClient
{
    XmppDomain          = "gcm.googleapis.com",
    Hostname            = "fcm-xmpp.googleapis.com",
    Port                = 5236,
    ResolveSrvRecords   = false,
    OldStyleSsl         = true,
    Username            = "YOUR_FIREBASE_SENDER_ID",
    Password            = "YOUR_FIREBASE_SERVER_KEY",
    AutoRoster          = false,
    AutoPresence        = false
};

xmppClient.Open();

You can find a basic example also here in our GIT repository:
https://gitlab.com/matrix-xmpp/samples/tree/master/csharp/FirebaseClient

See also:
https://firebase.google.com/docs/cloud-messaging/server#implementing-the-xmpp-connection-server-protocol

MatriX XMPP SDK available for .NET Core

The MatriX XMPP SDK is also available for the .NET Core now.
You can get it from NuGet here: https://www.nuget.org/packages/MatriX.NetCore/

It passed all our internal tests and QA, but its still marked as a pre-release until we collected some more feedback from users.

Don’t hesitate to contact us directly, or use our forums for any questions related to the .NET Core version.

MatriX v2 released

We are pleased to announce the stable releases of MatriX 2. More about the changes in the v2 version can be found in this blog post

Instead of installers we will use NuGet only for all future MatriX releases. You can find all MatriX NuGet packages here

Sample codes can be found in the Git repository here

All our customers with active support & maintenance can of course upgrade to MatriX 2 for free. Updating existing code bases to MatriX 2 should only take a few minutes. We highly suggest the update because there are many improvements in the MatriX 2 core, and also many new features on our roadmap.

MatriX JS XMPP library in beta now

We are pleased to announce our new JavaScript XMPP library MatriX JS which is available for beta now.

MatriX JS is build with Microsoft’s TypeScript. The software design is very similar to our popular MatriX .NET XMPP SDK. TypeScript allowed us to port lots of existing source code, logic and patterns from our MatriX C# library to JavaScript. MatriX JS is also based on LinQ and LinQ to XML. This will make it very easy for our existing customers to port existing code bases to the web or cross platform HTML/JS applications.

Currently BOSH and websockets are supported as transport layers. Node.js and tcp sockets are coming later.

MatriX JS will be licensed under a Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0) license.

Contact us to join the MatriX JS beta

MatriX v2 pre release

The first version of MatriX was released in February 2009. Now 6 years later we announce MatriX v2 pre release.

Over the last six years we released all new features and improvements always immediately to our customers, without making major changes in the version number. There have never been any breaking changes.

MatriX v2 has many major improvements in the core, but we also have done some minor changes in the Api. Most of the Api changes are related to Enum names only. Many of them were never compatible with the c# naming conventions.

They have been there because some of the supported .NET platforms were not able to parse the values case-insensitive, and there were no other ways to do this without using endless IF or SWITCH statements on all platforms.
Also some of the code is still left from the very first .NET version of our XMPP components in 2002, using .NET 1.0 and C# 1.0. In the very early days of c# many people were using Java, C or C++ conventions for the new c# language.

public enum MessageType
{  
    Normal,   
    Error,
    Chat,
    GroupChat,
    Headline
}

public enum MessageType
{
    normal,
    error,
    chat, 
    groupchat,
    headline
}

Updating even huge codebases to v2.0 should be very easy and take only some minutes.

With 2.0 we will also separate the NuGet packages by platform. This will allow us publishing NuGet packages much easier and more often. There is still lots of platform specific code in each MatriX edition which does not allow us to work on all of them in parallel.

Right now only builds for teh Full .NET Framework 3.5, 4.0 and 4.5 are available. All other platforms will be published in the next days.

Of course all MatriX licenses keys with Support&Maintenance are valid for v2 as well.

When you find any issues with the pre release please report them directly by Email to us, or use our forums.

Secure Gmail Authentication with X-OAUTH2 SASL

In July 2014 Google has introduced the “More Secure Gmail Authentication feature”.
When Access for less secure apps is set to disabled then Google does not allow login over SASL PLAIN anymore (even on TLS).

During authentication Google replies with the not-authorized error. And they will notify you by email that access to an insecure application was denied.

CLIENT: <auth mechanism="PLAIN" xmlns="urn:ietf:params:xml:ns:xmpp-sasl">AUTH DATA</auth>
SERVER: <failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
  <not-authorized />
</failure>

When access for less secure apps is disabled you have to login with the X-OAUTH2 SASL mechanism the Gmail XMPP server offers. Here is a small tutorial how to achieve this with MatriX.

1) API Project

In order to access the Google API you have to setup a project in the Google API Console which provides you the Access credentials. Once you have created your API project you can request your credentials which include the Client Id and Client Secret. During the creation process of the app project we selected “native application”.

2) Request an Access Token

To authenticate with OAuth 2.0 we need to get our Access Token. The OAuth 2.0 is documented at the Google pages under the following 2 links:

There are also several .NET libraries available, e.g DotNetOpenAuth or Google APIs Client Library.

We are not going to use a third party library for now, because this help us also to understand the whole XAuth authentication flow.

We create a new form and put a Webbrowser control on it. When the form loads we have ro navigate to a Url which includes;

  • Client Id of our API project
  • A redirect Uri, we use this urn:ietf:wg:oauth:2.0:oob
  • scopes:
    • https://www.googleapis.com/auth/googletalk
      (required for XMPP authentication)
    • https://www.googleapis.com/auth/userinfo.email
      (optional, we can use this t get the username/email address of the user)

When our form with the webbrowser loads we navigate to this Url with teh following code:

const string CLIENT_SECRET  = "XXXXXXXYYYYYYYYYYYYZZZZZZZZZ";
const string CLIENT_ID      = "yyyyyyyyyyyyy-xxxxxxxxxxxxxxxxx.apps.googleusercontent.com";

private static Uri GetAutenticationUri()
{
    var postData = new List<string>
    {
        "client_id=" + CLIENT_ID,
        "redirect_uri=urn:ietf:wg:oauth:2.0:oob",
        "scope=https://www.googleapis.com/auth/googletalk https://www.googleapis.com/auth/userinfo.email",
        "response_type=code"
    };

    return new Uri("https://accounts.google.com/o/oauth2/auth" + "?" + string.Join("&", postData.ToArray()));
}


private void Form_Load(object sender, EventArgs e)
{
  // navigate to the Uri when the form loads
  webBrowser1.Url = GetAutenticationUri();
}

When you run the code you should see the following: google_xoauth2

3) Authentication

When the user now clicks on “Accept” in the authentication dialog the page in the browser reloads. The new page contains an Authentication code in the title tag. The authentication code is also in the body of the result page. We have seen cases where the code in the title tag was cut off. So it could be more secure to parse it from the body.

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    string docTitle = ((WebBrowser) sender).DocumentTitle.ToLower();
    // when there is "success code=" in the title its the page we are looking for.
    if (docTitle.IndexOf("success code=") > -1)
    {
        webBrowser1.Visible = false; // Hide the webbrowser
        // we can find the auth code in the title tag of the html page
        string authCode = webBrowser1.DocumentTitle.Replace("Success code=", "");
        
        ProcessAuthorizationCode(authCode);
    }
    else if (docTitle.IndexOf("denied error=") > -1)
    { 
        // user denied the app dialog, handle this here.        
    }
}

4) Exchanging the Authentication Code

Now we have the Authentication code, and can use it to request the access token and refresh token over a simple HTTP Post. The result is in JSON, we use Newtonsoft.Json to process it.

public void ProcessAuthorizationCode(string authCode)
{
    var postData = new List<string>
    {
        "code=" + authCode,
        "client_id=" + CLIENT_ID,
        "client_secret=" + CLIENT_SECRET,
        "redirect_uri=urn:ietf:wg:oauth:2.0:oob",
        "grant_type=authorization_code"
    };

    //Posting the Data to Google
    string responseString = Post("https://accounts.google.com/o/oauth2/token", postData);

    //Processing the JSON Response
    JObject jObject = JObject.Parse(responseString);
    
    JToken refreshToken = jObject.SelectToken("refresh_token");
    // Checking for errors.
    if (refreshToken == null)
    {
        //this._ErrorMessage = response;
    }
    else
    {
        RefreshToken = refreshToken.ToString();
        AccessToken = jObject.SelectToken("access_token").ToString();
        // close the browser Windows, we are done
        Close();
    }
}

public static string Post(string url, List<string> postData)
{
    var request = WebRequest.Create(url);

    // Preparing the post data
    var toPost = string.Join("&", postData.ToArray());
    byte[] byteArray = Encoding.UTF8.GetBytes(toPost);

    request.Method = "POST";
    request.ContentType = "application/x-www-form-urlencoded";
    request.ContentLength = byteArray.Length;
    var dataStream = request.GetRequestStream();
    
    dataStream.Write(byteArray, 0, byteArray.Length);
    dataStream.Close();
    try
    {
        // read the response
        var response = request.GetResponse();
        dataStream = response.GetResponseStream();
        var reader = new StreamReader(dataStream);
        string responseString = reader.ReadToEnd();
        
        reader.Close();
        dataStream.Close();
        response.Close();
        
        return responseString;
    }
    catch (Exception)
    {
        return null;
    }
}

5) Getting the username (optional)

The username for XMPP authentication for XOAUTH2 SASL is the users email address. You can either ask the user to enter it in your software. Or you can use your access token to request more user details. This is why we have added the scope https://www.googleapis.com/auth/userinfo.email. This allows us to get the username with a post to the following url:
https://www.googleapis.com/oauth2/v1/userinfo?access_token={your_access_token}

This request returns JSON payload where you could fine the users email address.

6) Authenticate with MartiX

Now we have everything to perform the XOAUTH2 authentication with MatriX. We need to subscribe to the OnBeforeSasl event to manual select the SASL mechanism and pass our access token.

private void xmppClient_OnBeforeSasl(object sender, Matrix.Xmpp.Sasl.SaslEventArgs e)
{
  // make sure we use the correct username for authentication    
  xmppClient.Username = "user12345@gmail.com";
  // disable automatic SASL algrithm selection in MatriX
  e.Auto = false;
  // manual specify the X_OAUTH2 SASL mechanism 
  e.SaslMechanism = Matrix.Xmpp.Sasl.SaslMechanism.X_OAUTH2;
  
  //pass the Access token to MatriX  
  e.SaslProperties = new OAuthProperties()
  {
      AccessToken = "AccessToken"
  };    
}