Decrypting JSON Web Encrypted tokens in PCL

This week I worked on a feature for a Xamarin app I’m building that gave me quite some headaches because it involved a good amount of yak shaving to get it working correctly. My main reason for blogging this is for my own reference in the future, but maybe it can help someone else too 🙂

yak shaving
Yak shaving, gotta love it…

Our team is building a cross platform Xamarin app that has a good amount of shared code in an MVVM architecture. Most of the app is implemented in PCL libraries with a front end project per platform.

For communicating with a backend API, the app requires a token obtained from an Identity Provider. In addition to the API access token, we’re also getting an OpenId token that is crucial for the app. Using Xamarin.Auth for example, it’s pretty easy to setup an OAuth flow that lets the user login and the app obtain that token.

So far so good.

There’s a lot to be said about which OAuth flow is suitable in which scenario. For us, embedding a client secret in the app was a no go, since this can’t be kept secret if it’s embedded in the source code of the app (reverse engineering!). We chose a PCKE approach. Without going into too much detail around the flow, I want to focus on one aspect: securing the OpenID token. This blogpost is mostly about what I learned about token encryption and decryption.

207h

Our requirement was to have asymmetric encryption in place, where the app provides a public key to the server, which it uses to encrypt the JWT. The app can then decrypt the data using its private key, so we could mitigate a token interception attack. The public key was to be transferred in an X509 certificate (PEM encoded). The idea was to have the app generate a private/public keypair on-the-fly as we don’t want to hard code a private key into the app. That would lead us to the same situation as the hard coded Client Secret. All we want is to make sure that the requesting app is the only one able to decrypt the token it requested.

There’s a nice standard for encrypting tokens using a variety of algorithms: JWE – JSON Web Encryption. The original token is in a JSON structure, encrypted and packaged into a standardized format. In our case, these were the specs:

Algorithm: RSA_OAEP – RSAES using Optimal Asymmetric Encryption Padding (OAEP) (RFC 3447), with the default parameters specified by RFC 3447 in section A.2.1

Encryption method A256GCM – AES in Galois/Counter Mode (GCM) (NIST.800-38D) using a 256-bit key

Basically what happens is: the token payload is encrypted using a random Content Encryption Key (CEK) provided by the server. This is an authenticated encryption mode, where data is added to prove authenticity. In addition to the key, an Initialization Vector (IV) is added, and also an Authentication Tag (authTag) and Additional Authenticated Data, basically consisting of a Base64 representation of the JWE header. All this together provides a symmetric encryption through which we can decrypt the token. This is the A256CGM – AES step.

All the information I mentioned – the CEK, IV, cipherText (the encrypted token), AAD and authTag – are present in the JWE package. To add the final layer of security, the CEK has to be encrypted, otherwise anyone would be able to read the token. This is the RSA_OAEP – RSAES step mentioned earlier. In plain English, the CEK is encrypted using asymmetric encryption. The server uses the app’s public key for this, obtained from the X509 certificate in the request.

So the way back to obtain the token plain text is to decrypt the CEK using the private key, and then decrypt the token payload using the CEK together with the IV, AAD and authTag, as illustrated in the diagram below:

jwe-decryption

That looks pretty daunting, but luckily there are libraries that help us handle this scenario, or the many other combinations of algorithms and encodings. One popular example is the JOSE-JWT library for .NET. You can feed it the complete JWE package and the CEK decryption key, and it does all the heavy lifting. JOSE-JWT can also handle our scenario, with our combination of algorithms and encodings.

Here’s the catch…

This won’t fly in a PCL. JOSE-JWT is built on System.Security.Cryptography, which isn’t available in PCL code. There have been some attempts to make JOSE-JWT available for Xamarin, but this won’t work fully cross platform. So ideally, we’d want a library that solves this using PCL compatible API’s. And sadly, there is no JOSE-JWT implementation available for PCL yet.

281H_banner.png
Now what?!

JWE just uses standard encryption algorithms, so it should be possible to implement these on top of a crypto API that is available cross platform (in PCL). I have tried two options:

  • PCLCrypto: this library mimics the WinRTCrypto API’s but relies on native, platform specific crypto-engines to perform the encryption. This results in the fastest encryption engine but is limited in terms of supported scenario’s or algorithms.
  • BouncyCastle-PCL: a cross platform crypto library that supports all sorts of cryptographic algorithms.

