Musings ·

Sugar

I have a confession, I have a sweet tooth. I love sugar. I know it’s bad for me, but I can’t help myself at times. In my defense, I try hard to limit my intake. I avoid fizzy drinks for the most part, but I probably over-indulge in cake (and biscuits). Who doesn’t love cake?

Dentists have long known sugar is bad for you. The rest of us have probably been in denial to some extent. And given the kind of energy and money thrown at pushing sugar in front of us, is it any suprise?

I used to work at Coca-Cola. What I saw horrified me ##I used to work at Coca-Cola. What I saw horrified me

The Independent by Chris Hemmings

Like an over-shaken can, outrage is spilling everywhere today. An investigation by The Times has outlined how Coca-Cola spends millions of dollars every year trying to disprove the undisprovable. Frankly, anyone gullible enough to believe any ‘research’ suggesting cans of fizzy sugar don’t make you fat is an idiot, but that’s not the real problem here.

But just how bad is it? Pretty bad. This (long) article from the Guardian is a fascinating read.

The Sugar Conspiracy ##The Sugar Conspiracy

the Guardian by Ian Leslie

The long read: In 1972, a British scientist sounded the alarm that sugar - and not fat - was the greatest danger to our health. But his findings were ridiculed and his reputation ruined. How did the world’s top nutrition scientists get it so wrong for so long?

I suspect I may be too weak-willed to overhaul my sugar-ingesting habits, but I’d like to think I can trim it down.

PlantUml Text Encoding

A lot of UML I find cumbersome and not terribly helpful. However, when dealing with a large data model, a class diagram can be really helpful. A key problem though is the maintenance overhead, so I went hunting for a class diagram format that I could automate in our build and would look good in a source control history. I stumbled upon PlantUML, text-based definitions for UML diagrams. Perfect.

PlantUML also provide a Web Service that can be called to generate SVG/PNG from the text-based definition. As with so many things, there’s a catch. Custom encoding. Fortunately it’s a fairly simple port over to the C# code I needed and here it is. Might be useful to someone…

Available on GitHub

And as PlantUML Text Encoder.linq

using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Text;

namespace PlantUml.Utils
{
   public class PlantUmlTextEncoder
   {
      public string Encode(TextReader reader)
      {
         using (var output = new MemoryStream())
         {
            using (var writer = new StreamWriter(new DeflateStream(output, CompressionLevel.Optimal), Encoding.UTF8))
               writer.Write(reader.ReadToEnd());
            return Encode(output.ToArray());
         }
      }
      
      private static string Encode(IReadOnlyList<byte> bytes)
      {
         var length = bytes.Count;
         var s = new StringBuilder();
         for (var i = 0; i < length; i += 3)
         {
            var b1 = bytes[i];
            var b2 = i + 1 < length ? bytes[i + 1] : (byte) 0;
            var b3 = i + 2 < length ? bytes[i + 2] : (byte) 0;
            s.Append(Append3Bytes(b1, b2, b3));
         }
         return s.ToString();
      }
      
      private static char[] Append3Bytes(byte b1, byte b2, byte b3)
      {
         var c1 = b1 >> 2;
         var c2 = (b1 & 0x3) << 4 | b2 >> 4;
         var c3 = (b2 & 0xF) << 2 | b3 >> 6;
         var c4 = b3 & 0x3F;
         return new[]
         {
            EncodeByte((byte) (c1 & 0x3F)),
            EncodeByte((byte) (c2 & 0x3F)),
            EncodeByte((byte) (c3 & 0x3F)),
            EncodeByte((byte) (c4 & 0x3F))
         };
      }
      
      private static char EncodeByte(byte b)
      {
         var ascii = Encoding.ASCII;
         if (b < 10)
            return ascii.GetChars(new[] {(byte) (48 + b)})[0];
         b -= 10;
         if (b < 26)
            return ascii.GetChars(new[] {(byte) (65 + b)})[0];
         b -= 26;
         if (b < 26)
            return ascii.GetChars(new[] {(byte) (97 + b)})[0];
         b -= 26;
         if (b == 0)
            return '-';
         if (b == 1)
            return '_';
         return '?';
      }
   }
}

Complexity is your enemy

Words along these lines are often uttered in our office. Nice to see we’re in good company.

Complexity is your enemy - Virgin.com ##Complexity is your enemy - Virgin.com

Virgin.com

Complexity is your enemy. Any fool can make something complicated. It is hard to make something simple….

Family time at Marwell Wildlife

Family time @ Marwell Wildlife

Google Login and OWIN

In my adventures trying to get to grips with OWIN and WebAPI my next step was to look at how I can use Google as an external OAUTH login provider. My simple app will use Google as its sole form of login so I wanted to fire up my LINQPad OWIN template and flesh out the extra steps required to prove a Google login.