Since PCLCrypto mimics the WinRTCrypto API, it seemed pretty easy to implement our JOSE-JWT port on top of PCLCrypto, by stealing borrowing from the experimental JOSE-RT port. (Thanks Dmitriy Vsekhvalnov for the tip!) And indeed, if you look at the AesGcmEncryptor class, it looks rather straight forward. Alas, it turns out our GCM authenticated mode isn’t supported by PCLCrypto. It threw a NotSupportedException at me.

So the other option was to use BouncyCastle-PCL. We ended up with a solution that does the following:

  • Generation of the public/private keypair
  • Generation of the X509 certificate containing the public key
  • Unpacking the JWE package
  • Decrypting (or unwrapping) the CEK using the private key
  • Decrypting the token payload

Mind you, I only had to support our specific scenario, but it’s a small step towards a full JOSE-PCL implementation. Maybe someday I’ll make an attempt 🙂

Without further ado, here is the code I ended up with:

using System;
using System.IO;
using System.Text;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Operators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO.Pem;
using Org.BouncyCastle.X509;
using System.Linq;

namespace JoseJWE
{
	public class CryptoService
	{
		public AsymmetricCipherKeyPair GenerateKeyPair()
		{
			var random = new SecureRandom();
			var keyGenerationParameters = new KeyGenerationParameters(random, 1024);
			var keyPairGenerator = new RsaKeyPairGenerator();
			keyPairGenerator.Init(keyGenerationParameters);
			var keyPair = keyPairGenerator.GenerateKeyPair();
			return keyPair;
		}

		public string GeneratePemEncodedCertificate(AsymmetricCipherKeyPair keyPair)
		{
				var random = new SecureRandom();
				var signatureFactory = new Asn1SignatureFactory("SHA256WithRSA", keyPair.Private, random);

				var gen = new X509V3CertificateGenerator();
				gen.SetPublicKey(keyPair.Public);

				BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue), random);
				gen.SetSerialNumber(serialNumber);

				var x509Name = new X509Name("CN=MyCertificate,O=RoyCornelissen,OU=CryptoService");
				gen.SetIssuerDN(x509Name);
				gen.SetSubjectDN(x509Name);

				gen.SetNotBefore(DateTime.UtcNow.AddHours(-1));
				gen.SetNotAfter(DateTime.UtcNow.AddMonths(1));

				var x509 = gen.Generate(signatureFactory);
				x509.CheckValidity(DateTime.UtcNow);
				x509.Verify(keyPair.Public);

				using (var stringWriter = new StringWriter())
				{
					var writer = new PemWriter(stringWriter);
					var pog = new PemObject("CERTIFICATE", x509.GetEncoded());
					writer.WriteObject(pog);
					return stringWriter.ToString();
				}
		}

		public string DecodeJwt(string tokenData, AsymmetricKeyParameter privateKey)
		{
			var token = Parse(tokenData);
			return DecodeAndDecrypt(token, privateKey);
		}

		private string DecodeAndDecrypt(byte[][] parts, AsymmetricKeyParameter key)
		{
			byte[] header = parts[0];
			byte[] encryptedCek = parts[1];
			byte[] iv = parts[2];
			byte[] cipherText = parts[3];
			byte[] authTag = parts[4];

			var cek = Unwrap(encryptedCek, key);
			var aad = Encoding.UTF8.GetBytes(Serialize(header));

			return Decrypt(cek, iv, aad, cipherText, authTag);
		}

		private string Serialize(params byte[][] parts)
		{
			var builder = new StringBuilder();

			foreach (var part in parts)
			{
				builder.Append(Base64UrlEncode(part)).Append(".");
			}

			builder.Remove(builder.Length - 1, 1);

			return builder.ToString();
		}

		private byte[][] Parse(string token)
		{
			string[] parts = token.Split('.');

			var result = new byte[parts.Length][];

			for (int i = 0; i < parts.Length; i++)
			{
				result[i] = Base64UrlDecode(parts[i]);
			}

			return result;
		}

		private byte[] Unwrap(byte[] encryptedCek, AsymmetricKeyParameter key)
		{
			var decryptEngine = new OaepEncoding(new RsaEngine());
			decryptEngine.Init(false, key);
			var deciphered = decryptEngine.ProcessBlock(encryptedCek, 0, encryptedCek.Length);
			return deciphered;
		}

		//Preconfigured Encryption Parameters
		private static readonly int MacBitSize = 128;

		/// <summary>
		/// Performs AES decryption in GCM chaining mode over cipher text
		/// </summary>
		/// <param name="cek">aes key</param>
		/// <param name="iv">initialization vector</param>
		/// <param name="aad">additional authn data</param>
		/// <param name="cipherText">cipher text message to be decrypted</param>
		/// <param name="authTag">authentication tag</param>
		/// <returns>decrypted plain text messages</returns>
		private string Decrypt(byte[] cek, byte[] iv, byte[] aad, byte[] cipherText, byte[] authTag)
		{
				var keyParameter = new KeyParameter(cek);
				var gcmParameters = new AeadParameters(
					keyParameter,
					MacBitSize,
					iv);

				var gcmMode = new GcmBlockCipher(new AesFastEngine());
				gcmMode.Init(false, gcmParameters);
				gcmMode.ProcessAadBytes(aad, 0, aad.Length);

				var cipherBuffer = cipherText.Concat(authTag).ToArray();
				var plainBytes = new byte[gcmMode.GetOutputSize(cipherBuffer.Length)];
				var res = gcmMode.ProcessBytes(cipherBuffer, 0, cipherBuffer.Length, plainBytes, 0);
				gcmMode.DoFinal(plainBytes, res);

				var plain = Encoding.UTF8.GetString(plainBytes, 0, plainBytes.Length);
				return plain;
		}

		// from JWT spec
		public byte[] FromBase64Url(string base64Url)
		{
			string padded = base64Url.Length % 4 == 0
				? base64Url : base64Url + "====".Substring(base64Url.Length % 4);
			string base64 = padded.Replace("_", "/")
									.Replace("-", "+");
			return Convert.FromBase64String(base64);
		}

		// from JWT spec
		public string Base64UrlEncode(byte[] input)
		{
			var output = Convert.ToBase64String(input);
			output = output.Split('=')[0]; // Remove any trailing '='s
			output = output.Replace('+', '-'); // 62nd char of encoding
			output = output.Replace('/', '_'); // 63rd char of encoding
			return output;
		}

		// from JWT spec
		private byte[] Base64UrlDecode(string input)
		{
			var output = input;
			output = output.Replace('-', '+'); // 62nd char of encoding
			output = output.Replace('_', '/'); // 63rd char of encoding
			switch (output.Length % 4) // Pad with trailing '='s
			{
				case 0: break; // No pad chars in this case
				case 1: output += "==="; break; // Three pad chars
				case 2: output += "=="; break; // Two pad chars
				case 3: output += "="; break; // One pad char
				default: throw new Exception("Illegal base64url string!");
			}
			var converted = Convert.FromBase64String(output); // Standard base64 decoder
			return converted;
		}
	}
}

Its usage is demonstrated by the following unit tests:


<pre>using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using FluentAssertions;
using Jose;
using NUnit.Framework;
using Org.BouncyCastle.Crypto.Parameters;

namespace JoseJWE.Tests
{
	[TestFixture]
	public class CryptoServiceTests
	{
		private const string TokenPlainText = "{\"sub\":\"roycornelissen\",\"aud\":\"sample app\",\"nbf\":136424444,\"iss\":\"https://api.someorganization.com\",\"preferred_username\":\"Roy Cornelissen\",\"exp\":1364293137,\"given_name\":\"Roy\",\"iat\":13642555,\"family_name\":\"Cornelissen\",\"preferred_language\":\"nl-NL\"}";