Starting out with my template there’s a couple of additional NuGet packages we’re going to need.

Microsoft.Owin.Security.Cookies
Microsoft.Owin.Security.Google

I want to be able to prove a login and logout scenario and show that protected routes aren’t available to unauthenticated users. So to start let’s lock down our api controller with the Authorize attribute:

[RoutePrefix("api"), Authorize]
public class DefaultController : ApiController
{
   \\ Snipped...
}

In order to kick-off authentication (and to sign out again) we’ll need some form of account controller. To begin with just return a 200 for login and for logout, we’ll fill these out later.

[RoutePrefix("account")]
public class AccountController : ApiController
{
   [HttpGet, Route("login")]
   public IHttpActionResult Login(string returnUrl = null)
   {
      return Ok();
   }

   [HttpGet, Route("logout")]
   public IHttpActionResult Logout()
   {
      return Ok();
   }
}

It seems that the external login providers require cookie-based authentication in order to function. I had a bit of a play with other mechanisms for maintaining authentication state without success. Hopefully this will change in future versions but for now we need to tell the OWIN pipeline to use cookie authentication.

var cookieOpts = new CookieAuthenticationOptions
{
   LoginPath = new PathString("/account/login"),
   CookieSecure = CookieSecureOption.SameAsRequest
};
app.UseCookieAuthentication(cookieOpts);

This code goes into the top of the OWIN Startup configuration method. UseCookieAuthentication adds OWIN middleware to the pipeline that monitors the response flow and transforms 401 responses from Web Api into 302 responses redirecting the user to the path given in LoginPath.

At this point we already have everything we need to redirect an unauthenticated access to /api to our login at /account/login. Next step is to configure a login workflow.

It’s worth noting the CookieSecure property of CookieAuthenticationOptions, by default this is set to SameAsRequest so the cookie middleware will issue insecure cookies over HTTP. In a prod environment it’s probably best to set this to Always.

In order to use Google for external login we need to add in the Google Authentication middleware. In it’s simplest form this requires your Client Id and Client Secret from the Google Developer Console. This configuration needs to go into OWIN Startup after the cookie authentication configuration.

app.SetDefaultSignInAsAuthenticationType(cookieOpts.AuthenticationType);
var googleOpts = new GoogleOAuth2AuthenticationOptions
{
   ClientId = "<my-client-id>",
   ClientSecret = "<my-client-secret>"
};
app.UseGoogleAuthentication(googleOpts);

Post-authentication Google will only redirect users back to one of a list of Redirect URLs specified in your Developer Console. By default the Google provider will specify a redirect URL of /signin-google. You can override this in GoogleOAuth2AuthenticationOptions but there’s generally no need. The provider appears to internally register a route matching this path so a little bit of magic happens. :-)

The call to SetDefaultSignInAsAuthenticationType ensures that the Google login provider comes back with an Authentication Type that ties up to the cookie middleware, without this our login cookie won’t be issued and there’ll be no access for you (or anyone else).

We’ve now told OWIN to send unauthenticated requests to /account/login and that we’d like to use Google as a login provider but there still remains a step to kick the Google provider into action. In the real world you’d likely want a nice page informing your user they need to log in by clicking a pretty Google button, but for now we’ll keep it much simpler and just modify our Account Controller.

[HttpGet, Route("login")]
public IHttpActionResult Login(string returnUrl = null)
{
   var authProps = new AuthenticationProperties
   {
      RedirectUri = returnUrl
   };
   Request.GetOwinContext().Authentication.Challenge(authProps, "Google");
   return StatusCode(HttpStatusCode.Unauthorized);
}

The above login method tells the authentication middleware that it should challenge using the Google provider, we also return an HTTP 401. This kicks the server into initiating the Google OAuth login and sets us on our way. So the overall flow here is:

  1. User accesses \api
  2. asp.net returns an HTTP 401 due to the Authorise attribute
  3. Cookie authentication provider intercepts this and returns an HTTP 302 to /account/login
  4. The Account Controller adds a “Google” challenge and returns another HTTP 401
  5. Google authentication provider intercepts the challenge and initiates a Google login

The returnUrl parameter for Login matches the default value of CookieAuthenticationOptions.ReturnUrlParameter. The cookie middleware appends a parameter of this name to the query string when it makes a login redirect. The earlier magic of the /signin-google route will pick this up post-auth and send the user back to the URL they originally tried to access.

And we’re almost done. To be tidy we can use our logoff action to clear down the access token granted in the OAuth exchange. Again, this is dead simple:

[HttpGet, Route("logoff")]
public IHttpActionResult Logout()
{
   Request.GetOwinContext().Authentication.SignOut();
   return Ok();
}

Download Owin SelfHosted WebAPI - Google Login.linq