		[Test]
		public void GenerateCertificate_Generates_Valid_X509Certificate()
		{
			var g = new CryptoService();
			var keyPair = g.GenerateKeyPair();

			var pemEncodedCertificate = g.GeneratePemEncodedCertificate(keyPair).ToString();

			var p = new Org.BouncyCastle.X509.X509CertificateParser();
			var certDecoded = p.ReadCertificate(Encoding.UTF8.GetBytes(pemEncodedCertificate));

			certDecoded.Should().NotBeNull();
			certDecoded.NotBefore.Should().BeBefore(DateTime.UtcNow);
			certDecoded.NotAfter.Should().BeAfter(DateTime.UtcNow);
		}

		[Test]
		public void Certificate_Used_For_JWT_Encryption_JWE_Can_Be_Decrypted()
		{
			var g = new CryptoService();
			var keypair = g.GenerateKeyPair();

			var cert = g.GeneratePemEncodedCertificate(keypair);
			var base64Certificate = g.Base64UrlEncode(Encoding.UTF8.GetBytes(cert));

			// try to perform local encryption and decryption for reference
			var p = new Org.BouncyCastle.X509.X509CertificateParser();
			var certDecoded = p.ReadCertificate(g.FromBase64Url(base64Certificate));

      // use 3rd party library JOSE-JWT to encode the JWT (only works in .NET, not from PCL!)
			var publicRsaKey = ToRSA((RsaKeyParameters)certDecoded.GetPublicKey());
			var encrypted = JWT.Encode(TokenPlainText, publicRsaKey, JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM);

			// now attempt to decode it using our own cryptoService
			var plainText = g.DecodeJwt(encrypted, keypair.Private);
			plainText.Should().Be(TokenPlainText);
		}
    
    public static RSA ToRSA(RsaKeyParameters rsaKey)
    {
        RSAParameters rp = ToRSAParameters(rsaKey);
        RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider();
        rsaCsp.ImportParameters(rp);
        return rsaCsp;
    }

    private static RSAParameters ToRSAParameters(RsaKeyParameters rsaKey)
    {
        RSAParameters rp = new RSAParameters();
        rp.Modulus = rsaKey.Modulus.ToByteArrayUnsigned();
        if (rsaKey.IsPrivate)
            rp.D = rsaKey.Exponent.ToByteArrayUnsigned();
        else
            rp.Exponent = rsaKey.Exponent.ToByteArrayUnsigned();
        return rp;
    }
	}
}</pre>

The entire Gist is here on GitHub.

Advertisements

There is no app! – LevelUp Mobile slides

 

On September 22nd, 2016 I presented a session called “There is no app!” at the LevelUp Mobile 2016 event in Leusden. Here are the slides and video of that presentation:

[The video will be placed here shortly]

Abstract
Mobile platforms are evolving and getting richer and richer in features with every new release. The OS itself is becoming the primary interface for users to interact with, as are a new category of (wearable) devices.

What does this mean for us as app developers? Are the days of the traditional “mobile app” numbered? How do we serve our end users and optimize their mobile moment as much as possible?

The average smartphone owner has installed over 100 apps on their phone while they only use between 3 and 5 apps a day. By integrating your app more deeply into the mobile operating system can greatly increase the usage of the app. During this session we will show what you can do to integrate your apps in the Windows, iOS and Android platforms to keep your app top of mind. We’ll look at spotlight search, universal links, app indexing, Cortana integration and other APIs provided by iOS and Google Play services to engage your users in your apps. We’ll also look at new interaction models that are closer to the mobile platform: widgets, 3D-Touch, etc.

Ceci n’est pas une app

LevelUpMobile_logoRGBCall to action: join us at LevelUp Mobile on September 22nd in Leusden for a FREE inspirational evening on the future of Mobility and Devices.

 

The mobile platform war has been raging for almost ten years now. For now, it seems that Google (Android) and Apple (iOS) have won. (link) Microsoft, though still pushing Windows 10 for mobile as well, has accepted this and started providing high quality mobile apps for both Android and iOS.

Apple and Google have invested a lot in making their platforms richer and richer to attract and retain users. Apple’s advantage of 100% vertical integration of software and hardware has allowed them to create experiences like Apple Pay, 3D-Touch and Touch-ID that are very appealing to users and developers alike. At the same time, both Apple and Google have been putting features into the OS and stock apps that are competing with 3rd party offerings in the App Store. Furthermore, users have come to expect the same experience they get from their OS from 3rd party apps. Though some platform features might seem alike between iOS, Android and Windows, the way they are implemented can vastly differ and require access to core platform API’s.

As a strong proponent of Xamarin, I’ve been working in the world of cross platform mobile app development for almost 6 years now. The reason we chose to go with Xamarin was – first of all – of course the ability to share code amongst platforms, but – equally important – full access to the native platform API’s and the ability to create 100% native experiences. Given the trend of ever innovating mobile platforms, this puts us at a huge advantage over cross platform solutions that go for the lowest common denominator, both in UI (the same UI across all platforms) and UX (most of the time just the common superficial feature set across platforms).

With iOS 10, Apple is showing us a trend where apps can be integrated even deeper in the core OS experience. Of course we already had widgets in Android, but what to think about interactive widgets in iOS’s Today view, enriched with Siri’s AI capabilities? Interactive notifications are becoming more popular. Where a notification used to be a way to alert the user and allow them to open the accompanying app by tapping on it, notifications are becoming a User Interface by themselves, allowing the user to deal with the app’s functionality right from the lock screen.

ios-10-interactive-notifications
Deal with a notification right away from the Home screen. No need to open the app!
The boundaries of apps are blurring even more with advanced features like 3D-touch on the Home screen, and the ability to interact with apps from the Siri screen:

iOS-10-Control-Center-3D-Touch-iPhone-screenshot-001
Direct access to an app’s features through 3D-Touch. No need to open the app!

open_app_in_siri
Siri knows how to invoke your app and show it as a widget right inside its own interface. No need to open the app!

apps_in_imessage
iMessage can invoke your app right from its own interface. No need to open your app!
These are all iOS examples, by the way, but similar features can be found in Android and Windows 10, with its Live Tiles, Cortana integration, etcetera.

In general, user interaction with their mobile devices is becoming more and more streamlined, and to stay ahead as developers, we need to start thinking about these micro-interactions, these Mobile Moments, and offer the most efficient experience with our apps.

Mobile is not a neutral platform (link). The philosophy of web applications (built for browsers, available everywhere, with a consistent user experience everywhere) doesn’t apply here. We don’t build for the web, we build for the OS. Yay for native development! 🙂

spoon-boy
There is no spoon.
If we follow this train of thought, it leads us to an existential question: is there actually an app?

I would argue: not anymore – at least not in the traditional sense where we have an icon sitting on the home screen that launches into an application that comes into the foreground and occupies the whole screen. It seems like the days of the mobile “app” are numbered and we have to start thinking about apps as a set of autonomous micro-interactions that work together with the OS and/or other apps.

Luckily for us, as developers, there are plenty of new API’s and frameworks that help us build these interactions and I think it will only become more exciting from a technical perspective to build mobile experiences.

LevelUpMobile_logoRGB

On September 22nd, I’m joining Brechtje de Leij (mobile strategist and expert), Jorn de Vries of Flitsmeister fame, Johan Gorter & Rick Hoving from AFAS Software and the ever brilliant Laurent Bugnion to speak at a one-off inspiring event about the future of Mobile and Devices: LevelUp Mobile. Together with my colleague Geert, our talk is going to be about the exact topic of this blogpost and we’ll show some real life examples of how to implement these Mobile Moments using Xamarin.

If you have not registered yet, you can do it here: http://www.levelupmobile.nl! It’s free and it’s going to be fun!

To get more inspired, read Laurent’s teaser blog post about his upcoming talk: A world of devices.

Xamarin Evolve 16 – Training day 1

Hi there from Orlando, FL! Yesterday was the first day of the Xamarin Evolve 16 pre-conference training. And man, we’re already having a blast here. Evolve 16 is even bigger than the previous one, and on the pre-conf training alone, there are more people than there were at the original, legendary Evolve 2013; in total! Impressive.

Finally it's happening! #XamarinEvolve

A post shared by Roy Cornelissen (@roycornelissen) on

My mobile peer at Xpirit, Geert and I arrived on Saturday, together with a bunch of fellow Dutchies including some of my former colleagues from Info Support. It’s nice to catch up and hang out.

In the training, we’re doing the Intermediate track, which offers some more advanced topics. I have to say that most of the topics are already familiar, but for us this is also a great opportunity to get to know the Xamarin University material. We’re working towards certifying ourselves for delivering the official Xamarin University training curriculum at Xpirit to be the first Dutch Xamarin Training Partner! How awesome is that? Stay tuned for more news!

The main topics we covered were:

Asynchronous programming with async/await
For this module we dove into the mechanics behind the Task Parallel Library in .NET and the async/await keywords. This stuff is so important to get right as it’s crucial for quality apps to make sure that you’re not wasting the main UI thread by doing expensive work like heavy CPU-bound work or (network) I/O. The course went into some of the mechanics of async/await – with the compiler generated state machine that ends up in the generated IL.

The problem with async/await is that the syntactic sugar makes it almost too easy to make work inside your app asynchronous. The point is that making things asynchronous isn’t always necessary and using async/await the wrong way may actually hurt the app in the sense of complexity and possibly performance more than it helps. Understanding the state machine that the compiler generates, the effects of ConfigureAwait(false), working with the Dispatcher, etcetera is crucial if you want your apps to be responsive.

Patterns for reuse
A topic that’s dear to my heart. Marcel and I actually did a pretty popular talk about it at Evolve 2013. IMO, this stuff all still holds true, however we have progressed a bit when it comes to the maturity of the Xamarin platform. With the advent of Xamarin.Forms, more and more code sharing techniques are possible and go right up to the top UI level. On the other hand, Xamarin.Forms already takes away a lot of the hard work of bridging platforms. Very nice, but – my pet peeve – beware of the abstractions! 🙂

It all comes down to keeping things as simple as possible. In the training, we talked through using the Factory and Service Locator patterns, but our common conclusion was that they involve a fair amount of Yak Shaving.

front

In the end, Dependency Injection is a relatively clean way of dealing with dependencies that have per platform implementations. In my experience, using a light weight DI container like SimpleIoC is sufficient for most apps. Let’s be honest, in an average app, you don’t really need much sophisticated lifetime management or other things. You just want to be able to swap in per platform implementations of some components to use them from shared code. But before you start building your own components, head over to Xamarin’s plugin repo on GitHub because a lot of plugins are already available. And they generally use DI to set up.

Testing
We talked about the techniques that are at our disposal for validating the quality of your app. Of course using unit tests should be a no-brainer to developers, and there are actually some nice scenarios for testing the behaviour of your ViewModels and other logic in your app. These unit tests, being independent and mostly having their dependencies stubbed (another advantage of using DI is that it makes stubbing a bit easier), can give you the quickest feedback during your development cycle.

But an important part of your app will be the UI and that actually runs on the device. This has always been hard to test and we had a look at what Xamarin Test Cloud has to offer and the UITest API’s that you use to drive those tests. In a recent talk, I used this test pyramid diagram to show the stack I like to use for testing mobile apps:

mobile-test-stack.png

Note that I still think that there will always be a certain amount of manual testing involved for the more complex cases. And specifically those cases where you want to check the behaviour of your app under different circumstances, such as actually being on the move through tunnels or other low connection situations, or being out in the field to make actual pictures with the camera. Manual field tests by the team and beta test platforms like HockeyApp, Apple TestFlight and Google Play Beta are excellent tools for this.

Xamarin sure knows how to throw a party… #XamarinEvolve

A post shared by Roy Cornelissen (@roycornelissen) on

After the training it was time for some relaxation at LaFayette’s. Excellent food and great Southern style live music, and all the familiar faces from the Xamarin community there. Great to see everyone again! Really looking forward to the next few days!

To infinity, and beyond!
On Sunday, we had some spare time, so we spent the day at the NASA Kennedy Space Center. Wow what an amazing trip! It was incredible to see the huge rockets, it’s impossible to fathom how big they are until you see them. The same goes for the Space Shuttle. The Atlantis Space Shuttle is on display and you can see it up close. Super cool!

Awesome, the Atlantis Space Shuttle #nasa

A post shared by Roy Cornelissen (@roycornelissen) on

Rocket science

A post shared by Roy Cornelissen (@roycornelissen) on

The biggest surprise came when we went on the bus tour to the actual launch site. Again, it’s impossible to fathom the scale of the site and the equipment there that’s used for space travel. At the end we got a great show about the Apollo missions. The actual control center used for the Apollo mission is there on display. And then there’s the overwhelming and HUGE replica of the Apollo rocket.

Appollo Control Center #nasa

A post shared by Roy Cornelissen (@roycornelissen) on

And the coolest thing was: our Uber driver who took us back to the hotel was an engineer on the Space Shuttles for 30 years! So he could give us some fun behind-the-scenes insights. Did you know for example that there was an actual Coca Cola machine installed in one of the shuttles? That was to test the effects of carbonation in space. But since Coca Cola is a commercial company, NASA was not allowed to talk about that 😉

Oh and don’t you just love these vintage posters?

Love these vintage graphic posters #nasa

A post shared by Roy Cornelissen (@roycornelissen) on

NASA is recruiting #nasa

A post shared by Roy Cornelissen (@roycornelissen) on

Xpirit: Off to new adventures

Today marks an important day for me personally… After 15 years, I’ve left Info Support last Friday to pursue a new adventure in my career. Today, I joined a great team, starting up a wholly new company named Xpirit.

Looking back
Info Support has been a part of my life for 15 years. I did my graduation project at Info Support in 1999, and after getting my Bachelor’s degree, I signed up to work for them as a software developer and consultant. Flash forward to 2014 and I find myself working as a software architect, heading up the Enterprise Mobile competence center, speaking at international software conferences and blogging, tweeting and sharing knowledge with awesome peers from all over the world. I learned so much in my time at Info Support, and I owe a lot to the great bunch of people there. In return, I gave my best over these 15 years and helped Info Support to be in the top of Dutch IT. Now the time has come for me to take on this new opportunity.

Xprit Think ahead. Act now.
Xpirit is a new consulting company, focusing entirely on the Microsoft ecosystem. With a fantastic new team, consisting of Microsoft MVP’s, Regional Directors and community leaders, we will offer high end consulting services for (enterprise) companies looking to implement or integrate systems using the Microsoft stack. This doesn’t mean that we will focus solely on MS products though. The Microsoft ecosystem is extremely rich with Open Source frameworks and 3rd party solutions.

Our technical team consists of Marcel de Vries (CTO), Alex Thissen, Marcel Meijer, Patriek van Dorp (soon) and myself and is powered by our Sales and Managing Director Pascal Greuter. This sounds like a dream team to me, and I’m extremely excited to be a part of it. Each brings their own strengths and personality to the table, which makes for a great environment to work in.

dreamteam cap

For me personally this means that I will continue to focus on cloud and mobile architecture and development in the enterprise. Of course, Xamarin will continue to be a big part of my strategy in this. Microsoft makes fantastic technology to build services and back end architectures, but let’s face it, their end user facing technologies are struggling to keep up with Google’s and Apple’s. It’s a diverse world, in which iOS and Android co-exist with – even dominate – Windows, even more so in the mobile area. Xamarin enables us to leverage the highly productive language and frameworks from the Microsoft stack directly on iOS and Android. A perfect fit. Marcel and I will continue to be active in the Xamarin community, and run the Dutch Mobile .NET Developers user group together with the fine people from Macaw and Info Support.

Many also know that I also enjoy working on distributed systems, SOA and event driven architectures. Azure is a great platform for this. One framework that I’ve been specialising in for the last couple of years, is NServiceBus. I’m committed to continuing my activities in the NServiceBus community, and would love to be your go-to-guy for distributed systems design with NServiceBus.

Xpirit is a Xebia company, which means that we’re fortunate to inherit the same company strenghts and values that make Xebia a great company. If you’re interested, go check out Good To Great by Jim Collins, Winning by Jack Welch, and Eckart’s Notes by Eckart Wintzen to understand the foundations we’re going to build on. Inspiring stuff, that’s for sure!

We’re starting small, but thinking big. We’re looking forward to great and innovating projects in the world of cloud, mobile, IoT and everything Microsoft.

I can’t wait to see what the future holds. Here’s to new adventures!

the-hobbit-adventure