alexbilbie.comhttp://alexbilbie.com/
Posts from alexbilbie.comen-gbThu, 18 Jan 2018 08:50:24 +0000Thu, 18 Jan 2018 08:50:24 +0000Coding Solo episode 6http://alexbilbie.com/2017/11/coding-solo-episode-6Fri, 24 Nov 2017 00:00:00 +0000Alex Bilbie
<p>In episode six of <a href="https://codingsolo.works/">Coding Solo</a>, I talked about yet another holiday, we talk about how our new video-based ventures are going, and how we validate those ideas we have in the shower (or crawling through the Củ Chi tunnels).</p>
<p>Please do send us any feedback you have especially if there any topics you feel we should cover or any questions you’d like us to answer about freelancing. You can email us at <a href="mailto:feedback@codingsolo.works">feedback@codingsolo.works</a>.</p>
<iframe width="450" height="450" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/354850412&amp;color=%23ff5500&amp;auto_play=false&amp;hide_related=true&amp;show_comments=false&amp;show_user=true&amp;show_reposts=false&amp;show_teaser=false&amp;visual=true"></iframe>
<p><a href="http://alexbilbie.com/2017/11/coding-solo-episode-6/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Coding Solo episode 5http://alexbilbie.com/2017/09/coding-solo-episode-5Thu, 21 Sep 2017 00:00:00 +0000Alex Bilbie
<p>In episode five of <a href="https://codingsolo.works/">Coding Solo</a>, we talked about finally meeting in person at the Laravel London September meetup, answer more listener questions, the ups and downs of running open source projects and finish off with their thoughts on Apple’s announcements at the iPhone Event.</p>
<p>Please do send us any feedback you have especially if there any topics you feel we should cover or any questions you’d like us to answer about freelancing. You can email us at <a href="mailto:feedback@codingsolo.works">feedback@codingsolo.works</a>.</p>
<iframe width="450" height="450" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/343383763&amp;color=%23ff5500&amp;auto_play=false&amp;hide_related=true&amp;show_comments=false&amp;show_user=true&amp;show_reposts=false&amp;show_teaser=false&amp;visual=true"></iframe>
<p><a href="http://alexbilbie.com/2017/09/coding-solo-episode-5/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Getting the AWS X-Ray deamon to run on Alpine Linuxhttp://alexbilbie.com/2017/08/aws-xray-deamon-alpine-linuxThu, 31 Aug 2017 00:00:00 +0000Alex Bilbie
<p><a href="https://aws.amazon.com/xray/">X-Ray</a> is a managed distributed tracing service by Amazon Web Services. Your application (whether it’s a single API or made up of multiple distributed microservices) collects data (such as timing and metrics for business logic, SQL queries and calls to AWS services) whilst processing incoming requests and then sends this data to a local deamon over UDP which in turn forwards the data onto the X-Ray service.</p>
<p>I’ve been experimenting with bundling the <a href="http://docs.aws.amazon.com/xray/latest/devguide/xray-daemon.html">X-Ray deamon</a> into an <a href="https://alpinelinux.org/">Alpine Linux</a> container alongside some other binaries however out of the box it didn’t work. Attempting to execute the <code class="highlighter-rouge">xray</code> binary would result in a confusing error message like this:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sh: /xray: not found
</code></pre></div></div>
<p>After some Googling I discovered the <code class="highlighter-rouge">ldd</code> command which is used to find the shared libraries that a binary calls.</p>
<p>Executing <code class="highlighter-rouge">ldd xray</code> I get the following output:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/ # ldd xray
/lib64/ld-linux-x86-64.so.2 (0x55a247c9b000)
libpthread.so.0 =&gt; /lib64/ld-linux-x86-64.so.2 (0x55a247c9b000)
libc.so.6 =&gt; /lib64/ld-linux-x86-64.so.2 (0x55a247c9b000)
</code></pre></div></div>
<p>This first library that the X-Ray binary attempts to call is <code class="highlighter-rouge">/lib64/ld-linux-x86-64.so.2</code>.</p>
<p>If I list the contents of <code class="highlighter-rouge">/</code> I can see that the <code class="highlighter-rouge">/lib64</code> directory isn’t present out of the box with Alpine:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/ # ls
bin dev etc home lib media mnt proc root run sbin srv sys tmp usr var
</code></pre></div></div>
<p>My understanding is that this is because Alpine Linux uses <em>musl libc</em> instead of <em>GNU libc</em> and the <code class="highlighter-rouge">xray</code> binary is linked against <em>GNU libc</em> libraries.</p>
<p>Alpine provides a package called <a href="https://pkgs.alpinelinux.org/package/edge/main/x86/libc6-compat">libc6-compat</a> which provides compatibility libraries for glibc as well as symlinks <code class="highlighter-rouge">/lib64</code> to <code class="highlighter-rouge">/lib</code>. This can be installed with the command <code class="highlighter-rouge">apk add libc6-compat</code>.</p>
<p>After installing <code class="highlighter-rouge">libc6-compat</code> the X-Ray deamon now runs successfully.</p>
<p><a href="http://alexbilbie.com/2017/08/aws-xray-deamon-alpine-linux/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Coding Solo episode 4http://alexbilbie.com/2017/08/coding-solo-episode-4Wed, 23 Aug 2017 00:00:00 +0000Alex Bilbie
<p>In episode four of <a href="https://codingsolo.works/">Coding Solo</a>, David and I have a nice ol’ chat about our feelings when it comes to working on side projects. We also discuss taking time off from work and answer some more listener emails.</p>
<p>Please do send us any feedback you have especially if there any topics you feel we should cover or any questions you’d like us to answer about freelancing. You can email us at <a href="mailto:feedback@codingsolo.works">feedback@codingsolo.works</a>.</p>
<iframe width="450" height="450" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/338818448&amp;auto_play=false&amp;hide_related=false&amp;show_comments=false&amp;show_user=true&amp;show_reposts=false&amp;visual=true"></iframe>
<p><a href="http://alexbilbie.com/2017/08/coding-solo-episode-4/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Looking for a new maintainer of league/oauth2-serverhttp://alexbilbie.com/2017/08/looking-for-a-new-maintainer-of-league-oauth2-serverMon, 21 Aug 2017 09:39:02 +0000Alex Bilbie
<p>A little over five years ago I pushed the <a href="https://github.com/thephpleague/oauth2-server/commit/6649083e71dd7c1e095e8dd56df15f1adbc5b30c">first commit</a> for the project that eventually became <a href="https://github.com/thephpleague/oauth2-server">league/oauth2-server</a>.</p>
<p>The project has been downloaded over 2.5 million times, has more than 3000 Github stars and has been contributed to by 77 awesome people across some 2000 commits.</p>
<p>Last year when I became self-employed I had intentions that I’d have more time to dedicate towards open source projects but reality worked out slightly differently and I’ve had one of the busiest (and best) years of my life.</p>
<p>The other principal factor is truth be told I don’t actively use the project any more. This past year I’ve become more of a programming language polyglot and I’ve written more lines of JavaScript, Swift and Go than I have PHP.</p>
<p>That the project has stagnated somewhat has started to bother me greatly. Therefore I believe it is now time to hand over the reigns to someone who can devote more time and energy to the project than I’ve been able to.</p>
<p>I’ve no deadline for finding someone - I want to find the right person (or group of people) who is/are really impassioned by the project, want to advance the project (for example implement OpenID support) and are willing to devote time to answering support requests and review pull requests.</p>
<p>If you reading this are that person, or you know someone who might be please email me - <a href="mailto:hello@alexbilbie.com">hello@alexbilbie.com</a> - I’d love to have a chat with you.</p>
<p><a href="http://alexbilbie.com/2017/08/looking-for-a-new-maintainer-of-league-oauth2-server/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Coding Solo episode 3http://alexbilbie.com/2017/08/coding-solo-episode-3Sun, 13 Aug 2017 00:00:00 +0000Alex Bilbie
<p>In episode 3 of <a href="https://codingsolo.works/">Coding Solo</a> David and I talk about finding work, doing the work, invoicing for the work and hopefully getting paid on time for the work.</p>
<p>Please do send us any feedback you have especially if there any topics you feel we should cover or any questions you’d like us to answer about freelancing. You can email us at <a href="mailto:feedback@codingsolo.works">feedback@codingsolo.works</a>.</p>
<iframe width="450" height="450" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/336972510&amp;auto_play=false&amp;hide_related=false&amp;show_comments=false&amp;show_user=true&amp;show_reposts=false&amp;visual=true"></iframe>
<p><a href="http://alexbilbie.com/2017/08/coding-solo-episode-3/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Coding Solo episode 2http://alexbilbie.com/2017/07/coding-solo-episode-2Wed, 26 Jul 2017 00:00:00 +0000Alex Bilbie
<p><a href="https://twitter.com/davzie">David</a> and I are back with a new episode of our podcast about freelancing in the UK, <a href="https://codingsolo.works/">Coding Solo</a>.</p>
<p>In this episode we talk about setting up to go solo including setting up a limited company, find a bank that doesn’t suck, discussing how expenses and dividends work, how much accountants generally cost and how to run your company from an expenditure perspective.</p>
<p>Please do send us any feedback you have especially if there any topics you feel we should cover or any questions you’d like us to answer about freelancing. You can email us at <a href="mailto:feedback@codingsolo.works">feedback@codingsolo.works</a>.</p>
<iframe width="450" height="450" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/334905557&amp;auto_play=false&amp;hide_related=false&amp;show_comments=false&amp;show_user=true&amp;show_reposts=false&amp;visual=true"></iframe>
<p><a href="http://alexbilbie.com/2017/07/coding-solo-episode-2/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Introducing Coding Solo - a podcast about freelancing in the UKhttp://alexbilbie.com/2017/07/introducing-coding-soloWed, 12 Jul 2017 00:00:00 +0000Alex Bilbie
<p>I’m excited to announce <a href="https://codingsolo.works/">Coding Solo</a>, a new podcast by myself and <a href="https://twitter.com/davzie">David Thorpe</a> about freelancing in the UK.</p>
<p>Our aim for Coding Solo is to discuss both the positive and negative aspects of freelancing (in our experience and that of others) as well as talk about some of the specific UK aspects of freelancing - from taxes to IR35 to finding work.</p>
<p>Today we released our first episode “Procrastination and Prime Day”. We introduce ourselves and lightly touch on some of the topics we want to cover in depth in later episodes. We finish up with a technical chat about protocol buffers and iOS development; two things we’re both learning about as part of our current gigs.</p>
<p>Please do send us any feedback you have especially if there any topics you feel we should cover or any questions you’d like us to answer about freelancing. You can email us at <a href="mailto:feedback@codingsolo.works">feedback@codingsolo.works</a>.</p>
<iframe width="450" height="450" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/332851871&amp;auto_play=false&amp;hide_related=true&amp;show_comments=false&amp;show_user=true&amp;show_reposts=false&amp;visual=true"></iframe>
<p><a href="http://alexbilbie.com/2017/07/introducing-coding-solo/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
How to setup a Consul server cluster on EC2 in four easy stepshttp://alexbilbie.com/2017/06/consul-server-cluster-on-ec2Sun, 25 Jun 2017 00:00:00 +0000Alex Bilbie
<p>Over the past 18 months or so I’ve tried to deploy a <a href="https://consul.io">Consul</a> server cluster on EC2 several times. Ironically though for a service discovery service I’ve always had difficulty with Consul nodes failing to discover each other reliably.</p>
<p>The two most common solutions to node discovery have been to use known private IP addresses (by assigning pre-created Elatic Network Interfaces in an instance’s user-data script) or putting the Consul autoscaling group behind an internal Elastic Load Balancer. In both cases this adds unnecessary complexity and costs with the load balancer.</p>
<p>Today I discovered that in Consul 0.7.1 new configuration options were added to allow bootstrapping by automatically discovering AWS instances with a given tag key/value at startup. This is game changing because the hard work is done for you - all you need to do is ensure all of the Consul server instances share a tag and are able to communicate with one another.</p>
<p>To run your own Consul cluster you just need to follow these steps:</p>
<ol>
<li>Create an IAM role with the following policy:
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"Version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2012-10-17"</span><span class="p">,</span><span class="w">
</span><span class="s2">"Statement"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="p">{</span><span class="w">
</span><span class="s2">"Sid"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w">
</span><span class="s2">"Effect"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Allow"</span><span class="p">,</span><span class="w">
</span><span class="s2">"Action"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ec2:DescribeInstances"</span><span class="p">,</span><span class="w">
</span><span class="s2">"Resource"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div> </div>
</li>
<li>Create an EC2 security group that the Consul server instances and any other instances that need to communicate with the Consul servers can reside in.</li>
<li>Create another EC2 security group for just the Consul server instances with the following ingress rules (set the source to be the other security group you created):
<ul>
<li>TCP 8300 (Server RPC)</li>
<li>TCP 8301 (Serf LAN)</li>
<li>UDP 8301 (Serf LAN)</li>
<li>TCP 8302 (Serf WAN)</li>
<li>UDP 8302 (Serf WAN)</li>
<li>TCP 8400 (CLI RPC)</li>
<li>TCP 8500 (HTTP API)</li>
<li>TCP 8600 (DNS)</li>
<li>UDP 8600 (DNS)</li>
</ul>
</li>
<li>Finally I used the following launch configuration to download and install the Consul binary, then create and load an Upstart script to run Consul in server mode and auto-discover other instances based on the name of the autoscaling group (you could also use this script to bake an AMI):
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="c">#!/bin/sh</span>
curl <span class="nt">-O</span> https://releases.hashicorp.com/consul/0.8.4/consul_0.8.4_linux_amd64.zip
unzip consul_0.8.4_linux_amd64.zip
<span class="nb">rm</span> <span class="nt">-f</span> consul_0.8.4_linux_amd64.zip
<span class="nb">mv </span>consul /usr/local/bin
<span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt; /etc/init/consul.conf
description "Consul"
author "Alex Bilbie"
start on filesystem or runlevel [2345]
stop on shutdown
script
/usr/local/bin/consul agent \
-server \
-data-dir=/tmp/consul \
-client=0.0.0.0 \
-datacenter=AWS_REGION \
-bootstrap-expect=3 \
-ui \
-retry-join-ec2-tag-key=aws:autoscaling:groupName \
-retry-join-ec2-tag-value=NAME_OF_AUTOSCALING_GROUP
end script
</span><span class="no"> EOF
</span> initctl reload-configuration
initctl start consul
</code></pre></div> </div>
</li>
</ol>
<p>The autoscaling group that runs the launch configuration needs a min, max and desired count of 3 to maintain the quorum.</p>
<p>If you SSH into any of the Consul servers and run <code class="highlighter-rouge">/usr/local/bin/consul members</code> you should see the three instaces listed out like so:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Node Address Status Type Build Protocol
ip-10-0-1-122 10.0.1.122:8301 alive client 0.8.4 3
ip-10-0-2-12 10.0.2.12:8301 alive server 0.8.4 3
ip-10-0-2-45 10.0.2.45:8301 alive server 0.8.4 3
</code></pre></div></div>
<p>If you expose port 8500 to your IP address in the security group and visit <a href="http://server-public-ip:8500/ui">http://server-public-ip:8500/ui</a> you’ll be able to interact with the build in web interface.</p>
<p>I hope you’ll agree that it really is very simple now to get a Consul cluster up and running on EC2 without the need to mess around with network interfaces or load balancers. The configuration described above is built with high availability in mind (assuming your auto-scaling group is launching across availability zones) and is self-healing should any of your instances fail.</p>
<p><a href="http://alexbilbie.com/2017/06/consul-server-cluster-on-ec2/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Amazon Web Services Solutions Architect Associate Certificationhttp://alexbilbie.com/2017/02/amazon-web-services-solutions-architect-associate-certificationTue, 07 Feb 2017 00:00:00 +0000Alex Bilbie
<figure>
<img src="/images/aws-saa-cert.png" title="My AWS certification certificate" />
</figure>
<p>Yesterday I took my Amazon Web Services Solutions Architect Associate certification exam and I’m stoked to have passed with 90%.</p>
<p>I found the Solutions Architect exam too be much harder than the Developer exam; the questions are much more verbose - you have to make much more of a conscious decision as to what information in the given scenario is relevant and what isn’t.</p>
<p>The major themes in my exam were:</p>
<ul>
<li>VPC (ACL, security groups, private subnet connectivity, VPC peering)</li>
<li>S3 (hybrid cloud storage, ACL/bucket policies/IAM permissions and storage classes)</li>
<li>EBS (moving volumes between regions/AZs, encrypting volumes, setting up RAID)</li>
</ul>
<p>If you’re looking to take the Solutions Architect exam I’d also recommend understanding the <a href="https://aws.amazon.com/compliance/shared-responsibility-model/">AWS Shared Responsibility Model</a>.</p>
<p>As with the <a href="/2016/04/aws-developer-associate-certification/">AWS developer associate exam I took last year</a> I found the whole experience an excellent test of the knowledge I’ve picked up after two and a half years of building and maintaining multiple production environments on AWS.</p>
<p>I can’t recommend the <a href="https://acloud.guru/">ACloud Guru</a> courses enough; whilst I am very familiar with day to day operations with the vast majority of the AWS services, the guru courses really helped me better understand services that are useful for hybrid cloud environments which I’m unlikely to make as much use of.</p>
<p><a href="http://alexbilbie.com/2017/02/amazon-web-services-solutions-architect-associate-certification/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Re-Introducing Jenkins: Automated Testing with Pipelineshttp://alexbilbie.com/2017/01/re-introducing-jenkins-automated-testing-with-pipelinesThu, 05 Jan 2017 00:00:00 +0000Alex Bilbie
<p>I’ve written an article for SitePoint about using Jenkins and pipelines to test and build your code. Check it out here - <a href="https://www.sitepoint.com/re-introducing-jenkins-automated-testing-with-pipelines/">https://www.sitepoint.com/re-introducing-jenkins-automated-testing-with-pipelines/</a>.</p>
<p><a href="http://alexbilbie.com/2017/01/re-introducing-jenkins-automated-testing-with-pipelines/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Using AWS CodePipeline and CodeBuild to update a Jekyll websitehttp://alexbilbie.com/2016/12/codebuild-codepipeline-update-jekyll-websiteSun, 04 Dec 2016 00:00:00 +0000Alex Bilbie
<p>This week at the AWS Re:Invent 2016 event in Las Vegas a new <a href="https://aws.amazon.com/codebuild/">CodeBuild</a> service was introduced. CodeBuild is essentially a build service which given an input (generally code), will process it in some way and then output a build artifact.</p>
<p>My <a href="https://alexbilbie.com/">alexbilbie.com</a> blog is a static website created with <a href="https://jekyllrb.com/">Jekyll</a> and hosted with Github Pages. I’ve been wanting for sometime to move away from Github Pages and store the site in an S3 bucket however this would require some sort of mechanism to update the S3 hosted version whenever I publish a new post (which Github Pages does automatically). There are a few methods to this using CircleCI and TravisCI out there but I wanted to see if CodeBuild could be used instead.</p>
<p>My first step was to setup a new S3 bucket (using the very speedy new S3 console):</p>
<figure>
<img src="/images/codebuild-jekyll/0create-bucket.png" />
</figure>
<p>The bucket needs to be configured for static website hosting which is trivial to enable in just a few clicks:</p>
<figure>
<img src="/images/codebuild-jekyll/1bucket-static-website.png" />
</figure>
<p>Finally the bucket policy needs updating to allow anonymous reads:</p>
<figure>
<img src="/images/codebuild-jekyll/2bucket-permissions.png" />
</figure>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="s2">"Statement"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="p">{</span><span class="w">
</span><span class="s2">"Effect"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Allow"</span><span class="p">,</span><span class="w">
</span><span class="s2">"Principal"</span><span class="p">:</span><span class="w"> </span><span class="s2">"*"</span><span class="p">,</span><span class="w">
</span><span class="s2">"Action"</span><span class="p">:</span><span class="w"> </span><span class="s2">"s3:GetObject"</span><span class="p">,</span><span class="w">
</span><span class="s2">"Resource"</span><span class="p">:</span><span class="w"> </span><span class="s2">"arn:aws:s3:::alexbilbiecom/*"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>Then I navigated to the CodeBuild console and created a new project using the following settings:</p>
<figure>
<img src="/images/codebuild-jekyll/3codebuild-create-project.png" />
</figure>
<ul>
<li>Project name: <code class="highlighter-rouge">alexbilbie_com</code></li>
<li>Source provider: <code class="highlighter-rouge">github</code></li>
<li>Repository: <code class="highlighter-rouge">alexbilbie.github.com</code></li>
<li>Environment image: <code class="highlighter-rouge">Use an image maanged by AWS CodeBuild</code></li>
<li>Operating System: <code class="highlighter-rouge">Ubuntu</code> (currently the only available option)</li>
<li>Runtime: <code class="highlighter-rouge">Ruby</code></li>
<li>Version: <code class="highlighter-rouge">ruby:2.3.1</code></li>
<li>Build specification: <code class="highlighter-rouge">Use the buildspec.yml in the source code root directory</code></li>
<li>Artifact type: <code class="highlighter-rouge">No artifact</code></li>
<li>Service role: <code class="highlighter-rouge">Create a service role in your account</code></li>
</ul>
<p>Through some experimentation I discovered that if you let CodeBuild automatically upload the Jekyll build output then you can’t have the site in the root of the bucket (it will be under <code class="highlighter-rouge">&lt;artifact name&gt;/_site/</code> prefix). The CodeBuild Ruby image comes with the AWS CLI pre-installed so I used a build command to upload the result directly to the bucket root using <code class="highlighter-rouge">aws s3 sync</code> command.</p>
<p>Next up I edited the service role that the CodeBuild wizard created to allow write access to the website S3 bucket. Normally I would create the service role manually however at the time of writing you can’t create a CodeBuild service role (at least through the console).</p>
<p>I added the following to the generated policy:</p>
<figure>
<img src="/images/codebuild-jekyll/5iam-policy-permission.png" />
</figure>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>{
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::alexbilbiecom",
"arn:aws:s3:::alexbilbiecom/*"
],
"Action": [
"s3:PutObject",
"s3:Get*",
"s3:List*"
]
}
</code></pre></div></div>
<p>The final step was to add a <code class="highlighter-rouge">buildspec.yml</code> file to the root of the Github repository:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>version: 0.1
phases:
install:
commands:
- gem install jekyll jekyll-paginate jekyll-sitemap jekyll-gist
build:
commands:
- echo "******** Building Jekyll site ********"
- jekyll build
- echo "******** Uploading to S3 ********"
- aws s3 sync _site/ s3://alexbilbiecom
</code></pre></div></div>
<p>Inside the <code class="highlighter-rouge">buildspec.yml</code> you can hook into the <code class="highlighter-rouge">install</code>, <code class="highlighter-rouge">pre_build</code>, <code class="highlighter-rouge">build</code> and <code class="highlighter-rouge">post_build</code> lifecycle events as well as specify artifacts to upload to S3. In this case I just needed to hook into <code class="highlighter-rouge">install</code> and <code class="highlighter-rouge">build</code> events.</p>
<p>From here you can start a new build, I used the default settings and clicked <code class="highlighter-rouge">Start Build</code>.</p>
<figure>
<img src="/images/codebuild-jekyll/6new-build.png" />
</figure>
<p>A few minutes later…success!</p>
<figure>
<img src="/images/codebuild-jekyll/7build-success.png" />
</figure>
<p>At this point I could navigate to the bucket static site URL to verify the generated site was working correctly.</p>
<p>CodeBuild is set up but it currently requires manual triggering of build. Fortunately last year’s new service, CodePipeline can help out here.</p>
<p>In the CodePipeline console I created a new pipeline linked to the Github repository:</p>
<figure>
<img src="/images/codebuild-jekyll/8new-pipeline.png" />
</figure>
<p>Under the build setting I selected <code class="highlighter-rouge">AWS CodeBuild</code> as the build provider and selected the CodeBuild project I’d created.</p>
<p><strong>Note:</strong> Currently CodePipeline requires the build provider to produce an output which the CodeBuild project doesn’t currently have. I went back to the CodeBuild settings and set them to this:</p>
<figure>
<img src="/images/codebuild-jekyll/codebuild-artifact.png" />
</figure>
<p>I skipped the <code class="highlighter-rouge">beta</code> section of the wizard as a deployment isn’t required.</p>
<figure>
<img src="/images/codebuild-jekyll/9pipeline-build.png" />
</figure>
<p>Finally I let the console create a CodePipeline service IAM role for me and completed the wizard.</p>
<figure>
<img src="/images/codebuild-jekyll/10pipeline-beta.png" />
</figure>
<figure>
<img src="/images/codebuild-jekyll/11pipeline-service-role.png" />
</figure>
<p>Now whenever I make a change in the Github repository CodePipeline will automatically trigger CodeBuild and my website will be updated.</p>
<figure>
<img src="/images/codebuild-jekyll/12pipeline-view.png" />
</figure>
<p>From my brief look at CodeBuild it looks like the start of a really useful service. Usually I set clients up with a Jenkins build server however from my brief play here and some reading of the documentation I’m keen to explore the service more to see to what extent it could potentially replace Jenkins in the future.</p>
<p><a href="http://alexbilbie.com/2016/12/codebuild-codepipeline-update-jekyll-website/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Can't Eat That - An app for food allergy sufferershttp://alexbilbie.com/2016/10/cant-eat-thatFri, 14 Oct 2016 00:00:00 +0000Alex Bilbie
<p>This year I’ve been fortunate to travel a lot more than I ever have done - from Denmark to Japan to France to Canada and the US as well.</p>
<p>I have a severe allergy to tree nuts and legumes (such as peanuts) and this often presents a problem when expressing my dietary requirements both abroad and in new restaurants at home due to language barriers.</p>
<p>There are a few different companies out there that will happily sell you credit card-sized allergy translation cards at £5-10 per language but in a world where I’m more likely to have my iPhone on me than my wallet I decided an app makes more sense.</p>
<p>About 18 months ago I took a short iOS Swift course with Treehouse but I never really got into it. This time, armed with an actual end goal in mind (always useful when learning new things), I sat down and refreshed my understanding and built an app I’ve called <a href="https://canteatthat.com"><strong>Can’t Eat That</strong></a>.</p>
<figure>
<img src="/images/cant-eat-that/home-iphone.jpg" />
</figure>
<p>Working with a <a href="https://applingua.com/">fantastic translation agency</a> in Cardiff (hi Rob!) the app has phrases describing 11 allergies in 18 languages.</p>
<p>The allergies included in the app are based on the <a href="https://www.food.gov.uk/sites/default/files/food-allergen-labelling-technical-guidance.pdf">EU’s food allergen label requirements</a> (generally the items highlighted on an food wrapper ingredients label):</p>
<ul>
<li>Eggs</li>
<li>Fish</li>
<li>Gluten</li>
<li>Milk</li>
<li>Soy and soybeans</li>
<li>Nuts and nut oil</li>
<li>Peanuts and peanut oil</li>
<li>Crustaceans (such as prawns and crabs)</li>
<li>Molluscs (such as mussels and squid)</li>
<li>Celery and celeriac</li>
<li>Mustard</li>
<li>Sesame</li>
<li>Sulfur</li>
<li>Lupin</li>
</ul>
<p>The lovely team at Applingua expertly translated these allergies into the following languages:</p>
<ul>
<li>Arabic</li>
<li>Chinese</li>
<li>French</li>
<li>German</li>
<li>Greek</li>
<li>Hindi</li>
<li>Indonesian</li>
<li>Italian</li>
<li>Japanese</li>
<li>Korean</li>
<li>Malaysian</li>
<li>Polish</li>
<li>Portugese</li>
<li>Russian</li>
<li>Spanish</li>
<li>Thai</li>
<li>Turkish</li>
</ul>
<figure>
<img src="/images/cant-eat-that/translation-iphone.jpg" />
</figure>
<p>If you have an iOS device please do have a play with the app - both the app and the French language pack are free to download.</p>
<p>Likewise if you yourself have an allergy or have any friends or family who have allergies please do let them know about it.</p>
<p>I will write about my experiences building an iOS app and learning Swift in a future post.</p>
<p><a href="https://itunes.apple.com/us/app/cant-eat-that-food-allergy/id1114910072?mt=8&amp;at=1001lqtb&amp;ct=alexbilbiecom"><img src="/images/cant-eat-that/AppStore.svg" /></a></p>
<p><a href="http://alexbilbie.com/2016/10/cant-eat-that/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Starting a Jenkins multi-branch pipeline build from a Bitbucket commithttp://alexbilbie.com/2016/09/jenkins-multibranch-pipeline-build-bitbucket-commitWed, 28 Sep 2016 00:00:00 +0000Alex Bilbie
<p>After some experimentation I’ve finally worked out how to start a Jenkins multi-pipeline build via a notification from Bitbucket when someone pushes a commit.</p>
<p>The first step is to disable CSRF protection (I know…I know…but it’s necessary to allow remote access). You can do this by selecting <em>Manage Jenkins</em>, <em>Configure Global Security</em> then unchecking the <em>Prevent Cross Site Request Forgery exploits</em> option.</p>
<p>Next step, navigate into your job from the main page and select <em>Branch Indexing</em> from the menu on the left. From this page right click on the link that says <em>Run Now</em>, copy the link address and paste it into a text editor.</p>
<p>Now go back to the Jenkins root menu and select <em>People</em>, then choose your user (or preferably a dedicated Jenkins user), choose <em>Configure</em>, and then reveal the API token. Copy it and head back to your text editor.</p>
<p>Assuming the branch indexing run now URL is <code class="highlighter-rouge">https://jenkins.example.com/job/my-project/build?delay=0</code>, the Jenkins user is <code class="highlighter-rouge">jenkins</code> and the API token is <code class="highlighter-rouge">RdFrCiEwgs9boUsJVHoi</code> modify the URL so it looks like this:</p>
<p><code class="highlighter-rouge">https://jenkins:RdFrCiEwgs9boUsJVHoi@jenkins.example.com/job/my-project/build</code></p>
<p>Next go into the settings of your Bitbucket and create a new webhook, paste in the modified link and save the form.</p>
<p>Commit something and you should see that a moment later Jenkins will run a branch index on the job and then run the build for the branch you committed to.</p>
<p>Multi-branch pipelines are a very new feature to Jenkins 2.0 and are still very part-baked in my opinion. As I get more proficient I will write a tutorial because whilst frustrating to get setup and going they’re a huge time saver.</p>
<p><a href="http://alexbilbie.com/2016/09/jenkins-multibranch-pipeline-build-bitbucket-commit/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Updated: a guide to OAuth 2.0 grantshttp://alexbilbie.com/2016/07/updated-grants-guideFri, 29 Jul 2016 00:00:00 +0000Alex Bilbie
<p>One of the most popular articles on this site is my guide to OAuth 2.0 grants.</p>
<p>I’ve spent some time updating it (I first wrote it in 2013).</p>
<p><a href="http://alexbilbie.com/guide-to-oauth-2-grants/">Check out the updated article here →</a></p>
<p><a href="http://alexbilbie.com/2016/07/updated-grants-guide/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Laravel Passport and league/oauth2-serverhttp://alexbilbie.com/2016/07/laravel-passportThu, 28 Jul 2016 00:00:00 +0000Alex Bilbie
<p>Taylor Otwell, the creator of the Laravel framework, has announced a new Laravel project - Laravel Passport - which uses my <a href="https://github.com/thephpleague/oauth2-server"><code class="highlighter-rouge">league/oauth2-server</code></a> project to “build an OAuth 2.0 backed API server in five minutes”.</p>
<p>This will be the second <a href="http://thephpleague.com">League of Extraordinary Packages</a> project that has native Laravel support; the first being the amazing <a href="http://flysystem.thephpleague.com">Flysystem</a> by Frank de Jonge which power’s <a href="https://laravel.com/docs/5.2/filesystem">Laravel’s Filesystem APIs</a>.</p>
<p>I will hopefully have a tutorial available shortly demonstrating how to use Passport once I’ve got my hands on the code.</p>
<p><a href="http://alexbilbie.com/2016/07/laravel-passport/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Amazon Web Services Developer Associate Certificationhttp://alexbilbie.com/2016/04/aws-developer-associate-certificationSat, 23 Apr 2016 00:00:00 +0000Alex Bilbie
<figure>
<img src="/images/aws-cert.png" title="My AWS certification certificate" />
</figure>
<p>Yesterday I took my Amazon Web Services Developer Associate certification exam and I’m very happy to have passed with 92%.</p>
<p>I’ve been using AWS services in production for over 18 months now and I’ve been wanting to validate my skills and extend my knowledge for a while by studying for one of the AWS certification exams.</p>
<p>In January <a href="http://udemy.com">udemy.com</a> had a flash sale so I picked up a few of the <a href="https://www.udemy.com/user/ryankroonenburg/">courses by Ryan Kroonenburg</a> and I’ve been watching them on and off since then. After booking my exam in February I started to really knuckle down on the revision. I also attended this past week a DynamoDB fundamentals session at the <a href="https://awsloft.london">AWS London Loft</a> and added to my revision notes by reading all of the relevant AWS service FAQs.</p>
<p>The 80 minute exam has 55 multiple-choice questions covering IAM, EC2, S3, Elastic Beanstalk, DynamoDB, SWF, SNS and SQS. The questions are either testing you on your general knowledge of AWS services or are asking you to pick the best option in a given scenario.</p>
<p>My exam featured lots of questions about S3 and only two on DynamoDB (which surprised me because I’d heard this particular exam is heavy on the DynamoDB questions). I had three questions about ELB and there were three questions on the AWS SDKs. There was also a really confusingly worded question about IAM SAML federation which required me to choose two options from five very similar options. Amusingly there were a few questions from the <a href="http://awstrainingandcertification.s3.amazonaws.com/production/AWS_certified_developer_associate_examsample.pdf">example questions</a> on the AWS Certification website that I recognised too. I highly recommend reading the service FAQs as there were a few questions asking questions about limitations of services in specific regions.</p>
<p>All in all I feel like it was a valuable experience; I know many more of the AWS services better from the additional studying - I certainly wouldn’t have been able to answer many of the questions just on my practical knowledge. Having not taken any sort of exam in over five years either it’s opened my mind to potentially studying for additional professional accreditation in the future, not necessarily for the right to call myself a fancy title or to put letters after my name but to really focus in on learning and understanding a tool or a service at a greater depth than is absorbed through general day-to-day practical usage.</p>
<p><a href="http://alexbilbie.com/2016/04/aws-developer-associate-certification/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
OAuth 2.0 Device Flow Granthttp://alexbilbie.com/2016/04/oauth-2-device-flow-grantTue, 19 Apr 2016 08:35:00 +0000Alex Bilbie
<p>When signing into apps and services on devices such as a Playstation or an Apple TV it can be immensely frustrating experience. Generally you will ordeal something similar to one of the following scenarios:</p>
<ol>
<li>The utterly terrible experience whereby you don’t have anything other than an onscreen keyboard and whatever pointing device/controller to enter your username and painfully complex 50 character password.</li>
<li>A slightly less terrible experience whereby you can pair a bluetooth keyboard to enter your username and that crazy long password but you’re balancing the keyboard on your knees whilst trying to copy the password out of 1password on your iPhone.</li>
</ol>
<p>Of course if you use the same 8 character password everywhere then it’s less of an issue but you can understand my predicament… ^_^</p>
<p>There are some apps however - such as Youtube for Apple TV - that have a much better end user experience.</p>
<p>When you sign into the YouTube app you’re presented with this screen:</p>
<figure>
<img src="/images/device-flow/youtube-apple-tv.png" title="Youtube for Apple TV sign-in screen with text asking the user to go to http://youtube.com/activate and enter a random code" />
</figure>
<p>At the URL displayed on screen you see this (after signing into your Google account):</p>
<figure>
<img src="/images/device-flow/youtube-1.png" title="Connect a device screen asking the user to enter the code from the Apple TV" />
</figure>
<p>Having entered the code presented on the TV screen a standard OAuth authorisation dialog is shown:</p>
<figure>
<img src="/images/device-flow/youtube-2.png" title="Youtube for Apple TV OAuth permissions authorization screen" />
</figure>
<figure>
<img src="/images/device-flow/youtube-3.png" title="Return to your device to continue message" />
</figure>
<p>A few seconds after click Allow the Youtube app had refreshed to show my account information.</p>
<p>Awesome!</p>
<p>This lovely UX features an implementation of the still very much in draft phase (at time of writing) <a href="https://tools.ietf.org/html/draft-ietf-oauth-device-flow-01">OAuth 2.0 Device Flow Grant</a>.</p>
<h2 id="how-it-works">How it works</h2>
<p>First an OAuth client (for example the Youtube app) makes a request to the authorization server:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>POST /token HTTP/1.1
Host: authorization-server.com
Content-Type: application/x-www-form-urlencoded
response_type=device_code
&amp;client_id=s6BhdRkqt3
</code></pre></div></div>
<p>The authorization server then responds with a JSON payload:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"verification_uri": "https://authorization-server.com/authorize",
"user_code": "94248",
"device_code": "74tq5miHKB",
"interval": 5
}
</code></pre></div></div>
<p>The <code class="highlighter-rouge">verification_uri</code> is the URL that the user should navigate to on another device.</p>
<p>The <code class="highlighter-rouge">user_code</code> is the code that the user should enter once they’ve authenticated with the authorization server.</p>
<p>Meanwhile the client should attempt to acquire an access token every few seconds (at a rate specified by <code class="highlighter-rouge">interval</code>) by POSTing to the access token endpoint on the authorization server:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>POST /token HTTP/1.1
Host: authorization-server.com
Content-Type: application/x-www-form-urlencoded
grant_type=device_code
&amp;client_id=s6BhdRkqt3
&amp;code=74tq5miHKB
</code></pre></div></div>
<p>The value of <code class="highlighter-rouge">code</code> should be the <code class="highlighter-rouge">device_code</code> from the JSON response in the previous request.</p>
<p>The client should continue to request an access token repeatedly until the end-user grants or denies the request, or the verification code expires.</p>
<p>If the client is polling too frequently it will receive an error from the authorisation server:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"error":"slow_down"
}
</code></pre></div></div>
<p>If the user hasn’t yet authorised the client the error will be:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"error":"authorization_pending"
}
</code></pre></div></div>
<p>If the user authorises the client an access token will be returned:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "2YotnFZFEjr1zCsicMWpAA",
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA"
}
</code></pre></div></div>
<p>If the user denies the client an error will be returned:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"error":"access_denied"
}
</code></pre></div></div>
<h2 id="conclusion">Conclusion</h2>
<p>The device flow grant provides a really pleasant experience for devices that do not support an easy data-entry method. In addition it is really simple for developers to integrate with.</p>
<p><a href="http://alexbilbie.com/2016/04/oauth-2-device-flow-grant/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
league/oauth2-server version 5.0 is out!http://alexbilbie.com/2016/04/league-oauth2-server-version-5-is-outMon, 18 Apr 2016 08:00:00 +0000Alex Bilbie
<p>Coming just over a year since the last major release, version 5.0 is a complete code rewrite with many improvements:</p>
<ul>
<li>PSR-7 support</li>
<li>Improved OAuth 2 specification support (public clients, implicit grant)</li>
<li>JWT support by default</li>
<li>Significantly simplified interfaces make getting started faster and easier</li>
<li>Rewritten documentation and examples</li>
</ul>
<p>It’s simpler than ever to created an authorisation server; here is an example using the Slim Framework with support for the resource owner password credentials grant:</p>
<script src="https://gist.github.com/alexbilbie/1f19a3cc5dbfc08fc822ad00490cd78c.js"></script>
<p>Your API endpoints can easily be secured using the resource server PSR-7 middleware:</p>
<script src="https://gist.github.com/alexbilbie/face0c52f60c621edd301c2be5c0f1a8.js"></script>
<p>To get started just run:</p>
<p><code class="highlighter-rouge">composer require league/oauth2-server</code></p>
<p>Check out the new documentation here - <a href="https://oauth2.thephpleague.com">https://oauth2.thephpleague.com</a>. If you have any questions please feel free to <a href="https://github.com/thephpleague/oauth2-server/issues/new">open a Github issue</a>.</p>
<p>I’d like to thank <a href="https://github.com/thephpleague/oauth2-server/graphs/contributors?from=2015-08-02&amp;to=2016-04-18&amp;type=c">everyone who has contributed</a> to this release, especially <a href="https://github.com/juliangut">Julián Gutiérrez</a> and <a href="https://github.com/frederikbosch">Frederik Bosch</a>.</p>
<p><a href="http://alexbilbie.com/2016/04/league-oauth2-server-version-5-is-out/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Annoucing league/oauth2-server 5.0.0 RC2http://alexbilbie.com/2016/04/league-oauth2-server-v5rc2Sun, 10 Apr 2016 00:00:00 +0000Alex Bilbie
<p><strong>league/oauth2-server</strong> <a href="https://github.com/thephpleague/oauth2-server/releases/tag/5.0.0-RC2">version 5.0.0 release candidate 2</a> has just been tagged.</p>
<p>Please feel free to ask questions on the <a href="https://github.com/thephpleague/oauth2-server/issues">Github issues page</a> and propose changes with a pull request.</p>
<p><a href="http://alexbilbie.com/2016/04/league-oauth2-server-v5rc2/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Annoucing league/oauth2-server 5.0 RC1http://alexbilbie.com/2016/03/league-oauth2-server-v5rcThu, 24 Mar 2016 20:00:00 +0000Alex Bilbie
<p><strong>league/oauth2-server</strong> <a href="https://github.com/thephpleague/oauth2-server/releases/tag/5.0.0-RC1">version 5.0.0 release candidate 1</a> has just been tagged!</p>
<p>Coming just over a year since the last major release, version 5.0 is a complete code rewrite with significantly simplified interfaces, improved OAuth 2 specification support and JWT support out of the box.</p>
<p>I’ve rewritten all of the documentation, viewable here - <a href="http://oauth2.thephpleague.com">http://oauth2.thephpleague.com</a>.</p>
<p>I will announce future release candidates and the final release here on my blog and through <a href="https://twitter.com/thephpleague">The PHP League twitter account</a>.</p>
<p>Please feel free to ask questions on the <a href="https://github.com/thephpleague/oauth2-server/issues">Github issues page</a> and propose changes with a pull request.</p>
<p><a href="http://alexbilbie.com/2016/03/league-oauth2-server-v5rc/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Programming a DS9208-1D barcode scannerhttp://alexbilbie.com/2016/01/programming-a-barcode-scannerThu, 07 Jan 2016 18:00:00 +0000Alex Bilbie
<p>I had 10 minutes of fun today learning how to program a barcode scanner. Specifically a “DS9208-1D” which is an omni-directional scanner that is available under numerous brands (we’ve got a Symbol branded version but Moterola also sell the same device).</p>
<p>Out of the box this scanner doesn’t send a carriage return after sending the scanned data. After a seemingly unnecessary amount of Googling I finally found <a href="https://atgsupportcentral.motorolasolutions.com/content/emb/docs/manuals/16262603b.pdf">a manual</a> which explains how to do this.</p>
<p>You’ll need to print the following pages from <a href="https://atgsupportcentral.motorolasolutions.com/content/emb/docs/manuals/16262603b.pdf">the manual</a>:</p>
<ul>
<li>Page 71 “Prefix/Suffix Values”</li>
<li>Page 72 “Scan Data Transmission Format”</li>
<li>Pages 245 + 246 “Numeric Bar Codes”</li>
</ul>
<p>Or just print this blog post out.</p>
<p>Start off with page 71 and scan the barcode <code class="highlighter-rouge">Scan Suffix 1</code> (data value <code class="highlighter-rouge">06h</code>). This will put the scanner into a mode which allows for scanning a four digit code which represents a character (or combination of characters).
Appendix E of the manual lists all of these codes and you’ll find that <code class="highlighter-rouge">6058</code> represents “Enter”.</p>
<p><img src="/images/barcode/barcode-scan-suffix-1.png" alt="/images/barcode/barcode-scan-suffix-1.png" /></p>
<p>Next scan each of the barcodes that represent <code class="highlighter-rouge">6</code>, <code class="highlighter-rouge">0</code>, <code class="highlighter-rouge">5</code> and <code class="highlighter-rouge">8</code>. You’ll hear a confirmation beep that doesn’t sound like a normal scan beep.</p>
<p><img src="/images/barcode/6.png" alt="/images/barcode/barcode-scan-suffix-1.png" />
<img src="/images/barcode/0.png" alt="/images/barcode/barcode-scan-suffix-1.png" />
<img src="/images/barcode/5.png" alt="/images/barcode/barcode-scan-suffix-1.png" />
<img src="/images/barcode/8.png" alt="/images/barcode/barcode-scan-suffix-1.png" /></p>
<p>Finally from page 72 scan the barcode entitled <code class="highlighter-rouge">&lt;DATA&gt;&lt;SUFFIX 1&gt;</code> (data value <code class="highlighter-rouge">01h</code>).</p>
<p><img src="/images/barcode/data-suffix-1.png" alt="/images/barcode/barcode-scan-suffix-1.png" /></p>
<p>Open a text editor and do a quick test scan of any barcode and you should see the cursor move to the next line after scanning.</p>
<p><a href="http://alexbilbie.com/2016/01/programming-a-barcode-scanner/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
2016 Comethhttp://alexbilbie.com/2016/01/2016-updateSun, 03 Jan 2016 22:22:00 +0000Alex Bilbie
<p>It’s been a very long time since I’ve posted here; 2015 turned out to be an insanely busy year.</p>
<p><a href="http://popsa.co/">Popsa</a>, the app I’ve been involved with since late 2014 launched in June. Working on Popsa has been great fun; I’ve gotten to work on some really interesting problems and learnt a lot about the world of printing and app development. I’ve also had the opportunity to build some cool <abbr title="Internet of Things">IoT</abbr> tech with Raspberry PIs and learn an arcane printer programming language (ZPL).</p>
<figure>
<img src="/images/snapcam.jpg" title="Popsa iOS Preview" />
</figure>
<p>My day job has pretty much taken up all of my time over the past year which in many ways has been incredible for learning and I’m incredibly fortunate to be in a position to have worked on a platform to support an app used by an audience many times larger than I’ve ever had before.</p>
<p>This year I’m setting some resolutions to try and ensure that I achieve some of the things I’ve wanted to do for a while:</p>
<ul>
<li>Blog more; 2015 featured just 3 posts compared to over sixty in 2013.</li>
<li>Start a podcast</li>
<li>Release v5 of <a href="https://github.com/thephpleague/oauth2-server">league/oauth2-server</a></li>
<li>Release <a href="https://leanpub.com/oauthello-a-book-about-oauth/">my OAuth book</a></li>
<li>Regularly attend some London tech meetups</li>
<li>Submit a talk and speak at at least one major conference this year</li>
<li>Read at least 20 books; half of which will be fiction</li>
<li>Release an open source project in another language aside from PHP</li>
</ul>
<p>I’ve also spent a bit of time today tidying up this blog and adding links in the sidebar to groups of posts that are popular (such as my <a href="/tag/oauth">OAuth articles</a>).</p>
<p><a href="http://alexbilbie.com/2016/01/2016-update/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Setup Jenkins and test a PHP projecthttp://alexbilbie.com/2015/04/setting-up-jenkinsSun, 19 Apr 2015 09:10:00 +0000Alex Bilbie
<p>After a chat with some other developers on Twitter the other day I offered to write a tutorial on how to setup Jenkins from scratch and create a job to test a PHP project.</p>
<p>For this tutorial I’m going to use a Digital Ocean droplet (get $10 free credit with <a href="https://www.digitalocean.com/?refcode=3d4888f57e2e">this link</a>) but you can use a server from anywhere.</p>
<p>Once I’ve installed and setup Jenkins I’m going to create a job to test <a href="https://github.com/alexbilbie/Proton">my Proton framework</a>.</p>
<h2 id="setup-the-server">Setup the server</h2>
<p>First create a new Ubuntu server - I’ve used a $5/month 512mb box but if you’re going to use Jenkins for multiple production projects I recommend you use a server with at least 2gb of RAM to keep your builds speedy.</p>
<p>Once the server has powered up then SSH in. We’re going to need a few tools installed:</p>
<noscript><pre># Add the Jenkins source
wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
echo &#39;deb http://pkg.jenkins-ci.org/debian binary/&#39; &gt;&gt; /etc/apt/sources.list
# We&#39;re going to install Nginx too
echo &quot;deb http://ppa.launchpad.net/nginx/stable/ubuntu trusty main&quot; &gt;&gt; /etc/apt/sources.list.d/nginx-stable-trusty.list
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C300EE8C
# Finally we want PHP too
echo &quot;deb http://ppa.launchpad.net/ondrej/php5-5.6/ubuntu trusty main&quot; &gt;&gt; /etc/apt/sources.list.d/php5-5.6-trusty.list`
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F4FCBB07
# Update the repositories
apt-get update
# Install Jenkins, Nginx, Git, PHP5 (latest) and Xdebug (for code coverage)
apt-get install jenkins nginx git php5-fpm php5-xdebug</pre></noscript>
<script src="https://gist.github.com/alexbilbie/17f0bcf9f33c48164972.js"> </script>
<p>Jenkins runs on port <code class="highlighter-rouge">8080</code> by default so we’re going to setup an Nginx proxy which listens on port <code class="highlighter-rouge">80</code> and proxies to Jenkins. We’ll also point a subdomain at it.</p>
<p>With my DNS provider I setup an DNS A record for <code class="highlighter-rouge">jenkins.alexbilbie.com</code> pointing at the IP address of my server.</p>
<p>Next I updated <code class="highlighter-rouge">/etc/nginx/sites-enabled/default</code> with the following setup:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
listen 80;
server_name jenkins.alexbilbie.com;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 150;
proxy_send_timeout 100;
proxy_read_timeout 100;
proxy_buffers 4 32k;
client_max_body_size 8m;
client_body_buffer_size 128k;
}
}
</code></pre></div></div>
<p>Now to bounce Nginx <code class="highlighter-rouge">service nginx restart</code> and start Jenkins <code class="highlighter-rouge">service jenkins start</code>.</p>
<p>I can now open up Jenkins in my browser:</p>
<figure>
![/images/jenkins-install/1.png](/images/jenkins-install/1.png)
</figure>
<h2 id="security">Security</h2>
<p>First thing to do is secure Jenkins. When you’re working in a team by far the easiest way is to use Github to secure your Jenkins installations using OAuth.</p>
<p>To enable Github security up we need to install a few plugins, on the left hand side click on <strong>Manage Jenkins</strong> then <strong>Manage Plugins</strong>.</p>
<p>Click on the Available tab then select the following plugins (you can use the search field to narrow down the list):</p>
<ul>
<li>Github OAuth Plugin</li>
<li>Github Plugin</li>
</ul>
<p>Click <strong>Download now and install after restart</strong>. Jenkins will now download the plugins and restart itself.</p>
<p>Whilst Jenkins is doing that head over to Github, go to <strong>Settings</strong> then <strong>Applications</strong>. Click <strong>Register new application</strong>.</p>
<figure>
![/images/jenkins-install/2.png](/images/jenkins-install/2.png)
</figure>
<p>I used the following settings:</p>
<ul>
<li><strong>Application name</strong>: <code class="highlighter-rouge">jenkins.alexbilbie.com</code></li>
<li><strong>Homepage URL</strong>: <code class="highlighter-rouge">http://jenkins.alexbilbie.com</code></li>
<li><strong>Authorization callback URL</strong>: <code class="highlighter-rouge">http://jenkins.alexbilbie.com:8080/securityRealm/finishLogin</code></li>
</ul>
<p>Finally click <strong>Register application</strong>.</p>
<p>Back in Jenkins click on <strong>Manage Jenkins</strong> then <strong>Configure Global Security</strong>. Check the <code class="highlighter-rouge">Enable security</code> checkbox.</p>
<p>Under <strong>Security Realm</strong> click on <strong>Github Authentication Plugin</strong>.</p>
<p>I used the following settings:</p>
<ul>
<li><strong>GitHub Web URI</strong>: <code class="highlighter-rouge">https://github.com</code></li>
<li><strong>GitHub API URI</strong>: <code class="highlighter-rouge">https://api.github.com</code></li>
<li><strong>Client ID</strong>: <em>(the client ID that Github gave you for your application)</em></li>
<li><strong>Client Secret</strong>: <em>(the client secret that Github gave you for your application)</em></li>
</ul>
<p>Under <strong>Authorization</strong> choose <strong>Github Commiter Authorization Strategy</strong>.</p>
<p>Update the following:</p>
<ul>
<li><strong>Admin User Names</strong>: <em>(your Github username)</em></li>
<li>Enable <strong>Grant READ permissions for /github-webhook</strong> (so that Github can ping your Jenkins install)</li>
<li>Click <strong>Save</strong>. You’ll now be sent to Github to sign-in:</li>
</ul>
<figure>
![/images/jenkins-install/3.png](/images/jenkins-install/3.png)
</figure>
<h2 id="install-composer">Install Composer</h2>
<p>We need to install <a href="http://getcomposer.org">Composer</a> so whilst SSH-d into the server run the following (as root):</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>su jenkins
mkdir ~/bin
cd ~/bin
curl -sS https://getcomposer.org/installer | php
mv composer.phar composer
</code></pre></div></div>
<p>By installing Composer as the <code class="highlighter-rouge">jenkins</code> user we can keep it updated easily with Jenkins itself.</p>
<h2 id="create-an-ssh-key-for-jenkins">Create an SSH key for Jenkins</h2>
<p>Jenkins needs an SSH key in order to commit back to Github (if that’s what you want). There are two options here, either create a new Github user or add a deploy key to the repository. For this tutorial I’m going to add a deploy key.</p>
<p>As the Jenkins user run the following - <code class="highlighter-rouge">ssh-keygen -t rsa -C "jenkins"</code>. I opted to not create a password for the key.</p>
<p>Copy the public key (<code class="highlighter-rouge">~/.ssh/id_rsa.pub</code>) to your clipboard and add it as a deploy key in your Github repository:</p>
<figure>
![/images/jenkins-install/4.png](/images/jenkins-install/4.png)
</figure>
<p>Next let Jenkins know about the private key. Click on <strong>Credentials</strong> then <strong>Global credentials (unrestricted)</strong> then <strong>Add Credentials</strong>.</p>
<p>Choose <code class="highlighter-rouge">SSH Username with private key</code>, add a username (I used <code class="highlighter-rouge">jenkins</code>) and add the private key (<code class="highlighter-rouge">~/.ssh/id_rsa</code>). Click <strong>OK</strong>.</p>
<h2 id="add-your-first-job">Add your first job</h2>
<p>Click <strong>New Item</strong>, add <code class="highlighter-rouge">Proton</code> as the project name then choose <code class="highlighter-rouge">Freestyle project</code>.</p>
<p>Setup the project like so (click on the images for a larger view):</p>
<p><a href="/images/jenkins-install/5.png"><figure><img src="/images/jenkins-install/5.png" alt="/images/jenkins-install/5.png" /></figure></a></p>
<p><a href="/images/jenkins-install/6.png"><figure><img src="/images/jenkins-install/6.png" alt="/images/jenkins-install/6.png" /></figure></a></p>
<p>Click <strong>Save</strong>.</p>
<p>In the project screen you can now click <strong>Build Now</strong>. If you’ve copied my config as above you can see in the output for the project that Jenkins will do the following:</p>
<ol>
<li>Set up a new project workspace</li>
<li>Clone the repository</li>
<li>Run <code class="highlighter-rouge">/var/lib/jenkins/bin/composer up</code></li>
<li>Run <code class="highlighter-rouge">vendor/bin/phpunit</code></li>
<li>Write the message <code class="highlighter-rouge">Finished: SUCCESS</code></li>
</ol>
<p>To get Github to automatically trigger a build when a change is pushed go into the repository <strong>Settings</strong>, then <strong>Webhooks and Services</strong>, choose then <code class="highlighter-rouge">Jenkins (Github plugin)</code> service.</p>
<p>I set the Jenkins hook URL to <code class="highlighter-rouge">https://jenkins.alexbilbie.com/github-webhook/</code>.</p>
<p>Now when I push a commit to the develop branch Github will ping Jenkins and automatically trigger a build.</p>
<h2 id="next-steps">Next steps</h2>
<p>Now that you’ve got a successful build you can make use of some Jenkins plugins to make Jenkins more useful.</p>
<ul>
<li>If you want to visualise PHPUnit code coverage then the <a href="http://wiki.jenkins-ci.org/display/JENKINS/Clover+PHP+Plugin">Clover PHP</a> will ingest a <code class="highlighter-rouge">clover.xml</code> file created by PHPUnit and create a graph on the job home page. You can also use it to ensure a minimum amount of coverage or the project will be marked as unstable or even fail the build.</li>
<li>Other plugins that create graphs and logs from PHPUnit and other QA tools include:</li>
<li><a href="http://wiki.jenkins-ci.org/display/JENKINS/Checkstyle+Plugin">Checkstyle</a> (for processing PHP_CodeSniffer logfiles in Checkstyle format)</li>
<li><a href="http://wiki.jenkins-ci.org/display/JENKINS/Crap4J+Plugin">Crap4J</a> (for processing PHPUnit’s Crap4J XML logfile)</li>
<li><a href="http://wiki.jenkins-ci.org/display/JENKINS/DRY+Plugin">DRY</a> (for processing phpcpd logfiles in PMD-CPD format)</li>
<li><a href="http://wiki.jenkins-ci.org/display/JENKINS/JDepend+Plugin">JDepend</a> (for processing PHP_Depend logfiles in JDepend format)</li>
<li><a href="http://wiki.jenkins-ci.org/display/JENKINS/Plot+Plugin">Plot</a> (for processing phploc CSV output)</li>
<li><a href="http://wiki.jenkins-ci.org/display/JENKINS/PMD+Plugin">PMD</a> (for processing PHPMD logfiles in PMD format)</li>
<li><a href="http://wiki.jenkins-ci.org/display/JENKINS/xUnit+Plugin">xUnit</a> (for processing PHPUnit’s JUnit XML logfile)</li>
<li>The <a href="http://wiki.jenkins-ci.org/display/JENKINS/HTML+Publisher+Plugin">HTML Publisher</a> allows you to keep HTML reports generated by your tests and link to them from a job page.</li>
<li>The <a href="http://wiki.jenkins-ci.org/display/JENKINS/AnsiColor+Plugin">AnsiColor</a> plugin adds support for ANSI escape sequences, including color, to the build output.</li>
<li>You can report build statuses back to <a href="http://wiki.jenkins-ci.org/display/JENKINS/HipChat+Plugin">Hipchat</a>, <a href="https://wiki.jenkins-ci.org/display/JENKINS/Slack+Plugin">Slack</a> and <a href="https://wiki.jenkins-ci.org/display/JENKINS/IRC+Plugin">IRC</a> with respective plugins.</li>
<li><a href="http://wiki.hudson-ci.org/display/HUDSON/Post+build+task">This plugin</a> allows you to run tasks like shell scripts after builds finish - I use it to stop Docker containers that I’ve used in my builds.</li>
<li>The <a href="https://wiki.jenkins-ci.org/display/JENKINS/S3+Plugin">S3 publisher plugin</a> will create an archive from a successful build and push it to Jenkins (which you could then automatically pull on to you servers to deploy new code).</li>
<li>One of my favourite plugins is the <a href="http://wiki.jenkins-ci.org/display/JENKINS/Build+Monitor+Plugin">Big Monitor plugin</a> which I have running on a TV (projected from a spare Mac Mini using a Chromecast). This is opposite my desk in the office and I can see all of my jobs and their current status (which of course are always green…).</li>
</ul>
<p>Jenkins can execute shell scripts as part of build jobs so you can use this to perform pretty much any task you want, from starting Docker containers, keeping Composer up to date (I have a job dedicated to this that runs once a week), API testing, or just about anything else that you manually do on the command line.</p>
<p>There are plugins to automatically build pull requests and you can set up upstream and downstream jobs that are run before and after other jobs.</p>
<p>I use these extensively so when I push to the <code class="highlighter-rouge">develop</code> branch of one of my projects I have certain tests run which when they pass automatically merge <code class="highlighter-rouge">develop</code> into <code class="highlighter-rouge">master</code>. I then have another job which listens to <code class="highlighter-rouge">master</code> which then has other tests run and packages up the code into an archive on S3 on success. I then have a final job that is triggered to run an Ansible task to deploy the code on S3 onto all my servers.</p>
<p>One word of advice, once you’ve got a working Jenkins setup try to keep it that way; I’ve been burnt numerous times by plugin updates that have broken or significantly slowed down my builds. If that happens you can easily downgrade a plugin inside the plugin manager.</p>
<p>Hopefully you’ve learnt from this tutorial just how easy it is to get setup and running with Jenkins and I’m sure like me in time you’ll find it to be an invaluable part of your development stack.</p>
<p><a href="http://alexbilbie.com/2015/04/setting-up-jenkins/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
OAuth Open Redirector Attackhttp://alexbilbie.com/2015/04/oauth-open-redirector-attackThu, 16 Apr 2015 10:00:00 +0000Alex Bilbie
<p>I’m a little late to writing about this but as reported by Antonio Sanso on <a href="http://intothesymmetry.blogspot.ch/2015/04/open-redirect-in-rfc6749-aka-oauth-20.html">his blog</a> he found yet another flaw in well known identity providers’ OAuth 2.0 implementations.</p>
<p>The specifics of the attack are the same as the last flaw that was found with Facebook’s implementation that <a href="/2013/02/facebooks-oauth-problem/">I wrote about a while ago</a>; namely that vendors aren’t being strict about whitelisting redirect URIs for the authorization (and likely implicit) grant routes.</p>
<p>Antonio discovered that if you registered a client with one redirect URI but crafted a OAuth authorizw URL with a different <code class="highlighter-rouge">redirect_uri</code> parameter then vendors were sending the user to the invalid (and non-whitelisted) redirect URI.</p>
<p>In these examples <code class="highlighter-rouge">www.attacker.com</code> is the non-whitelisted redirect URI:</p>
<ul>
<li>Facebook: <code class="highlighter-rouge">https://graph.facebook.com/oauth/authorize?response_type=code&amp;client_id=1621835668046481&amp;redirect_uri=http://www.attacker.com/&amp;scope=WRONG_SCOPE</code></li>
<li>Github: <code class="highlighter-rouge">https://github.com/login/oauth/authorize?response_type=code&amp;redirect_uri=http://attacker.com2&amp;client_id=e2ddb90328315c367b11</code></li>
<li>Microsoft: <code class="highlighter-rouge">https://login.live.com/oauth20_authorize.srf?response_type=code&amp;redirect_uri=http://attacker.com&amp;client_id=000000004C12822C</code></li>
<li>Moves: <code class="highlighter-rouge">https://api.moves-app.com/oauth/v1/authorize?response_type=code&amp;client_id=bc88FitX1298KPj2WS259BBMa9_KCfL3&amp;redirect_uri=data%3Atext%2Fhtml%2Ca&amp;state=&lt;script&gt;alert('hi')&lt;/script&gt;</code></li>
</ul>
<p>In his testing he discovered that Google’s implementation returned a <code class="highlighter-rouge">HTTP 400</code> instead of redirect the user because it is strictly validating the redirect URI against the client.</p>
<p>The <code class="highlighter-rouge">league/oauth2-server</code> PHP library I wrote is not vulnerable to this attack because very early on in the request I validate the <code class="highlighter-rouge">redirect_uri</code> along with the client credentials - <a href="https://github.com/thephpleague/oauth2-server/blob/master/src/Grant/AuthCodeGrant.php#L82">https://github.com/thephpleague/oauth2-server/blob/master/src/Grant/AuthCodeGrant.php#L82</a>.</p>
<p><a href="http://alexbilbie.com/2015/04/oauth-open-redirector-attack/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
An inspired journey into microservices architecturehttp://alexbilbie.com/2015/03/an-inspired-journey-into-microservices-architectureSun, 15 Mar 2015 10:11:00 +0000Alex Bilbie
<p>Sometime this week I came across a series of blog posts by the taxi company Hailo about how their architecture has changed over time from a simple PHP/Java API to a global infrastructure with over 150 services powering their consumer and operational apps.</p>
<p>The three blog posts can be found here:</p>
<ul>
<li><a href="https://sudo.hailoapp.com/services/2015/03/09/journey-into-a-microservice-world-part-1/">Part one</a></li>
<li><a href="https://sudo.hailoapp.com/services/2015/03/09/journey-into-a-microservice-world-part-2/">Part two</a></li>
<li><a href="https://sudo.hailoapp.com/services/2015/03/09/journey-into-a-microservice-world-part-3/">Part three</a></li>
</ul>
<p>I love <a href="https://sudo.hailoapp.com/web/2014/12/08/webapps-as-microservices/">this blog post</a> too.</p>
<p>I’ve been very slowly orientating my stack at work (more on that soon) to be made up of a number of discrete services, but since reading the posts above I’ve become a little bit obsessed with understanding at an even deeper level how to properly build and orchestrate a whole raft of services to power our mobile apps.</p>
<p>At this point I’ve come to two conclusions. First what I’ve made works really well so far and I don’t want to disrupt that unnecessarily. Also any further splitting out of application functions into individual services needs to be done at a rate which is manageable for the resources we have available at the time and also carefully because we’re about to launch our newest app into production.</p>
<p>My second conclusion is I really want and need to add another language to my toolbelt. I’ve worked with PHP for years now; I’m fast and effective with it but my frustration with the direction of the language <em>vs</em> what I want from it (namely strict scalar type hints and types), it’s lacklustre ability to run long running processes and poor concurrency support mean it’s starting to work against my needs. I’ve been playing on and off with other languages and Go and has really captured my imagination so my challenge now is to find the time to learn as much as I can about Go and if I’m confident with this new approach then appropriately introduce it into our stack.</p>
<p><a href="http://alexbilbie.com/2015/03/an-inspired-journey-into-microservices-architecture/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
OAuth 2 and API Security discussion on Full Stack Radio podcasthttp://alexbilbie.com/2014/12/full-stack-radioMon, 15 Dec 2014 18:27:00 +0000Alex Bilbie
<p>Last week I was invited by <a href="https://twitter.com/adamwathan">Adam Wathan</a> to appear on his Full Stack Radio podcast. We talked in depth about the OAuth 2 specification including all of the major grant types (when is best to use them, and some of the pitfalls), and then we talked about API security strategies for one of Adam’s side projects. It was good geeky fun.</p>
<p>You can find the episode here - <a href="http://fullstackradio.com/episodes/4/">http://fullstackradio.com/episodes/4/</a>.</p>
<p><a href="http://alexbilbie.com/2014/12/full-stack-radio/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Version 4 of league/oauth2-server is out!http://alexbilbie.com/2014/11/league-oauth2-server-version-4Sat, 08 Nov 2014 18:06:00 +0000Alex Bilbie
<p>After almost a year in development I’ve just tagged version 4.0.0 of <a href="https://github.com/thephpleague/oauth2-server">league/oauth2-server</a>.</p>
<p>Back in the summer <a href="/2014/08/open-source-guilt/">I wrote about some of the problems I’ve faced</a> during its development, but I’ve finally got there.</p>
<p>So what’s new about v4?</p>
<p><strong>First of all it’s a complete rewrite from scratch</strong>. Theres some old saying about never rewriting software, but this is a component that to be used in a larger system, and good software practise involves <a href="http://martinfowler.com/bliki/SacrificialArchitecture.html">sacrificing and upgrading modular components</a> to improve the overall stack.</p>
<p>At the code level I’ve updated everything to pass around objects which are much easier to test and validate than arbitrary key value arrays. This will also mean that code documentation generated with phpDocumentor or ApiGen will be much more useful.</p>
<p>Because almost all of the underlying objects have interfaces you can swap in your own key generator and create your own tokens as well as creating your own grant types much more easily than before.</p>
<p>In addition I’ve made use of Symfony’s Request class from <code class="highlighter-rouge">symfony/http-foundation</code> (which just about every framework uses) to parse and validate server requests which saves developers having to manually pass through request variables which was required in older versions.</p>
<p><a href="http://oauth2.thephpleague.com/authorization-server/events/">The server now emits events</a> which can be used to further integrate the library into your own application. For example the <code class="highlighter-rouge">session.owner</code> event is fired when a session has been allocated an owner - you might want to listen to this event to automatically add extra scopes (permissions) if the owner is an administrator. All of the events stuff is powered by the lovely <code class="highlighter-rouge">league/events</code> by Frank de Jonge.</p>
<p>All the code has been tested on the latest versions of PHP and HHVM too.</p>
<p>Finally, and probably most importantly there is some extensive documentation which can be found here - <a href="http://oauth2.thephpleague.com">http://oauth2.thephpleague.com</a>.</p>
<p>I’d like to thank everyone who has contributed to v4’s development - especially <a href="https://twitter.com/lucadegasperi">Luca Degasperi</a> and <a href="https://twitter.com/jasonclewis">Jason Lewis</a> and all the guys at the <a href="http://thephpleague.com">PHP League of Extraordinary Packages</a> for their support, nagging and bug fixes.</p>
<p><a href="http://alexbilbie.com/2014/11/league-oauth2-server-version-4/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Speed up Internet access in Vagrant boxeshttp://alexbilbie.com/2014/11/vagrant-dnsWed, 05 Nov 2014 15:33:00 +0000Alex Bilbie
<p>This afternoon I’ve been playing with the Facebook API in a Vagrant box but requests to the API were immensely slow.</p>
<p>The following request would take <code class="highlighter-rouge">5.5221911907196s</code> inside Vagrant:</p>
<noscript><pre>&lt;?php
$t = microtime(true);
file_get_contents(&#39;https://graph.facebook.com/v2.2/me?access_token={{access token}}&#39;);
var_dump(microtime(true) - $t);</pre></noscript>
<script src="https://gist.github.com/alexbilbie/7f35b1e6abd0a14c85fc.js"> </script>
<p>But on my rMBP the same request took just <code class="highlighter-rouge">0.16792297363281s</code>.</p>
<p>After a bit of Googling around I found that you can tell Virtualbox (through the <code class="highlighter-rouge">Vagrantfile</code>) to use the host as the DNS resolver:</p>
<noscript><pre>config.vm.provider &quot;virtualbox&quot; do |v|
v.customize [&quot;modifyvm&quot;, :id, &quot;--natdnshostresolver1&quot;, &quot;on&quot;]
end</pre></noscript>
<script src="https://gist.github.com/alexbilbie/b93793fe5c52b8d652db.js"> </script>
<p>After a quick <code class="highlighter-rouge">vagrant reload</code> the request took just <code class="highlighter-rouge">0.15842008590698s</code></p>
<p><a href="http://alexbilbie.com/2014/11/vagrant-dns/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Responding to reactions towards my job titlehttp://alexbilbie.com/2014/11/responsing-to-reactionsTue, 04 Nov 2014 12:40:00 +0000Alex Bilbie
<p>When people ask what I do for a living I say that I’m a software engineer. Nine times out of ten I will get the following reactions - “I’m not very good with computers” or “oo that sounds hard”.</p>
<p>My comeback to the former is that I quiz them about what that person finds difficult when it comes to computers, and then I explain that they actually know more than they realise and it wouldn’t take them long to adapt to new technology if they were put in that situation. For example discovering common features in a particular set of applications or websites may mean they also work in other applications and websites which means they can approach new things with some added confidence.</p>
<p>I discovered recently that there is actually a term for this joined-up experience: synoptic learning. Synoptic learning is the principle whereby experience, both through comfort and familiarity, with one part of a subject can help increase understanding with other parts because they’re able to create connections to what they already know.</p>
<p>I consider myself a “power user” when it comes to desktop operating systems and smartphones; I’m quick at doing what I want to do and I’m quick to learn and adapt when things change. What irks me though is when applications redefine well-defined UI patterns or keyboard shortcuts so they result in unexpected actions. These slow me down, however I can generally adapt and adopt new muscle memory. But this is unlikely to be the case for non-technical users and can cause confusion, distrust and ultimately the feeling of being patronised by technology. It is important that we help our users to feel comfortable with our software by not breaking the “well understood” and guiding them in a non-patronising way through the unfamiliar.</p>
<p>Regarding the “oo that sounds hard” response I explain that fundamentally I just solve problems with computers. I find that this is usually interests people further and I describe how I tell the computer to evaluate an input and return an output in some form. A few times I’ve found people are actually really interested in how certain aspects of technology work, i.e. curiosities they’ve always had but have never had the opportunity to be explained. Sometimes these conversations have even gone into explaining boolean logic and if/else statements and loops.</p>
<p>In my experience, if you don’t patronise non-technical people when you’re explaining what we do as developers they are actually genuinely interested and have some respect for our craft; especially if they can relate what we’ve said to their own experiences.</p>
<p>Recently I did a guest lecture explaining “life as a software developer” to the 2nd and 3rd year computer science students at the University of Lincoln. A large number of slides were about the communication side of the job. I don’t just sit all day staring at a computer screen; I communicate with my colleagues in the morning standup, on Hipchat, in meetings and over lunch and I communicate with myself through drawing on whiteboards and making todo lists and sketching out ideas.</p>
<p>But most importantly I communicate with those around me outside the workplace: my family and friends. I tell them what I’m up to because it helps build a support structure around me so that they understand some of the challenges I may face which explain why I’m knackered, or why I’m really pumped and fancy going to go to the pub for a pint and celebrating.</p>
<p>Regardless of how I anticipate someone reacting when I’m asked what I do, when I say I’m a software developer (or engineer; I use both words interchangeably) I always say it with pride knowing that through the work I’m doing right now I’m making others happy.</p>
<p><a href="http://alexbilbie.com/2014/11/responsing-to-reactions/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Introducing Protonhttp://alexbilbie.com/2014/10/introducing-protonSat, 04 Oct 2014 17:30:00 +0000Alex Bilbie
<p>The last few big projects I’ve worked on (mostly backend RESTful APIs) have been built with a combination of different packages loaded with Composer instead of building on top of a framework such as Laravel or Symfony.</p>
<p>My go to packages to build the core of each project for a while now have been the following:</p>
<ul>
<li><a href="https://github.com/orno/route">Orno\Route</a> for routing (it’s built on Nikita Popov’s <a href="https://github.com/nikic/FastRoute">FastRoute</a>).</li>
<li><a href="https://github.com/orno/di">Orno\Di</a> for dependency injection.</li>
<li><a href="https://github.com/thephpleague/event">League\Event</a> for dispatching events.</li>
</ul>
<p>For each app I would spend time bootstraping the packages together and then build on that foundation. The bootstrap code isn’t particularly excessive or laborious to put together, but it has been repetitive.</p>
<p>So as I started on another project this week I spend some time finally building a micro “framework” called Proton - <a href="https://github.com/alexbilbie/proton">https://github.com/alexbilbie/proton</a> which binds and exposes the packages above with one reusable component</p>
<p>Here is a simple example of how to use Proton with anonymous functions:</p>
<script src="https://gist.github.com/alexbilbie/2ab3b3c23b025dd70032.js"></script>
<p>And another with controllers:</p>
<script src="https://gist.github.com/alexbilbie/234efa329cd0c8348dc0.js"></script>
<script src="https://gist.github.com/alexbilbie/eb5d6d64f15d3bab47a3.js"></script>
<p>Why did I build yet another micro framework? Why not just use Slim or Silex or some other micro framework?</p>
<p>Principally because I really like the particular packages above that I’ve already mentioned; I know their codebases very well and they’re blazing fast. Also those other frameworks all offer features that I don’t need; I like my code lean and mean and I don’t want unnecessary overhead.</p>
<p>Proton contains <strong>just enough</strong> code to bootstrap those package components together (similarly to how I have done on previous projects), and leaves me to make the fundamental decisions about architecture myself; I’m not constrained in any way. Also the underlying packages are all exposed so I can work with the router, container and event dispatcher individually (as apposed to having to talk to them through a facade on the <code class="highlighter-rouge">Proton\Application</code> object).</p>
<p>Aside from this blog post I don’t plan on publicising Proton particularly; I’ve written it to help myself out and if others find it useful then that’s great too.</p>
<p>This week I also discovered <a href="http://stackphp.com">StackPHP</a> and it’s completely changed the way I’m thinking about app development (and helped inform the design of Proton).</p>
<p>The principle of StackPHP is that you build up layers of classes that implement <a href="https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/HttpKernelInterface.php">HttpKernelInterface</a>. Then each implementing class decorates another class so that you get several layers that pass around Request and Response objects in a common way.</p>
<p>For example, before your application runs you might want to:</p>
<ol>
<li>Parse any cookies sent in the request</li>
<li>Validate a session cookie that may be present</li>
<li>Respond with a 403 if the session cookie is invalid and exit before the main application logic runs.</li>
</ol>
<p>This is nicely demonstrated below by an onion image on the StackPHP website:</p>
<p><img src="http://stackphp.com/img/onion.png" alt="http://stackphp.com/img/onion.png" /></p>
<p>As long as each middleware (and the application itself) implements HttpKernelInterface you can literally stack these layers on top of each other and everything that follows will inherit and benefits from the preceding layers.</p>
<p>These middlewares can easily be with Proton too:</p>
<script src="https://gist.github.com/alexbilbie/dda1ece33134adbf4bf6.js"></script>
<p>The StackPHP website has a number of useful <a href="http://stackphp.com/middlewares/">middlewares built by the community</a>, as well as <a href="http://stackphp.com/toolbox/">some others</a> that help with the decoration of the layers (<a href="https://github.com/stackphp/builder">StackPHP/Builder</a>) and implement sessions in requests (<a href="https://github.com/stackphp/session">StackPHP/Session</a>). There are also <a href="http://stackphp.com/specs/">four work-in-progress conventions and protocols</a> that ensure interoperability between disparate middlewares.</p>
<p>I’ve already started on building a middleware <a href="https://github.com/thephpleague/oauth2-server">league/oauth2-server</a> and I will include this in the very nearly complete version 4 release.</p>
<p><a href="http://alexbilbie.com/2014/10/introducing-proton/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Open Source Guilthttp://alexbilbie.com/2014/08/open-source-guiltFri, 15 Aug 2014 13:30:00 +0000Alex Bilbie
<p>For the past few years I’ve “maintained” two very popular PHP libraries; an <a href="https://github.com/thephpleague/oauth2-server">OAuth 2 Server</a> and an <a href="https://github.com/thephpleague/oauth2-client">OAuth 2 Client</a>.</p>
<p>I’ve willingly and happily poured hours of my life into both projects. This was easily done when I worked for the University of Lincoln as both libraries were outputs of a project that I worked on. After leaving the university I moved to London and my life <em>“got flipped-turned upside down”</em> (as Will Smith once put it) which naturally resulted in a reduction in the number of commits that went into the projects.</p>
<p>This didn’t concern me too much though; as far as I was concerned at the time the code worked, it was documented and I could point to a number of blog posts with solutions to common problems. I received numerous emails from other developers thanking me for my work on the projects and a number of developers in the PHP community that I respected promoted the library, invited me to talk on podcasts and offered me freelance opportunities to implement the libraries into their codebases. I was happy.</p>
<p>The second half of 2013 I reworked some of the server code which was quickly becoming the more popular of the two libraries and I released version 3 which improved the library’s compliance with the OAuth 2.0 specification and the code itself was much cleaner. I tagged version 3, and I was again happy.</p>
<p>But I was lazy. I didn’t update the documentation and I didn’t update my blog posts which had example code implementations. Github issues started to appear asking for help, but some very kind developers who were interested in the project helped me answer them. The emails changed from thanks and congratulations to calls for help; and at one point I was receiving upwards of 30 emails a week.</p>
<p>Late 2013 I started working on version 4 to correct some pet-peeves I had with the code. I had become a benevolent dictator of the project and rejected numerous improvements to the existing codebase. I did my best with the emails piling up in my inbox but I also ignored many. My focus was only on the new version, because to me I knew it was better and I was able to easily implement it and I became frustrated by people who asked for help suggesting they just read the code and work it out.</p>
<p>During this time (from about November to March this year) I feel that on reflection I was fundamentally depressed and fed up. I felt terribly burnt out and couldn’t even comprehend looking at a computer screen once I got home from work, I was unhappy with where I was living and I felt immense pressure because so many other developers were depending on me for help working with my code. Some people started to call me out publicly - and rightly so, others were rude and hurtful towards to me and I’m ever grateful to Phil Sturgeon for shooting them down for being arseholes. I’d hit a rut and I needed to get out of it.</p>
<p>Change started earlier this year when I moved house, and at the end of May I left my old job. I took a break between starting a new job, and I started exercising. I improved my diet, made some new friends and found enjoyment in coding again.</p>
<p>However I still had the issue of my projects. Others had worked on the client library and improved it, but my server library had got to about 35 open issues (most of which concerned the lack of documentation) and I’d not commented on them in weeks. I’d missed my promises to others of getting some examples out and actually documenting the current stable version. <a href="https://github.com/bshaffer/oauth2-server-php">Another OAuth 2 server project</a> also overtook mine in popularity (and rightly so).</p>
<p>About a fortnight ago I received an email from a developer which immensely upset me; he wasn’t rude or angry but expressed his immense disappointment in me. I knew at that point that I had to get my act into gear and stop avoiding this elephant in the room.</p>
<p>And I’ve really tried. I’ve polished off version 4, merged it into the <code class="highlighter-rouge">develop</code> branch and finally written some goddamn <a href="http://oauth2.thephpleague.com">documentation</a> for it. As soon as that is finished (including an upgrade guide from version 3) I’m going to merge everything into master. Then I’m going to sort out the client library and bring that up to spec.</p>
<blockquote>
<p><em>“With great power comes great responsibility”</em></p>
</blockquote>
<p>Releasing open source projects is a great feeling however there are a number of considerations one should bear in mind:</p>
<ol>
<li><strong>Actions have consequences</strong> - consciously making the decision to put something you’ve made on the web with an open source license with the expectation that others may find it useful has a side effect; other developers may come to you with questions, problems, and security concerns. You have a responsibility to do your best to help them out if you care about the integrity, security and reputation of your project.</li>
<li><strong>People want to help</strong> - others may come to you with suggestions to improve or change the codebase. Sometimes these changes can be great and you’ll learn from them (I certainly have). Other times the change might be a good one but it may not fit in with your coding style, your future plans of the project or the code layout, and you should help the person making the change adapt it as necessary. Finally some suggestions may not be appropriate and you should politely explain why and offer suggestions as to how they can make more useful improvement.</li>
<li><strong>Your personal reputation is on the line</strong> - your name and email address will generally be embedded somewhere in the codebase, in git commit logs and in pretty graph visualisations on Github. This includes when you interact with others in bug trackers, and emailing others directly (nothing can stop them taking a screenshot and posting it on Twitter). If you act like an arsehole people will find it and call you out.</li>
<li><strong>Popular open source projects work well when the authors are using the project regularly themselves</strong> - one of the reasons why I have continued to work on the OAuth Server project more than the others is because I’m regularly implementing it in my personal projects or as part of my day to day job.</li>
</ol>
<p>Based on my experiences in recent months I’m going to try the following to make my life easier and happier:</p>
<ol>
<li>I’m going to set out clear roadmaps for the project and more openly invite others to contribute to features.</li>
<li>Document answers to the most common questions and problems so that I can point others to them in the future.</li>
<li>Encourage people to ask questions - whilst this might seem counterproductive to my bulging inbox problem, I’m going to ask people to contact <a href="https://groups.google.com/forum/#!forum/thephpleague">The PHP League’s mailing list</a> rather than contact me directly; this way multiple people can contribute answers.</li>
<li>Be more honest about <em>my</em> availability to work on new features.</li>
</ol>
<p><a href="http://alexbilbie.com/2014/08/open-source-guilt/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Using Ansible with a bastion SSH hosthttp://alexbilbie.com/2014/07/using-ansible-with-a-bastion-hostWed, 02 Jul 2014 10:30:00 +0000Alex Bilbie
<p>A common network security design pattern is to prevent any connections to your application servers from outside of their private subnet, and then using a <a href="http://en.wikipedia.org/wiki/Bastion_host">bastion host</a> hosted in a <a href="http://en.wikipedia.org/wiki/DMZ_%28computing%29">DMZ</a> to selectively whitelist traffic to the servers.</p>
<p>We have such a setup for one of our server pools through which we only allow SSH traffic from specific IP addresses. These servers are also provisioned via <a href="http://www.ansible.com/">Ansible</a> which programatically configures servers via SSH.</p>
<p>Due to our bastion host setup Ansible is unable to talk directly to our application servers so I had to find a way to proxy SSH connections through the bastion host.</p>
<p>I love using Ansible for creating simple tasks to run, for example flushing memcache to clear caches. Running with this example this is my Ansible structure:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>devops/
ansible/
roles/
memcache/
tasks/
main.yml
restart.yml
tasks/
restart-memcache.yml
vars/
production-memcache.yml
bin/
restart-production-memcache.sh
hosts.ini
ssh.config
ansible.cfg
</code></pre></div></div>
<p>The <code class="highlighter-rouge">tasks/restart-production-memcache.sh</code> script looks like this:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/sh</span>
ssh-add <span class="k">${</span><span class="nv">DEPLOY_KEYS_DIR</span><span class="k">}</span>/memcache-servers.pem
ansible-playbook <span class="nt">-i</span> ansible/hosts.ini <span class="nt">-u</span> ansible ansible/tasks/restart-memcache.yml <span class="nt">-v</span>
</code></pre></div></div>
<p>It is called from the root <code class="highlighter-rouge">devops</code> folder and first adds the servers SSH key too the SSH agent and then calls the <code class="highlighter-rouge">restart-memcache.yml</code> playbook which in turn includes the memcache role <code class="highlighter-rouge">restart.yml</code> playbook (as well as other performing other tasks).</p>
<p>In the <code class="highlighter-rouge">ssh.config</code> file I have the following SSH configuration set:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Host bastion
User ec2-user
HostName ###.###.###.###
ProxyCommand none
IdentityFile /path/to/ssh/key.pem
BatchMode yes
PasswordAuthentication no
Host *
ServerAliveInterval 60
TCPKeepAlive yes
ProxyCommand ssh -q -A ec2-user@###.###.###.### nc %h %p
ControlMaster auto
ControlPath ~/.ssh/mux-%r@%h:%p
ControlPersist 8h
User ansible
IdentityFile /path/to/ssh/key.pem
</code></pre></div></div>
<p>First the configuration for connecting to the bastion host is declared. Beneath that is a catch-all for all other hosts which in the <code class="highlighter-rouge">ProxyCommand</code> says to first connect to the bastion host then use netcat (<code class="highlighter-rouge">nc</code>) to pass the Ansible commands to the application server.</p>
<p>From the <code class="highlighter-rouge">devops</code> folder I can run <code class="highlighter-rouge">ssh bastion -F ssh.config</code> and I will be immediately connected to the bastion server.</p>
<p>Next Ansible needs to be told to use this custom SSH config when connecting to the application servers.</p>
<p>In the <code class="highlighter-rouge">ansible.cfg</code> file there is the following configuration:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[ssh_connection]
ssh_args = -o ControlPersist=15m -F ssh.config -q
scp_if_ssh = True
control_path = ~/.ssh/mux-%%r@%%h:%%p
</code></pre></div></div>
<p>When Ansible runs from the <code class="highlighter-rouge">devops</code> folder it will automatically pick up this <code class="highlighter-rouge">ansible.cfg</code> file and use the defined config when playbooks are run.</p>
<p>One issue with this setup is that Ansible’s output as it runs is very verbose as it includes the SSH debug connection information as it passes through the bastion host to connect to the application servers; I’ve not yet found a way to supress this.</p>
<p><a href="http://alexbilbie.com/2014/07/using-ansible-with-a-bastion-host/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Changing Timeshttp://alexbilbie.com/2014/06/changing-timesSun, 08 Jun 2014 22:40:00 +0000Alex Bilbie
<p>For the past year I’ve been relatively quiet about my day to day work owing to the “stealth” mode we have been operating with the project at <a href="http://videogamer.com">Videogamer</a>. After many a rewrite the initial MVP of the project is complete and I’m very proud of what we have designed, coded and architected. There is still some work to be done on the business side before the project is revealed but I’m really excited for the future of the site and the team.</p>
<p>What I can say is though is that I’ve had the opportunity to play with some great technologies such as Elasticsearch, Neo4J and Ansible and I truly feel excited to be a developer at the moment. In my spare time I’m playing around with Docker, and I’ve been teaching myself Ruby and RubyMotion and I’ve written about 5000 words of <a href="/2014/01/introducing-oauthello/">my book</a>.</p>
<p>At the end of May my contract was up at Videogamer and it was time to move on, I’ve thoroughly enjoyed my time with the team and I wish them all the best for the future; I really do believe the platform we’ve been building is the foundation of something great and I’m excited to see it in the wild.</p>
<p>Tomorrow I’m joining <a href="http://yuza.com">Yuza</a>, a mobile business incubator in central London as their new software engineer. Yuza have recently launched <a href="http://pollen.vc/">Pollen Velocity Capital</a>, a service which pays developers their app store revenues on a weekly basis (instead of the 30+ days that it can take for Apple and Google to pay); this money can then be one-click reinvested into social media campaigns or paid directly into the developer’s bank account.</p>
<p>I’ve been relatively quiet on the blogging front this year but I intend to get back to regular blogging soon - I’ve already a post about OpenID 2.0 in my drafts folder, and I’ve been working on a big update to my OAuth 2.0 Server library.</p>
<p>Until then, adieu.</p>
<p><a href="http://alexbilbie.com/2014/06/changing-times/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Notification overloadhttp://alexbilbie.com/2014/01/notification-overloadTue, 21 Jan 2014 09:59:00 +0000Alex Bilbie
<p>Scenario:</p>
<p>Someone sends me a tweet, email, iMessage, or I get a calendar alert</p>
<p>Result:</p>
<ul>
<li>My Macbook alerts me</li>
<li>My iPad alerts me</li>
<li>My iPhone alerts me</li>
<li>And now my wrist vibrates as the alert is forwarded from my iPhone to my Pebble.</li>
</ul>
<p>Aaaghhh.</p>
<p>It would be great if Apple could solve the problem of sending notifications to whichever device is most relevant to me at the time - here are my suggestions:</p>
<ul>
<li>If I’m sat casually browsing on my Macbook then alert me on there (but also send the notifications to my iPhone incase I suddenly get up and go).</li>
<li>If I’m working on my Macbook then send all notifications to my iPhone.</li>
<li>If I’m actively using my iPhone send all notifications there.</li>
<li>If I’m walking and my iPhone is sleeping in my pocket then buzz my Pebble.</li>
</ul>
<p><a href="http://alexbilbie.com/2014/01/notification-overload/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
A week with the Pebblehttp://alexbilbie.com/2014/01/a-week-with-the-pebbleSat, 18 Jan 2014 13:03:00 +0000Alex Bilbie
<p>Just over a week ago my Pebble smartwatch arrived and <a href="/2014/01/6-hours-with-pebble/">I wrote up my initial thoughts</a>. Having used it for a week now I thought I’d write up some further observations.</p>
<p>I said that my initial reason for buying the Pebble was so I could use it as actual watch and I’m slowly getting used to doing so though out of force of habit I still find myself reaching for my phone sometimes but I assume over time this will change.</p>
<p>One aspect that I hadn’t thought about originally (but pointed out by Mother) was that of safety; wandering around late at night in areas of London I’m not as familiar with I do feel more comfortable quickly changing song with a few pushes on my wrist rather than pulling my phone out of my pocket and showing it off to anyone watching. I’ve already developed some muscle memory to quickly change song without looking at my wrist.</p>
<p>I’ve also developed some muscle memory when it comes to knowing where the buttons are and how much force to exert with my thumb in order to register a change of state in the menu. I still think you need to push a little too hard but I don’t think a touch screen is necessarily a better solution.</p>
<p>I’ve now become used to having something on my wrist (this is the first watch I’ve owned) though I may change the strap at some point so I can have custom hole placements as I’m finding the two holes on the strap the Pebble comes with that I use the most are either ever so slightly too lose and so the watch slips or ever so slightly too tight so I’m conscious of that the watch is there.</p>
<p>The word Pebble is now part of my vernacular and everyone else around me because I keep yammering on about it. Therefore I’ve pretty much settled on not referring to it as a watch and just calling it “my Pebble”.</p>
<p>I’ve been running beta versions of the 2.0 firmware and the better iOS app and there are some nice goodies that have been added:</p>
<ul>
<li>Apps; I’ve got apps for getting bus, train and tube time. All immensely useful.</li>
<li>I’ve been trying the [7 minute workout exercise methodology] and there is an app for that.</li>
<li>I bought an app called <a href="https://itunes.apple.com/gb/app/smartwatch-pro-for-pebble/id673907094?mt=8">Smartwatch Pro</a> on the iOS AppStore which works as a “companion” to it’s Pebble app. With this I can access my calendars, tweets, reminders, setup and execute custom HTTP requests (useful if you’ve got smart light bulbs for example) and also make my phone make a loud noise if I can’t find it in my flat (I’m disgusted at myself for how much I’ve already used this - normally I have to eat into my Skype credit to call my mobile to find it).</li>
</ul>
<p>Beta 6 of the firmware is still a bit buggy but I’m sure they’ll iron out the kinks shortly.</p>
<p>All in all I’m still very happy with the Pebble, for the £90 or so it cost me it’s provided excellent value for money and a definite place in my digital life.</p>
<p><a href="http://alexbilbie.com/2014/01/a-week-with-the-pebble/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Introducing OAuthello, a book about OAuthhttp://alexbilbie.com/2014/01/introducing-oauthelloSat, 11 Jan 2014 21:58:00 +0000Alex Bilbie
<figure>
<img src="https://s3.amazonaws.com/titlepages.leanpub.com/oauthello-a-book-about-oauth/large?1389476512" />
</figure>
<p>So tonight <a href="https://twitter.com/alexbilbie/status/422121924547063808">I announced on Twitter</a> that I’m writing a book - <a href="https://leanpub.com/oauthello-a-book-about-oauth/">OAuthello, a book about OAuth</a>.</p>
<p>Why?</p>
<ol>
<li>I’ve been helping Phil Sturgeon edit <a href="https://leanpub.com/build-apis-you-wont-hate">his book</a> for the past few weeks and I’ve really enjoyed the process.</li>
<li>It’s a personal challenge - I genuinely care about this subject and it motivates me.</li>
<li>I’ve written several 5000+ word reports before in my old job so I know I’m capable of putting words on paper.</li>
<li>Everyone else in the PHP community is writing a book so I may as well join in.</li>
</ol>
<p>So here’s my rough plan:</p>
<ol>
<li>Publicly talk about the book so people will badger me about it and judge me if I don’t finish it.</li>
<li>Get a few chapters done before I open the landing page up for sales.</li>
<li>Finish the book by April/May.</li>
<li>Talk about the whole process at <a href="http://croydontechcity.com/">Croydon Tech City</a> once it’s published.</li>
</ol>
<p>Here goes!</p>
<div class="embed-container">
<iframe src="//www.youtube.com/embed/NTSGp4UdEvQ" frameborder="0" allowfullscreen=""></iframe>
</div>
<p><a href="http://alexbilbie.com/2014/01/introducing-oauthello/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
6 hours with the Pebble smartwatchhttp://alexbilbie.com/2014/01/6-hours-with-pebbleFri, 10 Jan 2014 21:59:00 +0000Alex Bilbie
<figure>
![My new Pebble watch](http://distilleryimage11.ak.instagram.com/8a0f19427a1511e398f612f9a6a6a72b_8.jpg)
</figure>
<p>My <a href="https://getpebble.com/">Pebble watch</a> arrived today. Here are my initial thoughts having worn and used it for the last 6 hours.</p>
<ul>
<li>My main reason for buying a watch was for telling the time (and because I can’t rely on having my phone on/with me at music festivals). The fact that the Pebble does other stuff is a bonus.</li>
<li>This is the first watch I’ve ever worn and having something permanently attached to my wrist feels very alien to me.</li>
<li>I wish I could remove some of the default watch faces and just keep the “text watch” face; if you hit either the top or bottom buttons on the right-hand side accidentally the watch face changes and I don’t like the look of them.</li>
<li>I don’t know whether or not to call it a watch or a Pebble when referring to it.</li>
<li>At first I was wearing the <del>Pebble</del> watch on my dominant (right) hand and I was finding it a bit awkward to use. I’ve since moved it to my left hand and found it much more comfortable to press the buttons, although I seemingly have to turn my wrist more towards in order to look at the time.</li>
<li>I think the buttons are too resistant to being pushed and flipping through the menus can be a bit awkward.</li>
<li>I wear a long overcoat when out and about and it annoys me having to get my iPhone out of my pocket to look at the time or change the song that is playing. I can now leave my phone in my pocket and tell the time and change the music all at the push of a button on my wrist. It’s the little things in life…</li>
<li>I love having iOS notifications pushed to my wrist however I keep accidentally pushing the middle button on the right-hand side and dismissing them all before I’ve read them; I wish there was a way to view past notifications.</li>
<li>I now want more contextual information available immediately to me on my wrist - e.g. if I’m within a few metres of a bus stop, I want it to tell me which buses are coming next and when? I’m going to take a look at the <a href="https://developer.getpebble.com/">Pebble SDK</a> to see if I could perhaps make an app to do this.</li>
<li>There doesn’t seem to be a way of telling how drained the battery is which is strange.</li>
</ul>
<p>I’ll report back in a week or so with some updates.</p>
<p><a href="http://alexbilbie.com/2014/01/6-hours-with-pebble/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Using Vagrant and Ansible for distributing educational course virtual machineshttp://alexbilbie.com/2013/12/vagrant-ansible-coursesThu, 19 Dec 2013 11:50:00 +0000Alex Bilbie
<p><a href="http://blog.ouseful.info/2013/12/02/packaging-software-for-distance-learners-vms-101/">Tony Hirst</a> wrote an article on his blog recently that I’d somehow missed in my RSS reader but in any case I’d like to quickly respond to it.</p>
<p>In <a href="http://blog.ouseful.info/2013/12/02/packaging-software-for-distance-learners-vms-101/">“Cursory Thoughts on Virtual Machines in Distance Education Courses”</a> Tony discuses using virtual machines in courses to help distribute software and operating systems to students who increasingly more and more are bringing in very different devices.</p>
<p>This is a common problem is development teams as well, in my current workplace two of us develop on OSX, another uses Ubuntu and our designer uses Windows; therefore it is important for us to have a development environment that works for all of us regardless of the operating system we use.</p>
<p>At the very end of the article Tony mentions using <a href="http://vagrantup.com/">Vagrant</a> which is a small piece of software to help “create and configure lightweight, reproducible, and portable development environments”. Essentially you write a small document in Ruby called a <em>Vagrantfile</em> to describe a virtual machine and then Vagrant will download, configure and spin-up that virtual machine in Virtualbox or VMWare or other Virtualisation software.</p>
<p>A Vagrantfile looks like this:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="no">Vagrant</span><span class="p">.</span><span class="nf">configure</span><span class="p">(</span><span class="s2">"2"</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">config</span><span class="o">|</span>
<span class="n">config</span><span class="p">.</span><span class="nf">vm</span><span class="p">.</span><span class="nf">box</span> <span class="o">=</span> <span class="s2">"lucid32"</span>
<span class="n">config</span><span class="p">.</span><span class="nf">vm</span><span class="p">.</span><span class="nf">box_url</span> <span class="o">=</span> <span class="s2">"http://files.vagrantup.com/lucid32.box"</span>
<span class="n">config</span><span class="p">.</span><span class="nf">vm</span><span class="p">.</span><span class="nf">network</span> <span class="s2">"forwarded_port"</span><span class="p">,</span> <span class="ss">guest: </span><span class="mi">80</span><span class="p">,</span> <span class="ss">host: </span><span class="mi">8080</span>
<span class="n">config</span><span class="p">.</span><span class="nf">vm</span><span class="p">.</span><span class="nf">network</span> <span class="s2">"private_network"</span><span class="p">,</span> <span class="ss">ip: </span><span class="s2">"192.168.100.10"</span>
<span class="n">config</span><span class="p">.</span><span class="nf">vm</span><span class="p">.</span><span class="nf">provider</span> <span class="s2">"virtualbox"</span> <span class="k">do</span> <span class="o">|</span><span class="n">v</span><span class="o">|</span>
<span class="n">v</span><span class="p">.</span><span class="nf">customize</span> <span class="p">[</span><span class="s2">"modifyvm"</span><span class="p">,</span> <span class="ss">:id</span><span class="p">,</span> <span class="s2">"--memory"</span><span class="p">,</span> <span class="s2">"512"</span><span class="p">]</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>
<p>Inside the folder that has the Vagrantfile you just type <code class="highlighter-rouge">vagrant up</code> and Vagrant will do the following (based on the above config):</p>
<ol>
<li>Download a Vagrant box from <a href="http://files.vagrantup.com/lucid32.box">http://files.vagrantup.com/lucid32.box</a> (a Vagrant box is essentially a gzipped .img file with it’s own Vagrantfile describing the box).</li>
<li>Save the downloaded box with the name “lucid32” - if in another Vagrantfile you reference “lucid32” it will use the box that has already been downloaded.</li>
<li>Configure the virtual machine to have 512mb of memory, port forward the guest port 80 to the host’s port 8080 and then give it a private IP address of 192.168.100.10.</li>
<li>Boot the virtual machine.</li>
</ol>
<p>Tony also discusses pre-configuring the virtual machines before distributing them because some students won’t be as au fait with installing software on Linux machines. This is certainly one option but I think in the long run academics would find it tedious trying to create different virtual machines with slight changes and having to store different images for each course.</p>
<p>A better option would be to use another <a href="http://en.wikipedia.org/wiki/DevOps">devops</a> tool called <a href="http://www.ansibleworks.com/">Ansible</a> which “is a powerful automation engine that makes systems and apps simple to deploy”.</p>
<p>Ansible uses <a href="http://en.wikipedia.org/wiki/YAML">YAML</a> files to describe a list of tasks that should be executed on a machine. For example if you wanted to do the following:</p>
<ol>
<li>Update apt</li>
<li>Install PHP + Apache</li>
<li>Open port 80 in the firewall</li>
<li>Start Apache</li>
</ol>
<p>You could express it like this:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">---</span>
<span class="pi">-</span> <span class="na">hosts</span><span class="pi">:</span> <span class="s">webserver</span>
<span class="na">user</span><span class="pi">:</span> <span class="s">vagrant</span>
<span class="na">sudo</span><span class="pi">:</span> <span class="s">True</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">update apt</span>
<span class="na">command</span><span class="pi">:</span> <span class="s">/usr/bin/apt-get update</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">install web server packages</span>
<span class="na">action</span><span class="pi">:</span> <span class="s">apt pkg=$item state=installed</span>
<span class="na">with_items</span><span class="pi">:</span>
<span class="err"> </span><span class="pi">-</span> <span class="s">httpd</span>
<span class="err"> </span><span class="s">- php</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">allow port 80</span>
<span class="na">command</span><span class="pi">:</span> <span class="s">/usr/sbin/ufw allow http</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">flush firewall</span>
<span class="na">command</span><span class="pi">:</span> <span class="s">/usr/sbin/ufw reload</span>
</code></pre></div></div>
<p>This YAML file (called a “playbook” in Ansible terminology) can be <a href="http://docs.vagrantup.com/v2/provisioning/ansible.html">automatically executed by Vagrant</a> to <a href="http://en.wikipedia.org/wiki/Provisioning#Server_provisioning">“provision”</a> the virtual machine.</p>
<p>Ansible playbooks can include other playbooks so an academic can have a playbook of common tasks and then have individual playbooks with slight variations for different courses.</p>
<p>Together the playbooks and the Vagrantfile can be distributed to the students and assuming they’ve installed Vagrant and Virtualbox for their OS they can be up and running with identical environments in just a few minutes.</p>
<p>At my workplace we use the same Ansible playbooks for both local development and provisioning our staging and production servers - together with similarly configured Vagrant boxes and VMWare vCloud (our cloud environment) images we’ve almost entirely removed the old problem of “but it works on my machine”.</p>
<p>As well as teaching students a version control system and how to use the command line I think it is vital that all computer science students finish their courses with familiarity of devops tools like Virtualbox, Vagrant, Ansible, and even tools like <a href="https://github.com/jedi4ever/veewee">Veewee</a> which help build custom Vagrant boxes.</p>
<p><a href="http://alexbilbie.com/2013/12/vagrant-ansible-courses/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Build APIs you won't hatehttp://alexbilbie.com/2013/12/build-apis-you-wont-hateThu, 12 Dec 2013 13:40:00 +0000Alex Bilbie
<p><a href="http://philsturgeon.co.uk/">Phil Sturgeon</a> is writing a book entitled <em>Build APIs you won’t hate</em> and I’m helping him as a technical reviewer.</p>
<p>He’s trying to work on a chapter a week and it’s starting to shape up nicely. <a href="https://leanpub.com/build-apis-you-wont-hate">Go buy a copy!</a></p>
<p><a href="http://alexbilbie.com/2013/12/build-apis-you-wont-hate/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Sometimes, travellers need a holiday from the holidayhttp://alexbilbie.com/2013/12/travellers-need-a-holiday-from-the-holidayWed, 11 Dec 2013 23:29:00 +0000Alex Bilbie
<blockquote>
<p>Sometimes, travellers need a holiday from the holiday. A chance to recharge, to stay in one place for a while, establish a little bit of a routine and just enjoy the art of not doing.
<a href="http://riseandshinepaps.wordpress.com/2013/12/05/a-holiday-from-the-holiday/">link</a></p>
</blockquote>
<p>My good friend Tara who has been travelling around the world for the last 6 months, through Africa, India and Asia. She’s still got another two continents to go!</p>
<p>She’s written some fantastic posts throughout her trip, do check out her blog.</p>
<p><a href="http://alexbilbie.com/2013/12/travellers-need-a-holiday-from-the-holiday/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
A nifty refresh-token trickhttp://alexbilbie.com/2013/11/Oauth-2-refresh-token-trickMon, 25 Nov 2013 22:36:00 +0000Alex Bilbie
<p>Tim Bray, who works on the Google Identity team, <a href="https://www.tbray.org/ongoing/When/201x/2013/11/02/Oauth-2-refresh-token-trick">documents here</a> a pretty cool trick you can do (in a very specific scenario) to check if someone still is part of an organisation by using OAuth 2.0 refresh tokens</p>
<p><a href="http://alexbilbie.com/2013/11/Oauth-2-refresh-token-trick/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Open data FTW!http://alexbilbie.com/2013/09/open-data-ftwTue, 24 Sep 2013 09:53:00 +0000Alex Bilbie
<figure>
![http://www.ordnancesurvey.co.uk/collateral/images/hdk/RS1385_southampton-water-minecraft.jpg](http://www.ordnancesurvey.co.uk/collateral/images/hdk/RS1385_southampton-water-minecraft.jpg)
</figure>
<p>Joseph Braybrook, an intern at the <a href="http://www.ordnancesurvey.co.uk/innovate/">Ordanance Survey Inovation Labs</a>, <a href="http://www.ordnancesurvey.co.uk/innovate/developers/minecraft-map-britain.html">has created 86,000 square miles worth of geographically accurate Great Britain</a> using some of their <a href="http://www.ordnancesurvey.co.uk/business-and-government/products/opendata-products.html">open data products</a>.</p>
<p>Some fine work there. In the linked blog post you can download the Minecraft world too.</p>
<p><a href="http://alexbilbie.com/2013/09/open-data-ftw/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
How to securely store OAuth access tokens in single page JavaScript web appshttp://alexbilbie.com/2013/09/securely-store-access-tokens-in-single-page-web-appFri, 06 Sep 2013 11:04:00 +0000Alex Bilbie
<p>A question I’m asked frequently is how developers should securely store OAuth access tokens and client credentials in a single page JavaScript webapp.</p>
<p>Here’s the answer: you can’t.</p>
<p>There is currently no way of securely storing something in front end JavaScript code and decrypting it without leaking your encryption key too<sup>*</sup>.</p>
<p>I can only think of one way to potentially help secure the API requests and that is by giving the browser a short-lived X.509 certificate (perhaps with the same TTL as an access token) which must be presented to the API along with the access token. The certificate’s “Subject Unique Identifier” parameter would contain the user’s ID.</p>
<p>The user’s browser will automatically present the certificate when requested by the API server during an API call and the server would then check the “Subject Unique Identifier” matched the ID of the user who owns the access token. An attacker will have to sniff both the access token (easily done) and the certificate (hard because it’s not accessible via JavaScript) in order to make a fraudulent request.</p>
<p>Having said that I really don’t think it’s worth the pain of development, testing, debugging and maintaining. Instead my recommendation is to have a very thin backend script through which all ajax requests are proxied. This backend script can securely store the user’s access token in an encrypted cookie/session/whatever and it securely keeps client’s credentials away from the front end.</p>
<p>Shameless plug: If you want to really easily implement a standards compliant OAuth 2.0 authorization server or secure your API with OAuth 2.0 then check out my PHP library - <a href="https://github.com/thephpleague/oauth2-server">https://github.com/thephpleague/oauth2-server</a>.</p>
<p><sup>*</sup> <em>I don’t know if any of the upcoming HTML5 cryptography specifications will remedy this.</em></p>
<p><a href="http://alexbilbie.com/2013/09/securely-store-access-tokens-in-single-page-web-app/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
The League of Extraordinary Packageshttp://alexbilbie.com/2013/08/the-php-leagueSat, 17 Aug 2013 10:48:00 +0000Alex Bilbie
<figure>
![http://www.thephpleague.com/images/logo.png](http://www.thephpleague.com/img/logo.png)
</figure>
<p>Phil Sturgeon and I have been working on a little project for a while called <a href="http://www.thephpleague.com/">The League of Extraordinary Packages</a>:</p>
<blockquote>
<p>The League of Extraordinary Packages has one driving mission, to track down and develop PHP packages of the highest quality possible, using modern tools, standards and practices to distribute, test and strengthen the code.</p>
<p>Members of The League follow the standards put forward by the PHP-FIG, follow the best practices detailed by PHP The Right Way and distribute all code through Composer.</p>
</blockquote>
<p>We’ve already got some great packages on there such as <a href="https://github.com/php-loep/DI">DI</a> which is a bleeding fast dependancy injection container, <a href="https://github.com/php-loep/Geotools">Geotools</a> which makes doing geo related work a much more pleasant experience and <a href="https://github.com/php-loep/grunt">Grunt</a> which is a library for executing commands in parallel on multiple remote machines via SSH.</p>
<p>My OAuth2 <a href="https://github.com/php-loep/oauth2-server">server</a> and <a href="https://github.com/php-loep/oauth2-client">client</a> packages are now part of the League too and Ben Corlett and Phil are working on a great OAuth1 client library too.</p>
<p>We’ve also got an awesome logo too thanks to <a href="https://twitter.com/dansyme">Dan Syme</a>.</p>
<p><a href="http://alexbilbie.com/2013/08/the-php-league/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
The Pixar Theoryhttp://alexbilbie.com/2013/07/the-pixar-theoryMon, 29 Jul 2013 22:53:00 +0000Alex Bilbie
<p><a href="http://jonnegroni.com/2013/07/11/the-pixar-theory/">Bloody marvellous speculation here</a>. If this turns out to be true then I hope we hear the behind the scenes story one day.</p>
<p><a href="http://alexbilbie.com/2013/07/the-pixar-theory/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Diversityhttp://alexbilbie.com/2013/07/diversitySun, 21 Jul 2013 21:33:00 +0000Alex Bilbie
<p><a href="http://hueniverse.com/2013/07/diversity-2/">A beautiful post</a> by Eran Hammer.</p>
<blockquote>
<p>In a rich, multidimensional reality, we must consider not only the attributes of the individuals, but also the makeup of the community we are trying to build. Setting a goal of more women, blacks, gays, etc. is pointless. That’s a stupid goal. Setting quotas is mechanical and more likely alienate others instead of bringing them in.</p>
</blockquote>
<p><a href="http://alexbilbie.com/2013/07/diversity/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Talking all things OAuth 2.0 on PHP Town Hall Podcasthttp://alexbilbie.com/2013/07/php-town-hall-podcastWed, 10 Jul 2013 20:41:00 +0000Alex Bilbie
<p>I was recently invited to join <a href="http://philsturgeon.co.uk">Phil Sturgeon</a>, <a href="http://benedmunds.com/">Ben Edmunds</a> and <a href="https://twitter.com/zachianblank">Zachary Blank</a> on the <a href="http://phptownhall.com">PHP Town Hall Podcast</a> to talk about OAuth 2.0.</p>
<p>Check it out - <a href="http://phptownhall.com//blog/2013/07/10/episode-9-is-oauth-2-the-devil/">http://phptownhall.com//blog/2013/07/10/episode-9-is-oauth-2-the-devil/</a>.</p>
<p>Please forgive my waffling, it was midnight GMT by the time we started recording and I was high as a kite on Red Bull and jelly beans.</p>
<p><a href="http://alexbilbie.com/2013/07/php-town-hall-podcast/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Ask GCHQhttp://alexbilbie.com/2013/06/askgchqSun, 23 Jun 2013 11:11:00 +0000Alex Bilbie
<blockquote>
<p>“What do you want us to know about you today?”
<a href="http://www.jonathancresswell.co.uk/askgchq/">link</a></p>
</blockquote>
<p><a href="http://alexbilbie.com/2013/06/askgchq/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Good Data Practicehttp://alexbilbie.com/2013/06/Good-Data-PracticeWed, 12 Jun 2013 11:56:00 +0000Alex Bilbie
<p><a href="http://blog.soton.ac.uk/data/2013/06/07/good-data-practice/">A good post</a> by Ashley Smith at the University of Southampton on how to properly prepare spreadsheets that are used to form open data.</p>
<p><a href="http://alexbilbie.com/2013/06/Good-Data-Practice/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
A fortnight in the big smokehttp://alexbilbie.com/2013/06/A-fortnight-in-the-big-smokeSun, 09 Jun 2013 18:26:00 +0000Alex Bilbie
<p>Today marks a fortnight since my mother dropped me at Peterborough train station with two bulging suitcases (one with a dodgy wheel I later found out) and my trusty laptop so that I could venture South to London to begin anew.</p>
<p>Assuming that it would take me a few weeks to find somewhere for myself and my friend <a href="http://twitter.com/mlbrook">Michelle</a> to live I booked into a property that I found on <a href="http://airbnb.co.uk">Airbnb</a> which is about twenty minutes walk to my new place of work here in Croydon. I’d heard some good things about Airbnb from friends and figuring that I couldn’t afford to live in a hotel for two weeks and I’d go stir crazy too I decided to take a risk and dropped £286 for a fortnights accommodation in someone’s spare room where I had freedom to live (semi) normally in multiple rooms, I could cook and I wouldn’t have cleaners interrupting my beauty sleep. Below are some of the photos of where I’ve been staying:</p>
<figure>![https://a0.muscache.com/pictures/11172211/large.jpg](https://a0.muscache.com/pictures/11172211/large.jpg)</figure>
<figure>![https://a2.muscache.com/pictures/11172655/large.jpg](https://a2.muscache.com/pictures/11172655/large.jpg)</figure>
<figure>![https://a0.muscache.com/pictures/11172755/large.jpg](https://a0.muscache.com/pictures/11172755/large.jpg)</figure>
<figure>![https://a0.muscache.com/pictures/11173416/large.jpg](https://a0.muscache.com/pictures/11173416/large.jpg)</figure>
<p>My host Francesca has a <a href="https://www.airbnb.co.uk/rooms/740645">really, really, beautiful house</a> (the few photos above that I’ve hotlinked from Airbnb’s website don’t do it justice) and she was a wonderful host during my stay. I would definately recommend anyone who is travelling has a look on the site to see what’s available and I’d even go so far as to say I don’t want to stay in a hotel again if, for a fraction of the cost, stay in an entire apartment instead of paying for an over-priced hotel.</p>
<p>Trying to find somewhere to live in London has been stressful and I mostly had the same shitty customer experience that I had when I was looking in Lincoln a year ago. Estate agents can be the most helpful people you’ll ever meet or they will be the most uncaring, cold and unsympathetic people you’ll ever meet. I’ve experienced both (more the latter than the former). We wanted to live in or around the Clapham Common or Balham area and London rental prices for a decent sized two bedroom apartment are upwards of £1600 per month. In the end we’ve managed to get into a brand-new-just-finished-last-week apartment near Tooting Broadway for £1450 per month. It really does pay to shop around. I’m glad I saved some money over the past few months as when we sign for the keys next weekend we’ll be dropping almost £4000 on the first months rent, deposit and agents fees.</p>
<p>Some photos (from Zoopla) of our new pad:</p>
<figure>![http://content.zoopla.co.uk/766d144b84ba0b2ecd608441c671f7858c8c1d81.jpg](http://content.zoopla.co.uk/766d144b84ba0b2ecd608441c671f7858c8c1d81.jpg)</figure>
<figure>![http://content.zoopla.co.uk/5a77bdcdd0985341567ccef512dc70064bb60e81.jpg](http://content.zoopla.co.uk/5a77bdcdd0985341567ccef512dc70064bb60e81.jpg)</figure>
<figure>![http://content.zoopla.co.uk/3ede657e72520d5b45b7fb7403cc5b9dee38cf01.jpg](http://content.zoopla.co.uk/3ede657e72520d5b45b7fb7403cc5b9dee38cf01.jpg)</figure>
<figure>![http://content.zoopla.co.uk/c51e796cb4edf4127ec1d328ee6b444ef988d57f.jpg](http://content.zoopla.co.uk/c51e796cb4edf4127ec1d328ee6b444ef988d57f.jpg)</figure>
<p>A few things I found different about renting in London verses Lincoln; first most flats in London are furnished with both white goods (fridge, washing machine, etc) and furniture whereas in Lincoln it was uncommon to find places with anything. Secondly in London you almost always will be dealing with the landlords directly after you’ve signed the tenancy agreement for any maintenance issues and the like, whereas in Lincoln (in my experience) you almost always deal with the estate agents. Also something I haven’t experienced before is having to pay for a third party to come in and do an inventory of the property before and after the tenancy, again in Lincoln the estate agents generally dealt with this as part of their service.</p>
<p>My new job has been working out great. <a href="http://www.videogamer.com/staff">My new colleagues</a> (I’ll be featured on that page soon enough) are all lovely and have all been very welcoming. I’ve not actually written any code in the past fortnight, instead (as my Twitter followers will attest) I’ve been arguing with <a href="http://www.opscode.com/chef/">Chef</a> and VMware vCloud Director. We’ve also had a couple of iteration meetings and hopefully in a few weeks once a few more bits are in place I’ll have more to write about in terms of what I’m going to be working on. It was a little strange at first having to adjust my brain into thinking about a new problem domain (as opposed to thinking about improving the staff and student experience in a university), but I’m really excited about our future plans. I also don’t have to care about users who are using a corporate desktop with IE7, this alone is bloody lovely.</p>
<p>I’ve a busy month ahead, next weekend I’m in Leeds at a wedding, the following weekend my parents are driving a van down to London with all of my belongings which are currently in storage (I missing my cooking stuff so much!) and the last weekend of June I’m going to be losing my Glastonbury (and music festival) virginity.</p>
<p><a href="http://alexbilbie.com/2013/06/A-fortnight-in-the-big-smoke/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Eight Nerds Get Rich Off A Game Where Oprah Sobs Into A Lean Cuisinehttp://alexbilbie.com/2013/05/cards-against-humanityFri, 31 May 2013 10:12:00 +0000Alex Bilbie
<blockquote>
<p>“The world ends not with a bang, but with a mime having a stroke”</p>
</blockquote>
<p><a href="http://www.chicagogrid.com/enterprise/cards-against-humanity-game-money/">Inspiring stuff.</a></p>
<p><a href="http://alexbilbie.com/2013/05/oprah-sobs-into-a-lean-cuisine/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Developing an interactive county council election map (part two)http://alexbilbie.com/2013/05/developing-an-interactive-county-council-election-map-part-twoWed, 08 May 2013 09:00:00 +0000Alex Bilbie
<blockquote>
<p>This is a follow-up to my first post: <a href="http://alexbilbie.com/2013/04/developing-an-interactive-county-council-election-map-part-one/">Developing an interactive county council election map (part one)</a>.</p>
</blockquote>
<p>Last Thursday (and Friday) proved to be an interesting day, both for myself and the people of Lincolnshire. It’s been well documented by the media how well UKIP did both nationally but in Lincolnshire it was especially interesting as we’ve been a blue county for decades and we now have a very different (and colourful) political landscape.</p>
<p>Here is how the map looked before and after the election:</p>
<figure>
![http://thelincolnite.co.uk/wp-content/uploads/2013/05/comparison.jpg](http://thelincolnite.co.uk/wp-content/uploads/2013/05/comparison.jpg)
</figure>
<p>On Thursday morning I was interviewed by journalism.co.uk as they were really interested in what The Lincolnite and I had been up to. Check out the article here <a href="http://www.journalism.co.uk/news/hyperlocal-site-the-lincolnite-cover-elections-live-interactive-map/s2/a552859/">http://www.journalism.co.uk/news/hyperlocal-site-the-lincolnite-cover-elections-live-interactive-map/s2/a552859/</a>.</p>
<p>I spent Thursday evening sat with the guys from <a href="http://thelincolnite.co.uk">The Lincolnite</a> drinking cold water and redbull trying to stay awake as we sat in the county council chamber from 9:30pm until almost 5am waiting for results to come in from across the county.</p>
<p>I took a few photos over the course of the night:</p>
<p>When results came in these boards would be updated with the results</p>
<figure>
![When results came in these boards would be updated with the results](/images/elections-1.jpg)
</figure>
<p>The media teams (The Lincolnite team, BBC Radio Lincolnshire and BBC stringers calling the results into London)</p>
<figure>
![The media teams](/images/elections-2.jpg)
</figure>
<p>An example results paper that was filled out and passed around when results were phoned in from across the county</p>
<figure>
![An example results paper that was filled out and passed around when results were phoned in from across the county](
/images/elections-3.jpg)
</figure>
<p>Taken around 4am as we waited for the final few results to come in. By this point a few other journalists had turned up as well as successful candidates, political wonks and other interested parties</p>
<figure>
![/images/elections-4.jpg](/images/elections-4.jpg)
</figure>
<figure>
![/images/elections-5.jpg](/images/elections-5.jpg)
</figure>
<p>For the interactive map Daniel (The Lincolnite’s editor) and I really liked the idea of having a “bar of power” across the top of the map which showed a visual makeup of the 77 divisions and was sorted left to right by the parties with the most seats. Each little division was clickable too and zoomed into the map. It also proved a useful way of seeing how many seats were left to be called as some of the divisions such as Stamford North are tiny to see on the map.</p>
<figure>
![/images/elections-part-two-map.png](/images/elections-part-two-map.png)
</figure>
<p>At 10pm (when voting stops) we switched the map to one that had no colour and just showed the outlines of the different divisions. Every 30 seconds an ajax request polled the server for the latest results and updated the map and bar of power with the winning colour and when a user zoomed into an area it would show the final results.</p>
<figure>
![/images/elections-part-two-zoom.png](/images/elections-part-two-zoom.png)
</figure>
<p>As results came in I sat and updated my very sexy admin interface with the number of votes each candidate received:</p>
<figure>
![/images/elections-entry-form.png](/images/elections-entry-form.png)
</figure>
<p>The Lincolnite team were <a href="http://thelincolnite.co.uk/2013/05/lincolnshire-local-elections-2013-results/">running a live blog</a> which had the map embedded at the top so for the many readers who were keeping an eye on the page throughout the night they had a nice realtime (ish) experience.</p>
<p>I learnt a few new things whilst developing the updated map. The main thing was how <a href="http://api.jquery.com/promise/">jQuery promises</a> worked which meant that until all 77 divisions had loaded (almost 2mb of JSON) the ajax poller wouldn’t start. I also included a nice little loading message too which appeared and disappeared as the status of the deferred object changed.</p>
<p>I also learnt a lot more about the <a href="http://leafletjs.com">Leaflet.js</a> API and I’m definitely going to use it again if I can come up with another geospacial project to work on.</p>
<p>We learnt a few things from this little experiment.</p>
<p>First of all is that we need to work really closely with the county council to try and get all of the data required in a more usable format (such as CSV) as we wasted so much time going through 77 PDFs and manually copy and pasting names, parties and districts.</p>
<p>Next we need to work with the local party associations so they can update their candidates biographical information themselves without them having to speak to us every time they want someone’s photo changing.</p>
<p><a href="http://blog.ouseful.info/2013/05/02/uk-local-elections-2013-live-data-live-maps/">Tony Hirst wrote a nice roundup</a> of other websites who also created live maps. He also speculates if “this will be the last round of elections without a national live data feed from somewhere pushing out the results in a standardised form”. I’ve been thinking about this a lot and I’m wondering if it might be worth teaming up with <a href="http://openlylocal.com/">OpenlyLocal</a> and <a href="http://mysociety.org">MySociety</a> to create some sort of national service. Perhaps more on that later?</p>
<p>All in all I had great fun making the maps, I learnt some new stuff, The Lincolnite got some well deserved coverage and praise and I also decided that I don’t find myself waiting for Stamford North to finish counting their votes at 4:30am again.</p>
<p><a href="http://alexbilbie.com/2013/05/developing-an-interactive-county-council-election-map-part-two/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Developing an interactive county council election map (part one)http://alexbilbie.com/2013/04/i-made-a-thingSat, 27 Apr 2013 11:00:00 +0000Alex Bilbie
<p>A few weeks ago I was approached by the guys at <a href="http://thelincolnite.co.uk">The Lincolnite</a> to look into developing an interactive page for the upcoming Lincolnshire County Council elections on the 2nd of May.</p>
<p>Part one launched yesterday and here’s what I’ve come up with:</p>
<figure>
![Elections map](http://alexbilbie.com/images/elections-part-one.png)
</figure>
<p>Check it out here - <a href="http://thelincolnite.co.uk/elections">http://thelincolnite.co.uk/elections</a></p>
<p>The map loads GeoJSON representations pf all 77 electoral divisions in Lincolnshire County Council and renders them on a custom <a href="http://mapbox.com/">Mapbox</a> map (which hides a lot of unnecessary map detail such as buildings) using <a href="http://leafletjs.com/">Leaflet.js</a>. Each division is coloured in with the colour of the party that is currently represented in that area. When a user clicks on a district it zooms in and displays in the right hand column the current councillor and a list of the 2013 candidates.</p>
<p>In the right hand column users can also enter their postcode which is sent to <a href="http://mysociety.org">MySociety’s</a> excellent <a href="http://mapit.mysociety.org">MapIt</a> service. If the postcode is real and is in the Lincolnshire County Council area then it will return with the ID of the division which will then zoom the map in and show candidates as above.</p>
<p>I encountered a few challenges along the way. First getting the candidates data was the most labour intense thing I’ve done in a while and there was no easy way to automate it.</p>
<p>Basically the council had a semi-complete spreadsheet of results from 2009 which after a bit of mangling provided me with an initial set of results which I could use to colour the map in (and I will use again for part two to compare this year’s results to previous results). In 2012 there were two by-elections and I found the results for these not from the council but local newspapers.</p>
<p>To get the 2013 candidates I had to wade through 77 differently formatted (depending on the parent district council) PDFs to manually copy and paste the candidates into my own CSV. One district council didn’t even include the parties the candidates were representing and I had to get this from another CSV provided by the county council (which didn’t include candidates’ first names otherwise I’d just have used that).</p>
<p>All of the CSV data was then loaded into a MySQL database and the Lincolnite guys can easily update candidates with links to photos and manifestos.</p>
<p>The other problem I had was trying to find a javascript mapping library that gave me the flexibility I needed and also wouldn’t grind to a halt when I fed it 77 GeoJSON encoded divisions.</p>
<p>I ruled out Google Maps because I couldn’t easily customise the map of Lincolnshire (i.e. remove buildings and make the roads, land and water lighter). Also everyone uses Google Maps and I wanted to play with something different for a change. I tried Mapbox’s own javascript framework with D3.js but that cried when I added more than about 30 divisions. I finally discovered leaflet.js which I really struggled to get my head around the API in order to make it do what I needed but it was very lightweight and the performance is fantastic.</p>
<p>So part one is out, and there’s just under a week to go until the elections which gives me a few days to finish off part two which is when the map will live update when results come in and update swingometers and other funky widgets on the fly.</p>
<p><a href="http://alexbilbie.com/2013/04/developing-an-interactive-county-council-election-map-part-one/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
So long, and thanks for all of the fish!http://alexbilbie.com/2013/04/the-next-chapterMon, 08 Apr 2013 11:00:00 +0000Alex Bilbie
<p>On the 13th of September 2008 I moved to Lincoln to study computer science at the University of Lincoln. Fresh faced, excited to move out of my parents’ house and looking forward to experiencing phone signal for the first time, the 18 year old me was ready to start a new life.</p>
<p>Fast forward almost 5 years and it’s time to start again.</p>
<p>At the end of May I’m leaving this beautiful city to move to my other home from home, London. I will be joining <a href="http://www.pro-gmedia.com/">Pro-G Media</a>, the proprietors of the very popular and highly respected <a href="http://videogamer.com">VideoGamer.com</a> as their new senior developer.</p>
<p>I leave Lincoln with many many great friends, four great years of employment at the University of Lincoln, five JISC projects under my belt, and a new found love of coffee. I’ve made some great contacts at many universities around the country, I’ve attended tens of conferences and I’ve presented my “Introduction to HTML5 and CSS3” presentation more times that I’d like to remember. I even managed to fit a degree in too.</p>
<p>To those who’ve given me opportunities here, especially <a href="http://josswinn.org">Joss Winn</a>, I’m incredibly grateful, and I’m sure I’ll be back to visit soon enough. I’m going to miss working (read: eating bacon, drinking coffee and dreaming up crazy hacks) with <a href="https://twitter.com/jacksonj04">Nick Jackson</a>, <a href="http://twitter.com/jmahoney127">Jamie Mahoney</a>, and <a href="https://twitter.com/jh_newton">Harry Newton</a> every day but we’ll all be living on the East Coast mainline so I’m sure we’ll be regularly meeting up.</p>
<p>I intend to remain in contact with the higher education and library developer community and I remain a strong supporter of the <a href="http://data.ac.uk/">data.ac.uk</a> movement and will try and take part in the discussions where I can.</p>
<p>I’m beyond excited about moving to London and tackling many new challenges, from actually moving to London (more on that later), to helping <a href="http://videogamer.com">VideoGamer.com</a> expand to a million daily visitors and beyond.</p>
<p>Not only that but I’m looking forward to being able to explore a different Sunday market every week of the year, go to far more music gigs than I’m currently able to, and I’m sure there are many delightful bars and coffee shops that I need to research and visit. Also I’m determined to live in a flat again that has gas hobs on the cooker - my wok can’t wait!</p>
<p>So thank you Lincoln, thank you Lincolnites, and thank you <a href="https://twitter.com/unilincoln">@unilincoln</a>. London, please put the kettle on!</p>
<blockquote>
<p><em>“The story of life is quicker than the wink of an eye, the story of love is hello and goodbye…until we meet again” - Jimi Hendrix</em></p>
</blockquote>
<p><a href="http://alexbilbie.com/2013/04/so-long-and-thanks-for-all-of-the-fish/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Goodbye TVC!http://alexbilbie.com/2013/03/goodbye-tvcFri, 22 Mar 2013 19:40:00 +0000Alex Bilbie
<p>I’m sat writing this as I watch the One Show which is the final ever live broadcast from BBC Television Centre.</p>
<p>I’ve been fortunate to visit Television Centre twice, once just a fortnight ago today, and also back in July 2011. My close friend Josh was working there both times I visited and he gave me a full tour of the entire building in 2011. I remember walking round in near silence as I absorbed 50 years of broadcasting history - it really is an incredible building which just oodles culture. I particularly remember visiting the Blue Peter garden and having my photo next to the Tardis. We also stood in the tech gallery and watched as the audience were warmed up for Jool’s Hollands show.</p>
<p>Whilst I don’t have any more experiences that I do feel truly honoured for having the opportunity to visit somewhere where so many of my favourite TV shows were filmed, from Blue Peter to Black Adder and Fawlty Towers.</p>
<p>Goodbye TVC!</p>
<figure>
![/images/goodbye-tvc.jpg](/images/goodbye-tvc.jpg)
</figure>
<p><a href="http://alexbilbie.com/2013/03/goodbye-tvc/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
50 years of 007http://alexbilbie.com/2013/03/bond-tribute-videoFri, 22 Mar 2013 11:36:00 +0000Alex Bilbie
<p>The best tribute I've seen yet to the 50 year legacy of James Bond.</p>
<div class="embed-container">
<iframe src="http://www.youtube.com/embed/t10mNXtfdUw?rel=0" frameborder="0" allowfullscreen></iframe>
</div>
<p><a href="http://alexbilbie.com/2013/03/50-years-of-007/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
API driven development: eating your own dog foodhttp://alexbilbie.com/2013/03/phpne-slidesThu, 21 Mar 2013 00:00:00 +0000Alex Bilbie
<p>On Tuesday I presented at the first ever <a href="http://conference.phpne.org.uk/">PHP North East</a> conference in Newcastle. Hosted in the fantastic <a href="https://www.tynesidecinema.co.uk/">Tyneside Cinema</a> (which is the last surviving Newsreel theatre still operating as a cinema full-time in the UK), it was a very well organised event and I’m incredibly grateful to the <a href="http://phpne.org.uk/">PHP North East group</a> for accepting my talk proposal.</p>
<p>My topic was “API driven development: Eating your own dog food”, I’ve embedded my slides below:</p>
<script async class="speakerdeck-embed" data-id="570f6a2072c90130970822000a9f0177" data-ratio="1.22634730538922" src="//speakerdeck.com/assets/embed.js"></script>
<p>Unfortunately they weren’t able to video my talk so my slides may seem a little out of context but hopefully you can get the overall gist of what I talked about.</p>
<p>Once again, I’d like to say thank you to Anthony Sterling and the PHPNE crew for putting on a wonderful event.</p>
<p><a href="http://alexbilbie.com/2013/03/api-driven-development-talk/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
More OAuth pitfalls that you can easily avoidhttp://alexbilbie.com/2013/03/avoiding-oauth-pitfallsFri, 15 Mar 2013 19:07:00 +0000Alex Bilbie
<p><code class="highlighter-rouge">&lt;rage&gt;</code></p>
<p>Egor Homakov has written <a href="http://homakov.blogspot.co.uk/2013/03/redirecturi-is-achilles-heel-of-oauth.html?m=1">another blog post</a> today exploring Facebook’s OAuth problem (as I dubbed it in <a href="http://alexbilbie.com/2013/02/facebooks-oauth-problem/">my previous post</a>).</p>
<p>Basically if you are developing an OAuth authorisation server then you <strong>must</strong> whitelist the entire redirect URI, not just the domain. In the <a href="http://tools.ietf.org/html/draft-ietf-oauth-v2-threatmodel-08#section-4.1.5">OAuth threat model specification</a> there is a <a href="http://tools.ietf.org/html/draft-ietf-oauth-v2-threatmodel-08#section-4.1.5">whole section (4.1.5)</a> dedicated to discuss pitfalls with open redirectors.</p>
<blockquote>
<p>If the authorization server allows the client to register only part of the redirection URI, an attacker can use an open redirector operated by the client to construct a redirection URI that will pass the authorization server validation but will send the authorization code or access token to an endpoint under the control of the attacker.</p>
</blockquote>
<p>Also if you have to use the implicit grant for whatever reason then as I said in <a href="http://alexbilbie.com/2013/02/a-guide-to-oauth-2-grants/">my guide to OAuth grants</a> you <strong>must</strong> bear this in mind:</p>
<blockquote>
<p>If you decide to implement this grant then you must be aware that the access token should be treated as “public knowledge” (like a public RSA key) and therefore it must have a very limited permissions when interacting with the API server.</p>
</blockquote>
<p>Unless you have a very very specific need and you can perhaps secure clients with client side certificates or you have a very clean environment then I strongly recommend you just avoid the implicit grant.</p>
<p><code class="highlighter-rouge">&lt;/rage&gt;</code></p>
<p><a href="http://alexbilbie.com/2013/03/avoiding-oauth-pitfalls/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; Dammithttps://twitter.com/sup3rmark/status/312028126932779008Fri, 15 Mar 2013 00:00:00 +0000Alex Bilbie
<blockquote class="twitter-tweet" align="center"><p>Two weeks of no pope: baby cured of HIV, breath test for cancer, salt water found on moon of Jupiter. Day one with pope: Google Reader dies.</p>&mdash; sup3rmark (@sup3rmark) <a href="https://twitter.com/sup3rmark/status/312028126932779008">March 14, 2013</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p><a href="http://alexbilbie.com/2013/03/dammit/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Anyone who thinks social media is﻿ a valid replacement for an RSS-reader, leave the room nowhttp://alexbilbie.com/2013/03/hitler-google-readerThu, 14 Mar 2013 12:28:00 +0000Alex Bilbie
<div class="embed-container">
<iframe src="http://www.youtube.com/embed/A25VgNZDQ08?rel=0" frameborder="0" allowfullscreen></iframe>
</div>
<p>
I'm genuinely gutted about <a href="http://googlereader.blogspot.co.uk/2013/03/powering-down-google-reader.html" rel="nofollow">Google Reader shutting down</a>. Time to find something else I guess. Or maybe build something myself? Gah.
</p>
<p>
And Orkut didn't get the chop? WTF?
</p>
<p><a href="http://alexbilbie.com/2013/03/hitler-google-reader/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Twitter's official clients have their OAuth keys leakhttp://alexbilbie.com/2013/03/twitter-official-clients-have-their-oauth-keys-leakThu, 07 Mar 2013 15:00:00 +0000Alex Bilbie
<p>Someone <a href="https://gist.github.com/re4k/3878505">has posted a Github Gist</a> with all of the client identifiers and secret keys for the official Twitter clients on various platforms.</p>
<p>This just highlights why it is imperitive that you <a href="http://alexbilbie.com/2013/02/facebooks-oauth-problem/">don’t screw up like Facebook did</a> by allowing wildcard client redirect URIs.</p>
<p>The client redirect URIs <strong>must</strong> be absolute and stored on the authorisation server.</p>
<h2 id="so-what-can-twitter-do-about-this">So what can Twitter do about this?</h2>
<p>They could release new binarys for all of their clients with new keys and invalidate the old keys, but clients that haven’t been updated will suddenly stop working and leave users confused and frustrated. Also it will be trivial for the new keys to be leaked too.</p>
<p>Alternatively they could come up with some sort of mechanism to allow the official clients to download new keys on the fly but then these could be captured with a man-in-the-middle attack.</p>
<h2 id="but-is-it-actually-a-problem">But is it actually a problem?</h2>
<p>First, it is important to recognise that this is really only a problem for desktop/mobile app clients (assuming that is that web server based clients themselves keep their keys secure - the differnece being that someone would have to break into a web server to get to them).</p>
<p>Therefore as long as Twitter aren’t giving their own applications additional functionality that 3rd party clients can’t replicate then there isn’t too much of a problem because with this equal playing field scenario it could be Tweetbot or MetroTwit we’re talking about.</p>
<p>Having said that, the official iOS mobile client at least does allow you to register a new account, so these leaked keys could be used to create spam accounts.</p>
<p>With 3rd party Twitter clients being limited to 100,000 access tokens this could tempt some to make use of these keys however if they were caught then they risk being named and shamed by the media and that in turn could also result in developer accounts being banned by Apple and Google from their app stores.</p>
<h2 id="is-oauth-to-blame">Is OAuth to blame?</h2>
<p>No, the OAuth protocol is behaving as it designed to here. That is, if a 3rd party client presented a correctly formed request with these valid keys and the correct redirect URI then, assuming Twitter doesn’t have some extra security in place to validate requests using their keys (such as validating user-agent strings for example), the authorisation server will assume the request is genuine.</p>
<p><a href="http://alexbilbie.com/2013/03/twitter-official-clients-have-their-oauth-keys-leak/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Boris Johnson on the EU's plan to cap bankers bonuseshttp://alexbilbie.com/2013/02/boris-opinionThu, 28 Feb 2013 12:18:00 +0000Alex Bilbie
<p><a href="http://www.bbc.co.uk/news/business-21621045">Boris Johnson’s eloquent opinion</a> of the EU’s plan to cap bankers bonuses:</p>
<blockquote>
<p>“This is possibly the most deluded measure to come from Europe since Diocletian tried to fix the price of groceries across the Roman Empire”</p>
</blockquote>
<p>Agreed.</p>
<p><a href="http://alexbilbie.com/2013/02/boris-opinion/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
The proper way of solving life's problemshttp://alexbilbie.com/2013/02/the-proper-way-of-solving-lifes-problemsWed, 27 Feb 2013 12:27:00 +0000Alex Bilbie
<p>
One man vs. his pet hate in life, Oreo cream.
</p>
<div class="embed-container">
<iframe src="http://www.youtube.com/embed/pii4G8FkCA4?rel=0" frameborder="0" allowfullscreen></iframe>
</div>
<p><a href="http://alexbilbie.com/2013/02/the-proper-way-of-solving-lifes-problems/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; How hackers changed the world: We Are Legionhttp://www.bbc.co.uk/i/b01qxmwp/Wed, 27 Feb 2013 10:40:00 +0000Alex Bilbie
<p>Last night I watched a BBC Four <a href="http://www.bbc.co.uk/programmes/b006mfx6">Storyville</a> documentary called <a href="http://www.bbc.co.uk/programmes/b01qxmwp">“How hackers changed the world: We Are Legion”</a>.</p>
<p>The programmes blurb is:</p>
<blockquote>
<p>A documentary going inside the complex network and history of Anonymous, the radical online ‘hacktivist’ collective, using interviews with members, writers and academics.</p>
</blockquote>
<p>If you’re interested in the history of hacking culture, how computers are changing the world, and how anyone with an Internet can easily make their voice heard by the masses then I’d recommend giving it a watch.</p>
<p>At the time of writing there are still 5 days of availability on iPlayer (it’s available until 10:29PM on Monday 4th March).</p>
<p><a href="http://alexbilbie.com/2013/02/how-hackers-changed-the-world/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Nine Inch Nails returns!http://alexbilbie.com/2013/02/nin-reformMon, 25 Feb 2013 22:40:00 +0000Alex Bilbie
<p>This is quite literally the best news I've heard all year. I've seen Nine Inch Nails four times live and I missed them last time they toured the UK. Hopefully it won't be long until they're back!</p>
<blockquote class="twitter-tweet tw-align-center" data-cards="hidden"><p>Nine Inch Nails returns! <a href="http://t.co/5E7k77EIbB" title="http://p4k.in/15ejToz">p4k.in/15ejToz</a></p>&mdash; Trent Reznor (@trent_reznor) <a href="https://twitter.com/trent_reznor/status/306059428627615744">February 25, 2013</a></blockquote>
<script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p><a href="http://alexbilbie.com/2013/02/nin-reform/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Facebook’s OAuth problemhttp://alexbilbie.com/2013/02/facebooks-oauth-problemMon, 25 Feb 2013 11:00:00 +0000Alex Bilbie
<p>Last week self-proclaimed web security evangelist Egor Homakov published a blog post entitled <a href="http://homakov.blogspot.co.uk/2013/02/hacking-facebook-with-oauth2-and-chrome.html">How we hacked Facebook with OAuth2 and Chrome bugs</a>. Naturally this led to a new round of “OAuth 2.0 is unsecure” comments on news articles that linked to the post.</p>
<p>If you actually read through the post however, the part of the attack that involves OAuth is this bit (emphasis from original text):</p>
<blockquote>
<p>2) OAuth2 is… quite unsafe auth framework. Gigantic attack surface, all parameters are passed in URL. I will write a separate post about OAuth1 vs OAuth2 in a few weeks. Threat Model is bigger than in official docs.
In August 2012 I wrote a lot about common vulnerabilities-by-design and even proposed to fix it: OAuth2.a.</p>
<p>We used 2 bugs: <strong>dynamic redirect_uri and dynamic response_type parameter</strong>.
response_type=code is the most secure authentication flow, because end user never sees his access_token. But response_type is basically <strong>a parameter in authorize URL</strong>. By replacing response_type=code to response_type=token,signed_request we receive both token and code on our redirect_uri.</p>
<p>redirect_uri can be not only app’s domain, <strong>but facebook.com domain is also allowed</strong>.
In our exploit we used response_type=token,signed_request&amp;redirect_uri=FB_PATH where FB_PATH was a specially crafted URL to disclose these values..</p>
</blockquote>
<p>If an OAuth 2.0 authorisation server is correctly configured then it should, in addition to numerous other checks, ensure that there is only one value in the <em>response_type</em> parameter (e.g. “code” - if using the authorization code grant) and the server should store whitelisted redirect URIs for each client on the server so that attacks can’t be launched with dynamic URIs.</p>
<p>I suspect partly why this has happened to Facebook is because when they launched their Graph APIs back in 2010 they secured them with draft 5 of the OAuth 2.0 specification. As the specification changed over it’s 27 drafts they already had clients hardcoded with specific parameters that couldn’t be updated easily and so therefore they had to make a choice to allow the above parameters that were used in the attack to accept dynamic and non-canon values.</p>
<p><a href="http://alexbilbie.com/2013/02/php-meet-oauth-2/">My OAuth 2.0 server library</a> is not vulnerable to the aforementioned attack as it strictly validates and verifies every parameter that is sent to it and redirect URIs are whitelisted on the server.</p>
<p><a href="http://alexbilbie.com/2013/02/facebooks-oauth-problem/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; I used Google Glass: the future, with monthly updateshttp://www.theverge.com/2013/2/22/4013406/i-used-google-glass-its-the-future-with-monthly-updatesSat, 23 Feb 2013 00:00:00 +0000Alex Bilbie
<blockquote>
<p>But I walked away convinced that this wasn’t just one of Google’s weird flights of fancy. The more I used Glass the more it made sense to me; the more I wanted it. If the team had told me I could sign up to have my current glasses augmented with Glass technology, I would have put pen to paper (and money in their hands) right then and there. And it’s that kind of stuff that will make the difference between this being a niche device for geeks and a product that everyone wants to experience.</p>
</blockquote>
<p>Great article by Joshua Topolsky for The Verge. Google are hoping to have it in the shops by the end of 2013. If developers can add their own features to Glass then I think this will be amazing.</p>
<p><a href="http://alexbilbie.com/2013/02/i-used-glass/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Securing your API with OAuth 2.0http://alexbilbie.com/2013/02/securing-your-api-with-oauth2Fri, 22 Feb 2013 12:04:00 +0000Alex Bilbie
<p>In <a href="http://alexbilbie.com/2013/02/php-meet-oauth-2/">a previous post</a> I announced my new OAuth 2.0 PHP libraries.</p>
<p>In this post I will show you how to use the server library to secure a simple API with OAuth 2.0.</p>
<hr />
<h2 id="install-the-library">Install the library</h2>
<p>The recommended way of installing the library is via <a href="http://getcomposer.org">Composer</a>.</p>
<p>If you already have a composer.json file in your root then add <code class="highlighter-rouge">”lncd/oauth2”: “*”</code> in the <em>require</em> object. Then run <code class="highlighter-rouge">composer update</code>.</p>
<p>Otherwise create a new file in your project root called <em>composer.json</em> add set the contents to:</p>
<pre><code data-language="javascript">{
"require": {
"lncd/OAuth2": "*"
}
}
</code></pre>
<p>Now, assuming you have installed Composer run <code class="highlighter-rouge">composer install</code>.</p>
<p>Ensure now that you’ve set up your project to autoload composer packages.</p>
<p>You could alternatively add the library as a git submodule or download a <a href="https://nodeload.github.com/lncd/OAuth2/zip/master">zip</a>.</p>
<h2 id="set-up-the-database">Set up the database</h2>
<p>To setup the database just import <em>sql/mysql.sql</em></p>
<h2 id="create-the-storage-models">Create the storage models</h2>
<p>In order to retrieve data from the database you should create classes which implement the following interfaces:</p>
<ul>
<li><code class="highlighter-rouge">\OAuth2\Storage\ScopeInterface</code></li>
<li><code class="highlighter-rouge">\OAuth2\Storage\SessionInterface</code></li>
</ul>
<h2 id="hooking-it-all-up">Hooking it all up</h2>
<p>Setting up the library is simple, just create a new instance of <code class="highlighter-rouge">\OAuth2\ResourceServer</code> and pass in your storage models.</p>
<pre><code data-language="php">// Include the storage models
include 'model_scope.php';
include 'model_session.php';
// Initiate the Request handler
$request = new \OAuth2\Util\Request();
// Initiate the auth server with the models
$server = new \OAuth2\ResourceServer(new SessionModel, new ScopeModel);
</code></pre>
<h2 id="checking-for-valid-access-tokens">Checking for valid access tokens</h2>
<p>Before your API responds you need to check that an access token has been presented with the request (either in the query string <code class="highlighter-rouge">?access_token=abcdef</code> or as an authorization header <code class="highlighter-rouge">Authorization: bearer abcdef</code>).</p>
<p>If you’re using a framework such as Laravel or CodeIgniter you could use a route filter to do this, or have a custom controller which other controllers extend from. In this example I’m using the Slim framework and I’m going to create a simple <a href="http://docs.slimframework.com/pages/routing-middleware/">route middleware</a> which is run before each endpoint function.</p>
<pre><code data-language="php">$checkToken = function () use ($server) {
return function() use ($server)
{
// Test for token existance and validity
try {
$server-&gt;isValid();
}
// The access token is missing or invalid...
catch (\OAuth2\Exception\InvalidAccessTokenException $e)
{
$app = \Slim\Slim::getInstance();
$res = $app-&gt;response();
$res['Content-Type'] = 'application/json';
$res-&gt;status(403);
$res-&gt;body(json_encode(array(
'error' =&gt; $e-&gt;getMessage()
)));
}
};
};
</code></pre>
<p>When <code class="highlighter-rouge">$server-&gt;isValid()</code> is called the library will run the following tasks:</p>
<ul>
<li>Check if an access token is present in the query string
<ul>
<li>If not, check if a base64 encoded access token is contained in an authorization header.
<ul>
<li>If not, throw <code class="highlighter-rouge">\OAuth2\Exception\InvalidAccessTokenException</code></li>
</ul>
</li>
</ul>
</li>
<li>Check if the access token is valid with the database
<ul>
<li>If not, throw <code class="highlighter-rouge">\OAuth2\Exception\InvalidAccessTokenException</code></li>
</ul>
</li>
<li>If the access token is valid:
<ul>
<li>Get the owner type (e.g. “user” or “client”) and their ID</li>
<li>Get a list of any scopes that are associated with the access token</li>
</ul>
</li>
</ul>
<p>Assuming an exception isn’t thrown you can then use the following functions in your API code:</p>
<ul>
<li><code class="highlighter-rouge">getOwnerType()</code> - This will return the type of the owner of the access token. For example if a user has authorized another client to use their resources the owner type would be “user”.</li>
<li><code class="highlighter-rouge">getOwnerId()</code> - This will return the ID of the access token owner. You can use this to check if the owner has permission to do take some sort of action (such as retrieve a document or upload a file to a folder).</li>
<li><code class="highlighter-rouge">hasScope()</code> - You can use this function to see if a specific scope (or several scopes) has been associated with the access token. You can use this to limit the contents of an API response or prevent access to an API endpoint without the correct scope.</li>
</ul>
<h2 id="a-simple-example">A simple example</h2>
<p>This example endpoint will return a user’s information if a valid access token is present. If the access token has the <code class="highlighter-rouge">user.contact</code> it will return additional information.</p>
<pre><code data-language="php">$app-&gt;get('/user/:id', $checkToken(), function ($id) use ($server, $app) {
$user_model = new UserModel();
$user = $user_model-&gt;getUser($id);
if ( ! $user)
{
$res = $app-&gt;response();
$res-&gt;status(404);
$res['Content-Type'] = 'application/json';
$res-&gt;body(json_encode(array(
'error' =&gt; 'User not found'
)));
}
else
{
// Basic response
$response = array(
'error' =&gt; null,
'result' =&gt; array(
'user_id' =&gt; $user['id'],
'firstname' =&gt; $user['firstname'],
'lastname' =&gt; $user['lastname']
)
);
// If the acess token has the "user.contact" access token include
// an email address and phone numner
if ($server-&gt;hasScope('user.contact'))
{
$response['result']['email'] = $user['email'];
$response['result']['phone'] = $user['phone'];
}
// Respond
$res = $app-&gt;response();
$res['Content-Type'] = 'application/json';
$res-&gt;body(json_encode($response));
}
});
</code></pre>
<h2 id="limiting-an-endpoint-to-a-specific-owner-type">Limiting an endpoint to a specific owner type</h2>
<p>In this example, only a user’s access token is valid:</p>
<pre><code data-language="php">$app-&gt;get('/user', $checkToken(), function () use ($server, $app) {
$user_model = new UserModel();
// Check the access token's owner is a user
if ($server-&gt;getOwnerType() === 'user')
{
// Get the access token owner's ID
$userId = $server-&gt;getOwnerId();
$user = $user_model-&gt;getUser($userId);
// If the user can't be found return 404
if ( ! $user)
{
$res = $app-&gt;response();
$res-&gt;status(404);
$res['Content-Type'] = 'application/json';
$res-&gt;body(json_encode(array(
'error' =&gt; 'Resource owner not found'
)));
}
// A user has been found
else
{
// Basic response
$response = array(
'error' =&gt; null,
'result' =&gt; array(
'user_id' =&gt; $user['id'],
'firstname' =&gt; $user['firstname'],
'lastname' =&gt; $user['lastname']
)
);
// If the acess token has the "user.contact" access token include
// an email address and phone numner
if ($server-&gt;hasScope('user.contact'))
{
$response['result']['email'] = $user['email'];
$response['result']['phone'] = $user['phone'];
}
// Respond
$res = $app-&gt;response();
$res['Content-Type'] = 'application/json';
$res-&gt;body(json_encode($response));
}
}
// The access token isn't owned by a user
else
{
$res = $app-&gt;response();
$res-&gt;status(403);
$res['Content-Type'] = 'application/json';
$res-&gt;body(json_encode(array(
'error' =&gt; 'Only access tokens representing users can use this endpoint'
)));
}
});
</code></pre>
<p>You might use an API function like this to allow a client to discover who a user is after they’ve signed into your authorization endpoint (<a href="http://alexbilbie.com/2013/02/developing-an-oauth2-authorization-server/">see an example of how to do this here</a>).</p>
<h2 id="limiting-an-endpoint-to-a-specific-owner-type-and-scope">Limiting an endpoint to a specific owner type and scope</h2>
<p>In this example, the endpoint will only respond to access tokens that are owner by client applications and that have the scope <code class="highlighter-rouge">users.list</code>.</p>
<pre><code data-language="php">$app-&gt;get('/users', $checkToken(), function () use ($server, $app) {
$user_model = new UserModel();
$users = $user_model-&gt;getUsers();
// Check the access token owner is a client
if ($server-&gt;getOwnerType() === 'client' &amp;&amp; $server-&gt;hasScope('users.list'))
{
$response = array(
'error' =&gt; null,
'results' =&gt; array()
);
$i = 0;
foreach ($users as $k =&gt; $v)
{
// Basic details
$response['results'][$i]['user_id'] = $v['id'];
$response['results'][$i]['firstname'] = $v['firstname'];
$response['results'][$i]['lastname'] = $v['lastname'];
// Include additional details with the right scope
if ($server-&gt;hasScope('user.contact'))
{
$response['results'][$i]['email'] = $v['email'];
$response['results'][$i]['phone'] = $v['phone'];
}
$i++;
}
$res = $app-&gt;response();
$res['Content-Type'] = 'application/json';
$res-&gt;body(json_encode($response));
}
// Access token owner isn't a client or doesn't have the correct scope
else
{
$res = $app-&gt;response();
$res-&gt;status(403);
$res['Content-Type'] = 'application/json';
$res-&gt;body(json_encode(array(
'error' =&gt; 'Only access tokens representing clients can use this endpoint'
)));
}
});
</code></pre>
<p>You might secure an endpoint in this way to only allow specific clients (such as your applications’ main website) access to private APIs.</p>
<hr />
<p>Hopefully you will see how easy it is to secure an API with OAuth 2.0 and how you can use scopes to limit response contents or access to endpoints.</p>
<p>You can download a complete working example here - <a href="https://github.com/lncd/oauth2-example-resource-server">https://github.com/lncd/oauth2-example-resource-server</a>.</p>
<p><a href="http://alexbilbie.com/2013/02/securing-your-api-with-oauth-2/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; Open policy documentshttp://lincoln.nickjackson.me/the-power-of-open-policy/Fri, 22 Feb 2013 11:50:00 +0000Alex Bilbie
<p>My colleague <a href="https://twitter.com/jacksonj04">Nick Jackson</a> discusses publishing policy documents in the open on Github:</p>
<blockquote>
<p>What’s interesting about using open text-based standards to write policy, Git for managing revisions and GitHub as a storage provider is that we’ve inadvertently made it very easy for people to do things that they couldn’t do before.</p>
<p>Where previously the process of creating policy was a bit mysterious, the entire world can now see not only the published version of the document – and by digging through the archives previously published versions – but every single change made in the history of the policy and who made it. Every change from the beginning of the document is trackable on a line-by-line basis, and using Git it’s even possible to see who is responsible for any single line of content. This gives us the immediate benefit of accountability, something which is great for finding out exactly who wrote a bit of a document if it needs clarification.</p>
</blockquote>
<p><a href="http://alexbilbie.com/2013/02/open-policy/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Developing an OAuth 2.0 authorization serverhttp://alexbilbie.com/2013/02/developing-an-oauth2-authorization-serverFri, 22 Feb 2013 09:00:00 +0000Alex Bilbie
<hr />
<h3 id="this-article-is-very-out-of-date---please-see-the-latest-documentation-at-httpsoauth2thephpleaguecom">This article is very out of date - please see the latest documentation at <a href="https://oauth2.thephpleague.com">https://oauth2.thephpleague.com</a></h3>
<hr />
<p>In <a href="http://alexbilbie.com/2013/02/php-meet-oauth-2/">my previous post</a> I announced my new OAuth 2.0 PHP libraries. This is the first in a number of posts that will show you how to use it.</p>
<hr />
<p>This guide will show you how to setup a basic OAuth 2.0 authorization server which supports the authorization code grant type.</p>
<h2 id="install-the-library">Install the library</h2>
<p>The recommended way of installing the library is via <a href="http://getcomposer.org">Composer</a>.</p>
<p>If you already have a composer.json file in your root then add <code class="highlighter-rouge">"lncd/oauth2”: “*”</code> in the <em>require</em> object. Then run <code class="highlighter-rouge">composer update</code>.</p>
<p>Otherwise create a new file in your project root called <em>composer.json</em> add set the contents to:</p>
<pre><code data-language="javascript">{
"require": {
"lncd/OAuth2": "*"
}
}
</code></pre>
<p>Now, assuming you have installed Composer run <code class="highlighter-rouge">composer install</code>.</p>
<p>Ensure now that you’ve set up your project to autoload composer packages.</p>
<hr />
<p>You could alternatively add the library as a git submodule or download a <a href="https://nodeload.github.com/league/OAuth2/zip/master">zip</a>.</p>
<h2 id="set-up-the-database">Set up the database</h2>
<p>To setup the database just import <em>sql/mysql.sql</em></p>
<h2 id="create-your-first-client">Create your first client</h2>
<p>In OAuth terms a <em>client</em> is an application (it could be a website or a mobile app) that communicates with your API.</p>
<p>Insert a client into the <code class="highlighter-rouge">oauth_clients</code> table. It is recommended that you make the <code class="highlighter-rouge">id</code> and <code class="highlighter-rouge">secret</code> fields random alphanumeric strings - <a href="http://randomkeygen.com/">http://randomkeygen.com/</a> is a useful for this. The <code class="highlighter-rouge">auto_approve</code> parameter should be to <em>1</em> if you want the user to automatically approve access to the client, otherwise set it to <em>0</em>.</p>
<p>If you want to use the <em>authorization grant</em> (where a user is redirected to the auth server from the client and the back in order to “sign-in” or “connect” with the client) then in the <code class="highlighter-rouge">oauth_client_endpoints</code> add a redirect URI (where the user is redirected back to after signing in). You can add multiple redirect URIs for production and development.</p>
<h2 id="create-the-storage-models">Create the storage models</h2>
<p>In order to persist data to the database you should create classes which implement the following three interfaces:</p>
<ul>
<li><code class="highlighter-rouge">\OAuth2\Storage\ClientInterface</code></li>
<li><code class="highlighter-rouge">\OAuth2\Storage\ScopeInterface</code></li>
<li><code class="highlighter-rouge">\OAuth2\Storage\SessionInterface</code></li>
</ul>
<h2 id="the-authorization-code-grant">The authorization code grant</h2>
<p>For reference here is an overview of how the authorization code grant works:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>+--------+ +---------------+
| |--(A)- authorisation Request -&gt;| Resource |
| | | Owner |
| |&lt;-(B)-- authorisation Grant ---| |
| | +---------------+
| |
| | +---------------+
| |--(C)-- authorisation Grant --&gt;| authorisation |
| Client | | Server |
| |&lt;-(D)----- Access Token -------| |
| | +---------------+
| |
| | +---------------+
| |--(E)----- Access Token ------&gt;| Resource |
| | | Server |
| |&lt;-(F)--- Protected Resource ---| |
+--------+ +---------------+
</code></pre></div></div>
<p><strong>(A)</strong> The client requests authorisation from the resource owner. The authorisation request can be made directly to the resource owner (as shown), or preferably indirectly via the authorisation server as an intermediary.</p>
<p><strong>(B)</strong> The client receives an authorisation grant, which is a credential representing the resource owner’s authorisation, expressed using one of four grant types defined in this specification or using an extension grant type. The authorisation grant type depends on the method used by the client to request authorisation and the types supported by the authorisation server.</p>
<p><strong>(C)</strong> The client requests an access token by authenticating with the authorisation server and presenting the authorisation grant.</p>
<p><strong>(D)</strong> The authorisation server authenticates the client and validates the authorisation grant, and if valid issues an access token.</p>
<p><strong>(E)</strong> The client requests the protected resource from the resource server and authenticates by presenting the access token.</p>
<p><strong>(F)</strong> The resource server validates the access token, and if valid, serves the request.</p>
<h2 id="create-an-oauth-controller">Create an <em>oauth</em> controller</h2>
<p><em>NOTE: This is assuming you’re using a framework that follows an MVC pattern, If you’re using individual files for each page then you create a new page for each controller route listed henceforth.</em></p>
<p>In your controller constuctor you should instantiate the auth server:</p>
<pre><code data-language="php">public function __construct()
{
// Initiate the request handler which deals with $_GET, $_POST, etc
$request = new \OAuth2\Util\Request();
// Create the auth server, the three parameters passed are references
// to the storage models
$this-&gt;authserver = new \OAuth2\AuthServer(
new ClientModel,
new SessionModel,
new ScopeModel
);
// Enable the authorization code grant type
$this-&gt;authserver-&gt;addGrantType(new \OAuth2\Grant\AuthCode());
// Set the TTL of an access token in seconds (default to 3600s / 1 hour)
$this-&gt;authserver-&gt;setExpiresIn(86400);
}
</code></pre>
<p>Create your first route (for example “index” - which would resolve to <em>/oauth</em>).</p>
<pre><code data-language="php">public function action_index()
{
try {
// Tell the auth server to check the required parameters are in the
// query string
$params = $this-&gt;authserver-&gt;checkAuthoriseParams();
// Save the verified parameters to the user's session
Session::put('client_id', $params['client_id']);
Session::put('client_details', $params['client_details']);
Session::put('redirect_uri', $params['redirect_uri']);
Session::put('response_type', $params['response_type']);
Session::put('scopes', $params['scopes']);
// Redirect the user to the sign-in route
return Redirect::to(‘oauth/signin');
} catch (Oauth2\Exception\ClientException $e) {
// Throw an error here which says what the problem is with the
// auth params
} catch (Exception $e) {
// Throw an error here which has caught a non-library specific error
}
}
</code></pre>
<p>Next create a sign-in route:</p>
<pre><code data-language="php">public function action_signin()
{
// Retrieve the auth params from the user's session
$params['client_id'] = Session::get('client_id');
$params['client_details'] = Session::get('client_details');
$params['redirect_uri'] = Session::get('redirect_uri');
$params['response_type'] = Session::get('response_type');
$params['scopes'] = Session::get('scopes');
// Check that the auth params are all present
foreach ($params as $key=&gt;$value) {
if ($value === null) {
// Throw an error because an auth param is missing - don't
// continue any further
}
}
// Process the sign-in form submission
if (Input::get('signin') !== null) {
try {
// Get username
$u = Input::get('username');
if ($u === null || trim($u) === '') {
throw new Exception('please enter your username.');
}
// Get password
$p = Input::get('password');
if ($p === null || trim($p) === '') {
throw new Exception('please enter your password.');
}
// Verify the user's username and password
// Set the user's ID to a session
} catch (Exception $e) {
$params['error_message'] = $e-&gt;getMessage();
}
}
// Get the user's ID from their session
$params['user_id'] = Session::get('user_id');
// User is signed in
if ($params['user_id'] !== null) {
// Redirect the user to /oauth/authorise route
return Redirect::to('oauth/authorise');
}
// User is not signed in, show the sign-in form
else {
return View::make('oauth.signin', $params);
}
}
</code></pre>
<p>In the sign-in form HTML page you should tell the user the name of the client that their signing into.</p>
<p>Once the user has signed in (if they didn’t already have an existing session) then they should be redirected the authorise route where the user explicitly gives permission for the client to act on their behalf.</p>
<pre><code data-language="php">public function action_authorise()
{
// Retrieve the auth params from the user's session
$params['client_id'] = Session::get('client_id');
$params['client_details'] = Session::get('client_details');
$params['redirect_uri'] = Session::get('redirect_uri');
$params['response_type'] = Session::get('response_type');
$params['scopes'] = Session::get('scopes');
// Check that the auth params are all present
foreach ($params as $key=&gt;$value) {
if ($value === null) {
// Throw an error because an auth param is missing - don't
// continue any further
}
}
// Get the user ID
$params['user_id'] = Session::get('user_id');
// User is not signed in so redirect them to the sign-in route (/oauth/signin)
if ($params['user_id'] === null) {
return Redirect::to('signin');
}
// Check if the client should be automatically approved
$autoApprove = ($params['client_details']['auto_approve'] === '1') ? true : false;
// Process the authorise request if the user's has clicked 'approve' or the client
if (Input::get('approve') !== null || $autoApprove === true) {
// Generate an authorization code
$code = $this-&gt;authserver-&gt;newAuthoriseRequest('user', $params['user_id'], $params);
// Redirect the user back to the client with an authorization code
return Redirect::to(
\OAuth2\Util\RedirectUri::make($params['redirect_uri'],
array(
'code' =&gt; $code,
'state' =&gt; isset($params['state']) ? $params['state'] : ''
)
));
}
// If the user has denied the client so redirect them back without an authorization code
if (Input::get('deny') !== null) {
return Redirect::to(
\OAuth2\Util\RedirectUri::make($params['redirect_uri'],
array(
'error' =&gt; $this-&gt;authserver-&gt;exceptionCodes[2],
'error_message' =&gt; $this-&gt;authserver-&gt;errors[$this-&gt;authserver-&gt;exceptionCodes[2]],
'state' =&gt; isset($params['state']) ? $params['state'] : ''
)
));
}
// The client shouldn't automatically be approved and the user hasn't yet
// approved it so show them a form
return View::make('oauth.authorise', $params);
}
</code></pre>
<p>In the authorize form the user should again be told the name of the client and also list all the scopes (permissions) it is requesting.</p>
<p>The final route to create is where the client exchanges the authorization code for an access token.</p>
<pre><code data-language="php">public function action_access_token()
{
try {
// Tell the auth server to issue an access token
$response = $this-&gt;authserver-&gt;issueAccessToken();
} catch (\Oauth2\Exception\ClientException $e) {
// Throw an exception because there was a problem with the client's request
$response = array(
'error' =&gt; $this-&gt;authserver::getExceptionType($e-&gt;getCode()),
'error_description' =&gt; $e-&gt;getMessage()
);
} catch (Exception $e) {
// Throw an error when a non-library specific exception has been thrown
$response = array(
'error' =&gt; 'undefined_error',
'error_description' =&gt; $e-&gt;getMessage()
);
}
header('Content-type: application/json');
echo json_encode($response);
}
</code></pre>
<p><a href="http://alexbilbie.com/2013/02/developing-an-oauth2-authorization-server/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
PHP, meet OAuth 2.0http://alexbilbie.com/2013/02/php-meet-oauthThu, 21 Feb 2013 00:00:00 +0000Alex Bilbie
<hr />
<h3 id="this-article-is-very-out-of-date---please-see-the-latest-documentation-at-httpsoauth2thephpleaguecom">This article is very out of date - please see the latest documentation at <a href="https://oauth2.thephpleague.com">https://oauth2.thephpleague.com</a></h3>
<hr />
<p>Over the last few months I’ve been developing a PHP library that helps you work with OAuth 2.0 in a number of different ways:</p>
<ul>
<li>Develop an authentication server which can be used as part of a web “single sign on” solution.</li>
<li>Secure your APIs with access tokens and scopes.</li>
<li>Easily sign users in to many different OAuth 2.0 identity providers.</li>
</ul>
<p>The code for the authentication and resource server can be found on Github here <a href="https://github.com/lncd/OAuth2">https://github.com/lncd/OAuth2</a>.</p>
<p>The server library code requires PHP 5.3+, is hooked into <a href="https://packagist.org/packages/lncd/Oauth2">Packagist</a> (a bit like Ruby Gems but for PHP) and has 100% unit test code coverage. It has built in support for the following grants:</p>
<ul>
<li>authentication code (<a href="http://tools.ietf.org/html/rfc6749#section-4.1">section 4.1</a>)</li>
<li>refresh token (<a href="http://tools.ietf.org/html/rfc6749#section-6">section 6</a>)</li>
<li>client credentials (<a href="http://tools.ietf.org/html/rfc6749#section-2.3.1">section 2.3.1</a>)</li>
<li>password (user credentials) (<a href="http://tools.ietf.org/html/rfc6749#section-4.3">section 4.3</a>)</li>
<li>implicit grant (<a href="http://tools.ietf.org/html/rfc6749#section-4.2">section 4.2</a>) - though I don’t recommend you use this grant unless you really understand how to safely use it</li>
</ul>
<p>You can easily create you own grants by extending <code class="highlighter-rouge">\OAuth2\Grant\GrantInterface</code>. I’m going to be creating plugins which support <a href="http://tools.ietf.org/wg/oauth/draft-ietf-oauth-json-web-token/">JSON web tokens</a> and the <a href="http://tools.ietf.org/wg/oauth/draft-ietf-oauth-saml2-bearer/">SAML assertions</a>.</p>
<p>The code for the client library can be found here <a href="https://github.com/lncd/OAuth2-Client">https://github.com/lncd/OAuth2-Client</a> - at the time of writing it isn’t quite finished, I’ll blog when it is.</p>
<p>Over the next few blog posts I’ll document how to use the libraries.</p>
<p><a href="http://alexbilbie.com/2013/02/php-meet-oauth-2/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
How it feels [through Glass]http://alexbilbie.com/2013/02/google-glassWed, 20 Feb 2013 16:15:00 +0000Alex Bilbie
<div class="embed-container">
<iframe src="http://www.youtube.com/embed/v1uyQZNg2vE?rel=0" frameborder="0" allowfullscreen="true"></iframe>
</div>
<p>Amazing.</p>
<p><a href="http://alexbilbie.com/2013/02/how-it-feels-through-glass/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; The Rhino Shieldhttp://www.kickstarter.com/projects/1081571316/rhino-shield-the-impact-resistant-screen-protectorWed, 20 Feb 2013 00:00:00 +0000Alex Bilbie
<p>This is the first thing I’ve ever backed on Kickstarter.</p>
<p>British innovation at its best.</p>
<div class="embed-container">
<iframe width="480" height="360" src="http://www.kickstarter.com/projects/1081571316/rhino-shield-the-impact-resistant-screen-protector/widget/video.html" frameborder="0"></iframe>
</div>
<p><a href="http://alexbilbie.com/2013/02/rhino-shield/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Tell SELinux to let PHP connect to a remote MySQL databasehttp://alexbilbie.com/2013/02/selinux-php-mysqlMon, 18 Feb 2013 00:00:00 +0000Alex Bilbie
<p>I’ve just wasted two hours trying to work out why I couldn’t connect to a remote MySQL database server from PHP, but connecting on the command line works fine on a RHEL6 box.</p>
<p>Turns out it was effin’ SELinux again (<a href="http://alexbilbie.com/2013/02/making-apache-selinux-play-nice/">see previous woes here</a>).</p>
<p>Setting the following values (as root) makes it all suddenly work fine:</p>
<pre><code data-language="shell">setsebool -P httpd_can_network_connect 1
setsebool -P httpd_can_network_connect_db 1
</code></pre>
<p><a href="http://alexbilbie.com/2013/02/selinux-php-mysql/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
When @alexbilbie met @twitterhttp://alexbilbie.com/2013/02/twitter-archiveThu, 14 Feb 2013 00:00:00 +0000Alex Bilbie
<p>
Tonight I discovered I now have access to my Twitter archive. Here are some gems I've found from my first year of tweeting (2008).
</p>
<p>
My first ever tweet, how dull:
</p>
<blockquote class="twitter-tweet"><p>On the computer in the art room</p>&mdash; Alex Bilbie (@alexbilbie) <a href="https://twitter.com/alexbilbie/status/454042412">November 29, 2007</a></blockquote>
<p>
I still haven't finished this project:
</p>
<blockquote class="twitter-tweet"><p>Started work on something I've been wanting to do for a while just for kicks - London Underground travel planning in PHP and jQuery</p>&mdash; Alex Bilbie (@alexbilbie) <a href="https://twitter.com/alexbilbie/status/791828044">April 18, 2008</a></blockquote>
<p>
There still isn't anything worth renting:
</p>
<blockquote class="twitter-tweet"><p>Just joined lovefilm.com (UK Netflix) - wtf do I rent?</p>&mdash; Alex Bilbie (@alexbilbie) <a href="https://twitter.com/alexbilbie/status/793624529">April 21, 2008</a></blockquote>
<p>
There is a reason I never got any homework done on time:
</p>
<blockquote class="twitter-tweet"><p>Oh shit I've missed House</p>&mdash; Alex Bilbie (@alexbilbie) <a href="https://twitter.com/alexbilbie/status/796234539">April 24, 2008</a></blockquote>
<blockquote class="twitter-tweet"><p>My mother recorded House. Panic over &lt;3</p>&mdash; Alex Bilbie (@alexbilbie) <a href="https://twitter.com/alexbilbie/status/796238267">April 24, 2008</a></blockquote>
<blockquote class="twitter-tweet"><p>I love House</p>&mdash; Alex Bilbie (@alexbilbie) <a href="https://twitter.com/alexbilbie/status/796257363">April 24, 2008</a></blockquote>
<p>
#fail
</p>
<blockquote class="twitter-tweet"><p>Put some quiche in the microwave, hit 'cook' then entered my debit card pin number instead of 30 seconds</p>&mdash; Alex Bilbie (@alexbilbie) <a href="https://twitter.com/alexbilbie/status/803173906">May 4, 2008</a></blockquote>
<p>
Have they fixed the memory leak yet?
</p>
<blockquote class="twitter-tweet"><p>Firefox has gotten soooo slow lately :S</p>&mdash; Alex Bilbie (@alexbilbie) <a href="https://twitter.com/alexbilbie/status/806569478">May 8, 2008</a></blockquote>
<p>
I've owned non-iPhones before?
</p>
<blockquote class="twitter-tweet"><p>I need a new mobile. My trusted Sony Erricson w810i has nearly had it :(</p>&mdash; Alex Bilbie (@alexbilbie) <a href="https://twitter.com/alexbilbie/status/826347642">June 3, 2008</a></blockquote>
<p>
Better
</p>
<blockquote class="twitter-tweet"><p>I can has iPhone</p>&mdash; Alex Bilbie (@alexbilbie) <a href="https://twitter.com/alexbilbie/status/920227958">September 13, 2008</a></blockquote>
<p>
To university!
</p>
<blockquote class="twitter-tweet"><p>A fresher should not have to be up this early :-/</p>&mdash; Alex Bilbie (@alexbilbie) <a href="https://twitter.com/alexbilbie/status/926964349">September 19, 2008</a></blockquote>
<blockquote class="twitter-tweet"><p>At my first ever house party lol</p>&mdash; Alex Bilbie (@alexbilbie) <a href="https://twitter.com/alexbilbie/status/959666483">October 14, 2008</a></blockquote>
<blockquote class="twitter-tweet"><p>It's 4 in the morning and some fucks are playing music so loudly in A block I can hear it anywhere in my flat. I really want to sleep.</p>&mdash; Alex Bilbie (@alexbilbie) <a href="https://twitter.com/alexbilbie/status/1042960329">December 7, 2008</a></blockquote>
<p>
How times have changed.
</p>
<blockquote class="twitter-tweet"><p>Vista is really playing up on my laptop so I'm debating downloading 7 beta 1 next week and starting afresh. Reviews say it's very stable.</p>&mdash; Alex Bilbie (@alexbilbie) <a href="https://twitter.com/alexbilbie/status/1082187511">December 28, 2008</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p><a href="http://alexbilbie.com/2013/02/twitter-archive/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; Did Vader screw up the invasion of Hoth?http://www.wired.com/dangerroom/2013/02/battle-of-hoth/Tue, 12 Feb 2013 00:00:00 +0000Alex Bilbie
<blockquote>
<p>When Vader enters the Hoth System with the Imperial Fleet, he’s holding a winning hand. What follows next is a reminder of two military truths that apply in our own time and in our own galaxy: Don’t place unaccountable religious fanatics in wartime command, and never underestimate a hegemonic power’s ability to miscalculate against an insurgency.</p>
</blockquote>
<p><a href="http://alexbilbie.com/2013/02/12/did-vader-screw-up-the-invasion-of-hoth/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; Visual timeline of the One Ringhttp://lotrproject.com/blog/2013/01/20/visual-timeline-of-the-one-ring/Sun, 10 Feb 2013 00:00:00 +0000Alex Bilbie
<figure>
![http://lotrproject.com/blog/wp-content/uploads/2013/01/timelineonering.jpg](http://lotrproject.com/blog/wp-content/uploads/2013/01/timelineonering.jpg)
</figure>
<p>This would sit very nicely next to my <a href="http://xkcd.com/657/">XKCD Movie Narrative Chart</a> post I got for Christmas.</p>
<p><a href="http://alexbilbie.com/2013/02/10/visual-timeline-of-the-one-ring/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; It might not get weirder than thishttps://sites.google.com/site/sophieinnorthkorea/Sun, 10 Feb 2013 00:00:00 +0000Alex Bilbie
<p>Fascinating account by Eric Schmidt’s daughter Sophie about their trip to North Korea.</p>
<blockquote>
<p>Top Level Take-aways:</p>
<ol>
<li>Go to North Korea if you can. It is very, very strange.</li>
<li>If it is January, disregard the above. It is very, very cold.</li>
<li>Nothing I’d read or heard beforehand really prepared me for what we saw.</li>
</ol>
</blockquote>
<p><a href="http://alexbilbie.com/2013/02/it-might-not-get-weirder-than-this/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; What happened to LEGO?http://therealityprose.wordpress.com/2013/01/17/what_happened_with_lego/Sat, 09 Feb 2013 00:00:00 +0000Alex Bilbie
<p>So LEGO is expensive to adults because it was free when we were kids. Damn.</p>
<p><a href="http://alexbilbie.com/2013/02/09/what-happened-to-lego/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; Star Wars spinoff films announcedhttp://starwars.com/news/new-spinoff-films-set-to-expand-the-star-wars-galaxy.htmlWed, 06 Feb 2013 00:00:00 +0000Alex Bilbie
<p>2015 can’t come soon enough.</p>
<p><a href="http://alexbilbie.com/2013/02/star-wars-spinoff-films-announced/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Making Apache and SELinux play nicehttp://alexbilbie.com/2013/02/selinux-apacheWed, 06 Feb 2013 00:00:00 +0000Alex Bilbie
<p>We spent far too many hours trying to solve a problem on a brand new RHEL6 box today. Basically Apache would only return 403 errors no matter what file we tried to hit up in a browser. The error log wasn’t much help either, even on the highest log level.</p>
<p>It turned out that SELinux was preventing Apache from accessing the files. The command to get around this is:</p>
<pre><code data-language="shell">chcon -Rv -t httpd_sys_content_t /path/to/web/root</code></pre>
<p>I don’t know much about SELinux but as I understand it that command should be persistant across server reboots. Also it seems you don’t need to reapply it each time you create a new file in the webroot either.</p>
<p>There is some useful infomation about working with SELinux on this <a href="http://wiki.centos.org/HowTos/SELinux">CentOS wiki page</a>.</p>
<p><a href="http://alexbilbie.com/2013/02/making-apache-selinux-play-nice/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; So what did you learn from the iPhone?http://www.bbc.co.uk/programmes/p014f43kFri, 01 Feb 2013 00:00:00 +0000Alex Bilbie
<blockquote>
When repeatedly asked what his company RIM Europe have learned from Apple in producing the new Blackberry 10, which is launched today, managing director Stephen Bates refuses to answer.
</blockquote>
<p>
Dammit man, just answer the question.
</p>
<p><a href="http://alexbilbie.com/2013/02/so-what-did-you-learn-from-the-iphone/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; BBC News Lab: Linked datahttp://www.bbc.co.uk/blogs/internet/posts/BBC-News-LabFri, 01 Feb 2013 00:00:00 +0000Alex Bilbie
<p>A fascinating blog post on the BBC Internet Blog about how they’re using semantic <a href="http://linkeddata.org/">linked data</a> as a fundamental part of their data architecture. There is <a href="http://www.bbc.co.uk/blogs/bbcinternet/2010/07/the_world_cup_and_a_call_to_ac.html">another great article here</a> which talks about their first experiments with linked data for the 2010 World Cup.</p>
<p>It’s a shame we so rarely ever get to play with their experiments though. Having said that there are a few of their older projects avaiable on the <a href="http://www.bbc.co.uk/rd/labs">R&amp;D Labs page</a>.</p>
<p><a href="http://alexbilbie.com/2013/02/bbc-new-lab-linked-data/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
#hmvXFactorFiringhttp://alexbilbie.com/2013/01/hmvxfactorfiringThu, 31 Jan 2013 09:00:00 +0000Alex Bilbie
<blockquote class="twitter-tweet tw-align-center"><p>The HMV social media team has just been fired, so they decided to tweet about it! Deleted now, but PRINT SCREEN works! <a href="http://t.co/A3cATPwJ" title="http://twitter.com/hirstycapital/status/296995595850240000/photo/1">twitter.com/hirstycapital/…</a></p>&mdash; Hirsty's Daily Dose (@hirstycapital) <a href="https://twitter.com/hirstycapital/status/296995595850240000">January 31, 2013</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<hr>
<p>
<strong>Update:</strong> here's all the tweets that were sent
</p>
<figure>
<img src="http://i.imgur.com/0PUZTT0.jpg" style="margin:0 auto;width:429px;display: block;">
</figure>
<p><a href="http://alexbilbie.com/2013/01/hmvxfactorfiring/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; J.J. Abrams to direct Star Wars: Episode VIIhttp://starwars.com/news/star-wars-is-being-kick-started-with-dynamite-jj-abrams-to-direct-star-wars-episode-vii.htmlSun, 27 Jan 2013 00:00:00 +0000Alex Bilbie
<p>I’m very excited about this - I love Abrams’ previous work on Fringe, Alias, Star Trek and Cloverfield.</p>
<p>Having said this whole Disney/LucasFilm/Bad Robot relationship thing is a bit unnerving. I really hope they don’t do anything stupid and start mixing universes and come out with something like “Episode VII: Buzz Lightyear to the Rescue”.</p>
<p>“Episode VII: Pirates of the Dagobah System” might be cool though.</p>
<figure>
![http://i.imgur.com/wiTAEdG.jpg](http://i.imgur.com/wiTAEdG.jpg)
</figure>
<p><a href="http://alexbilbie.com/2013/01/jj-abrams-to-direct-star-wars-7/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; Hype Machine: Dive into 5 years of music historyhttp://blog.hypem.com/2013/01/time-machine-dive-into-5-years-of-music-history/Sun, 27 Jan 2013 00:00:00 +0000Alex Bilbie
<blockquote>
<p>We recovered over <a href="http://hypem.com/popular/week:Oct-22-2007">5 years of weekly Popular charts</a> on the site (that is an immense 272 weeks!), starting from the week of Oct 22 2007, the first full week that the site was live</p>
</blockquote>
<p><a href="http://hypem.com">Hype Machine</a> has been my go to place to find new (and rediscover old) music for the last few years. This <a href="http://hypem.com/popular/week:Oct-22-2007">new chart browser</a> is awesome - I’ve already discovered some great remixes of some of my favourite songs.</p>
<p><a href="http://alexbilbie.com/2013/01/five-years-of-music-history/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; Actual Facebook Graph searcheshttp://actualfacebookgraphsearches.tumblr.com/Wed, 23 Jan 2013 00:00:00 +0000Alex Bilbie
<p>Some of my favourites:</p>
<blockquote>“Current employees of Tesco who like horses”</blockquote>
<blockquote>“Mothers of Catholics from Italy who like Durex”</blockquote>
<p><a href="http://alexbilbie.com/2013/01/actual-facebook-graph-searches/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; Star Wars: Machete Orderhttp://www.nomachetejuggling.com/2011/11/11/the-star-wars-saga-suggested-viewing-order/Mon, 21 Jan 2013 00:00:00 +0000Alex Bilbie
<p>I still remember watching the 1997 Special Edition releases at the cinema with my Dad and then dressing up as a jedi to go and see The Phantom Menace with my friends when I was 9.</p>
<p>Having recently watched Star Wars in the “machete order” I agree with much of this article and I think it’ll be the way I introduce my kids to Star Wars one day.</p>
<p>It’s worth mentioning that I also really enjoyed the 2008 Star Wars Clone Wars film and the CGI TV series; the most recent season was very political (and violent) and for a “kids” show I found myself looking forward to waiting for the next episode each week. That and the animation was some of the best I’ve ever seen.</p>
<p><a href="http://alexbilbie.com/2013/01/star-wars-machete-order/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; Hands-on with Graph Searchhttp://www.theverge.com/2013/1/15/3880004/facebook-graph-search-hands-onWed, 16 Jan 2013 00:00:00 +0000Alex Bilbie
<p>
The Verge, who are quickly becoming my favourite technology news website, have got a hands-on video with the new Facebook Graph Search.
</p>
<div class="embed-container">
<script src="http://player.ooyala.com/iframe.js#pbid=dcc84e41db014454b08662a766057e2b&ec=RsdzhmODq8dhc-1BxUkAnBzT4J-g8OVB"></script>
</div>
<p>
It looks pretty cool but I can't imagine myself wanting to search the web from inside Facebook, especially as about a centimetre on my screen above this new universal search bar there is Chrome's own universal search bar (which I have searching <a href="https://duckduckgo.com/">Duck Duck Go</a>).
</p>
<p>
It would be great if Facebook open sourced the natural language parser that they've designed - I can think of loads of applications where I would want to use it, plus when combined with the new <a href="https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html">Web Speech API</a> support that has just <a href="http://chrome.blogspot.co.uk/2013/01/hello-browser.html">landed in Chrome 25</a> I've got dreams of having my own Tony Stark-esque Jarvis system.
</p>
<p><a href="http://alexbilbie.com/2013/01/hands-on-with-graph-search/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Facebook Graph Search...in an ideal worldhttp://alexbilbie.com/2013/01/facebook-graph-search-in-an-ideal-worldWed, 16 Jan 2013 00:00:00 +0000Alex Bilbie
<div class="embed-container">
<iframe src="http://www.youtube.com/embed/ldwLByPO7cI" frameborder="0" allowfullscreen></iframe>
</div>
<p>Funny stuff by my friend <a href="http://www.jonathancresswell.co.uk/">Jonathan Cresswell</a></p>
<p><a href="http://alexbilbie.com/2013/01/facebook-graph-search-in-an-ideal-world/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
The staff at Jessops would like to thank you...http://alexbilbie.com/2013/01/jessops-windowTue, 15 Jan 2013 00:00:00 +0000Alex Bilbie
<blockquote class="twitter-tweet tw-align-center"><p>Jessops' window in Liverpool. Ouch. (pic c/o Dave the pap) <a href="http://t.co/IMj8nDvf" title="http://twitter.com/7streets/status/291255361795657729/photo/1">twitter.com/7streets/statu…</a></p>&mdash; Sevenstreets (@7streets) <a href="https://twitter.com/7streets/status/291255361795657729" data-datetime="2013-01-15T18:47:45+00:00">January 15, 2013</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p><a href="http://alexbilbie.com/2013/01/jessops-would-like-to-thank-you/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Farewell HMVhttp://alexbilbie.com/2013/01/farewell-hmvTue, 15 Jan 2013 00:00:00 +0000Alex Bilbie
<p>Simon Fox, former chief executive of HMV <a href="http://www.telegraph.co.uk/finance/newsbysector/retailandconsumer/9446010/HMV-appoints-former-Jessops-chief-Trevor-Moore-to-replace-Simon-Fox.html">speaking to the Telegraph last year</a>:</p>
<blockquote>
<p>I am proud to be leaving HMV with a profitable future secured. The appointment of Trevor Moore means that I will be leaving the company in safe hands.</p>
<p>…</p>
<p>He has the right skills and experience to lead HMV in the coming years.</p>
</blockquote>
<p>Trevor Moore used to be the chief executive of Jessops (which went into administration last week), and a senior executive at Threshers and Coffee Republic (both of which went into administration in 2009).</p>
<p>Today it was announced the UK highstreet retailer HMV was going into administration.</p>
<p>If I worked for a company that was considering bringing Moore onto their board of execs I’d be pretty scared.</p>
<p><a href="http://alexbilbie.com/2013/01/farewell-hmv/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; The Verge's coverage of Qualcomm's CES keynotehttp://www.theverge.com/2013/1/8/3850056/qualcomms-insane-ces-2013-keynote-pictures-tweetsTue, 08 Jan 2013 00:00:00 +0000Alex Bilbie
<p>
The Verge have put together a great article summing up Qualcomm's insane CES keynote. The video at the end rounds it off brilliantly.
</p>
<p><a href="http://alexbilbie.com/2013/01/verges-coverage-of-qualcomm-ces-keynote/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; Power surges in Britain caused by millions of people making teahttp://www.bbc.co.uk/britainfromabove/stories/people/teatimebritain.shtmlMon, 07 Jan 2013 00:00:00 +0000Alex Bilbie
<p>Amazing.</p>
<p><a href="http://alexbilbie.com/2013/01/teatime-britain/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
A tour of the ISShttp://alexbilbie.com/2013/01/tour-of-the-iss-testSun, 06 Jan 2013 00:00:00 +0000Alex Bilbie
<p>
This morning I came across this amazing video in which a departing crew of the International Space Station give a tour of the craft. It's 25 minutes long but it is well worth watching.
</p>
<p>
My favorite quote from the video is:
</p>
<blockquote>
I've not sat down in six months!
</blockquote>
<div class="embed-container">
<iframe src="http://www.youtube.com/embed/doN4t5NKW-k" frameborder="0" allowfullscreen></iframe>
</div>
<p><a href="http://alexbilbie.com/2013/01/tour-of-the-iss/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
&rarr; Living with HTTPShttp://www.imperialviolet.org/2012/07/19/hope9talk.htmlSun, 06 Jan 2013 00:00:00 +0000Alex Bilbie
<p>A must read</p>
<p><a href="http://alexbilbie.com/2013/01/living-with-https/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
A week without Facebookhttp://alexbilbie.com/2012/12/a-week-without-facebookSun, 30 Dec 2012 00:00:00 +0000Alex Bilbie
<p>A week ago today I deactivated my Facebook account. It was something I’ve been considering since a friend mentioned recently how frustrated he gets when he get’s invited to events over Facebook and how noone calls or texts him anymore, and I feel the same. I just don’t feel “social” on Facebook. I get far more digital interaction with friends on Twitter, and that has been the case for a while.</p>
<p>So a week later how am I finding it? Day to day I don’t feel like I’m missing either the site or I’m out of contact with people. I removed the apps from my iPhone so I don’t get any notifications; the apps were actually hidden anyway in a folder called “Social” on the springboard, whereas Tweetbot has always been one of the 4 blessed apps on the dock which shows where my priorities really are anyway.</p>
<p>When I’m at my laptop though it’s much harder - I catch myself starting to type “cmd + t” followed by “f a” in Chrome. Frustratingly it’s actually quite difficult to completely remove all mention of a site from your history in Chrome. In Firefox there is an option to remove all visits by domain but I had to manually do this myself by editing the history file under <code class="highlighter-rouge">~/Library/Application Support/Google/Chrome/Default</code> with a SQLite editor.</p>
<p>Another frustration is when I discover new websites that require me to sign-in via Facebook. In part I feel that maybe I should just setup a dummy Facebook account so I can use these sites but then when I think about it I don’t really care enough about these sites anyway to bother interacting with them in a personalised manner.</p>
<p>So do I feel better being Facebook free? Yeah I guess so, I’ve certainly texted people a lot more to see if they’ve had a pleasant Christmas rather than just observing their Facebook status’ that say they’ve had a good one.</p>
<p>Here’s to a Facebook free 2013. Happy new year!</p>
<p><a href="http://alexbilbie.com/2012/12/a-week-without-facebook/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
2012http://alexbilbie.com/2012/12/two-thousand-and-twelveTue, 25 Dec 2012 00:00:00 +0000Alex Bilbie
<p>On reflection 2012 seems to have gone immensely quickly. Here are some of my highlights:</p>
<p>In February I helped organise the annual <a href="http://devcsi.ukoln.ac.uk/">DevCSI</a> <a href="http://dev8d.org">Dev8D</a> conference and ended up doing my <a href="https://speakerdeck.com/alexbilbie/introduction-to-html5-and-css3">HTML5 talk three</a> times due to popular demand. I also helped organise and <a href="https://speakerdeck.com/alexbilbie/introduction-to-mongodb">spoke about MongoDB</a> at the annual UK leg of the CodeIgniter.</p>
<p>In May I saw the end of my degree (finally!) and I spoke (and helped out at) DevCSI’s new conference, <a href="http://devcsi.ukoln.ac.uk/past-events/dev8ed/">Dev8ed</a>.</p>
<p>In June I visited to my friend in Berlin and spent a few days exploring the city.</p>
<p>I July I started my new research project, <a href="http://linkey.blogs.lincoln.ac.uk">Linkey</a> which is looking at the use of OAuth in higher education institutions and how it can be made to work in a corporate environment run on proprietary software.</p>
<p>In August I spent a few days away in the rolling hills of Shropshire with friends which was wonderfully relaxing, appropriately boozy and we ate like kings. I also moved into my first ever flat by myself.</p>
<p>In September, for the first time in 18 years I didn’t have to return to studying.</p>
<p>In early November I visited the USA for the first time with Dave Tarrant from the University of Southampton to take part in the international Scholarly Infrastructure Technical Summit (S.I.T.S) meeting. We also spent a few days up in the Colorado mountains at David Flanders’ parents lodge 8500ft above sea level. Amazing.</p>
<p>Finally just this month I was accepted to talk at the <a href="http://conference.phpne.org.uk/">PHP North East conference</a> next March about API driven development.</p>
<p>Looking forward to 2013, I’m hoping to do some more travelling; both America and Scandanavia are on the table. I’m planning on starting my own company with my friend Nick; more on that soon. I can’t wait.</p>
<p><a href="http://alexbilbie.com/2012/12/two-thousand-and-twelve/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
I'm speaking at PHPNE Conference 2013http://alexbilbie.com/2012/12/phpne-talkTue, 18 Dec 2012 00:00:00 +0000Alex Bilbie
<p>I’m very excited to say that my talk proposal entitled “AAPI Driven Development: Eating Your Own Dog Food” has been accepted for <a href="http://conference.phpne.org.uk/">PHPNE Conference 2013</a> on the 19th of March 2013 in Newcastle Upon Tyne.</p>
<p>At the time of writing there 44 tickets still available <a href="https://phpne13.eventbrite.co.uk/">so go get one</a>.</p>
<p>I can’t wait :D</p>
<p><a href="http://alexbilbie.com/2012/12/phpne-talk/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
PHP 5.3/5.4 for OS X 10.6/10.7/10.8 as binary packagehttp://alexbilbie.com/2012/12/php-for-osxMon, 10 Dec 2012 00:00:00 +0000Alex Bilbie
<p>The wonderful people at <a href="http://liip.ch/">Liip</a> have created <a href="http://php-osx.liip.ch/">binary packages for PHP 5.3, 5.4 and 5.5 for OS X Snowy, Lion and Mountail Lion</a>.</p>
<p>Install PHP 5.4 is as simple as running the following in your terminal:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl -s http://php-osx.liip.ch/install.sh | bash -s 5.4
</code></pre></div></div>
<p>To make this new version of PHP your system default, edit your system path so that /usr/local/php5/bin is before wherever the default PHP location is (find that out with <code class="highlighter-rouge">which php</code>).</p>
<p>Remember to read the install full notes on the web page.</p>
<p><a href="http://php-osx.liip.ch/">➝ http://php-osx.liip.ch/</a></p>
<p><a href="http://alexbilbie.com/2012/12/php-for-osx/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
MongoQB updated for Mongo PECL 1.3http://alexbilbie.com/2012/11/mongoqb-updateFri, 30 Nov 2012 00:00:00 +0000Alex Bilbie
<p>I have updated <a href="https://github.com/alexbilbie/MongoQB">MongoQB</a> to support the new MongoDB PECL update (<a href="http://pecl.php.net/package/mongo/1.3.0">v1.3</a>) which introduces some big changes to the base classes as described <a href="http://blog.mongodb.org/post/36666163412/introducing-mongoclient">in this blog post on the MongoDB blog</a>.</p>
<p>The only big change for developers using the library is you don’t need to pass the <code class="highlighter-rouge">persist</code> and <code class="highlighter-rouge">persist_key</code> keys into the connection array.</p>
<p><a href="http://alexbilbie.com/2012/11/mongoqb-update/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Which Bond villain plan would have worked?http://alexbilbie.com/2012/11/which-bond-villians-plan-would-have-workedThu, 29 Nov 2012 00:00:00 +0000Alex Bilbie
<p>Amusing article by vulture.com - <a href="http://www.vulture.com/2012/11/which-james-bond-villain-plan-would-have-worked.html">http://www.vulture.com/2012/11/which-james-bond-villain-plan-would-have-worked.html</a></p>
<p><a href="http://alexbilbie.com/2012/11/which-bond-villians-plan-would-have-worked/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Hawk: a new HTTP authentication schemehttp://alexbilbie.com/2012/11/hawk-a-new-http-authentication-schemeWed, 28 Nov 2012 00:00:00 +0000Alex Bilbie
<p><a href="http://hueniverse.com/">Eran Hammer</a> (formerly editor of the OAuth specifications) has introduced a new HTTP authentication scheme called <a href="https://github.com/hueniverse/hawk">Hawk</a>.</p>
<p>Hawk is described as a HTTP authentication scheme using a message authentication code (MAC) algorithm to provide partial HTTP request cryptographic verification. It is related to his other new project <a href="https://github.com/hueniverse/oz">Oz</a> which is a web authorisation protocol promoted as an alternative to OAuth. Eran has made it clear that he doesn’t want to write a new specification after the leaving the OAuth working group and so he is intending to describe Hawk (and Oz) through code and leave it up to someone else to write a formal specification.</p>
<h3 id="what-is-hawk">What is Hawk?</h3>
<p>An overview of Hawk is provided in the <a href="https://github.com/hueniverse/hawk/blob/master/README.md#introduction">README file in the repository</a>:</p>
<blockquote>
<p>Hawk is an HTTP authentication scheme providing a method for making authenticated HTTP requests with partial cryptographic verification of the request, covering the HTTP method, request URI, and host.</p>
<p>Similar to the HTTP Basic access authentication scheme, the Hawk scheme utilizes a set of client credentials which include an identifier and key. However, in contrast with the Basic scheme, the key is never included in authenticated requests but is used to calculate a request MAC value which is included instead.</p>
<p>The Hawk scheme requires the establishment of a shared symmetric key between the client and the server, which is beyond the scope of this module. Typically, the shared credentials are established via an initial TLS-protected phase or derived from some other shared confidential information available to both the client and the server.</p>
<p>The primary design goals of this mechanism are to:</p>
<ul>
<li>simplify and improve HTTP authentication for services that are unwilling or unable to employ TLS for every request,</li>
<li>secure the shared credentials against leakage when sent over a secure channel to the wrong server (e.g., when the client uses some form of dynamic configuration to determine where to send an authenticated request), and</li>
<li>mitigate the exposure of credentials sent to a malicious server over an unauthenticated secure channel due to client failure to validate the server’s identity as part of its TLS handshake.</li>
</ul>
<p>Unlike the HTTP Digest authentication scheme, Hawk provides limited protection against replay attacks which does not require prior interaction with the server. Instead, the client provides a timestamp which the server can use to prevent replay attacks outside a narrow time window. Also unlike Digest, this mechanism is not intended to protect the key itself (user’s password in Digest) because the client and server both have access to the key material in the clear.</p>
</blockquote>
<p>To clarify, MAC (Message Authentication Code) is a cryptographic string that is sent alongside a message (such as an HTTP request) to detect tampering and forgery. Both the sender and the receiver will use the same shared secret to generate and verify the MAC. The OAuth 1.0 specification used MAC signatures but these were removed in OAuth 2.0.</p>
<h3 id="protocol-example">Protocol Example</h3>
<p>To demonstrate how Hawk authentication works there is a <a href="https://github.com/hueniverse/hawk/blob/master/README.md#protocol-example">protocol example</a>:</p>
<p>The client attempts to access a protected resource without authentication, sending the following HTTP request to
the resource server:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>GET /resource/1?b=1&amp;a=2 HTTP/1.1
Host: 127.0.0.1:8000
</code></pre></div></div>
<p>The resource server returns the following authentication challenge:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>HTTP/1.1 401 Unauthorized
WWW-Authenticate: Hawk
</code></pre></div></div>
<p>The client has previously obtained a set of <strong>Hawk</strong> credentials for accessing resources on the “http://example.com/”
server. The <strong>Hawk</strong> credentials issued to the client include the following attributes:</p>
<ul>
<li>Key identifier: dh37fgj492je</li>
<li>Key: werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn</li>
<li>Algorithm: hmac-sha-256</li>
</ul>
<p>The client generates the authentication header by calculating a timestamp (e.g. the number of seconds since January 1,
1970 00:00:00 GMT) and constructs the normalized request string (newline separated values):</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1353832234
GET
/resource/1?b=1&amp;a=2
127.0.0.1
8000
some-app-data
</code></pre></div></div>
<p>The request MAC is calculated using the specified algorithm “hmac-sha-256” and the key over the normalized request string.
The result is base64-encoded to produce the request MAC:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/uYWR6W5vTbY3WKUAN6fa+7p1t+1Yl6hFxKeMLfR6kk=
</code></pre></div></div>
<p>The client includes the <strong>Hawk</strong> key identifier, timestamp, and request MAC with the request using the HTTP “Authorization”
request header field:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>GET /resource/1?b=1&amp;a=2 HTTP/1.1
Host: 127.0.0.1:8000
Authorization: Hawk id="dh37fgj492je", ts="1353832234", ext="some-app-data", mac="/uYWR6W5vTbY3WKUAN6fa+7p1t+1Yl6hFxKeMLfR6kk="
</code></pre></div></div>
<p>The server validates the request by calculating the request MAC again based on the request received and verifies the validity and scope of the <strong>Hawk</strong> credentials. If valid, the server responds with the requested resource.</p>
<h3 id="security-considerations">Security Considerations</h3>
<p>There are a number of security considerations to consider which can be seen here <a href="https://github.com/hueniverse/hawk#security-considerations">https://github.com/hueniverse/hawk#security-considerations</a>.</p>
<h3 id="hawk-vs-oauth">Hawk vs. OAuth</h3>
<p>The Hawk documentation says that is can be used for client to server authentication but I think it would also make an easier to implement (than OAuth) authentication protocol if you are implementing machine to machine authentication.</p>
<p>For delegating access to protected resources then the documentation recommends <a href="https://github.com/hueniverse/oz">Oz</a> as alternative to OAuth. I will review Oz in another post.</p>
<h2 id="php-implementation">PHP Implementation</h2>
<p>I’ve had a go at implementing Hawk in PHP - <a href="https://github.com/alexbilbie/PHP-Hawk">https://github.com/alexbilbie/PHP-Hawk</a>.</p>
<h3 id="client-usage">Client Usage</h3>
<p>Assume you’re hitting up the following endpoint:</p>
<p><code class="highlighter-rouge">https://api.example.com/user/123?foo=bar</code></p>
<p>And the API server has given you the following credentials:</p>
<ul>
<li>Key - <code class="highlighter-rouge">ghU3QVGgXM</code></li>
<li>Secret - <code class="highlighter-rouge">5jNP12yT17Hx5Md3DCZ5pGI5sui82efX</code></li>
</ul>
<p>To generate the header run the following:</p>
<pre><code data-language="php">$key = 'ghU3QVGgXM';
$secret = '5jNP12yT17Hx5Md3DCZ5pGI5sui82efX';
$hawk = Hawk::generateHeader($key, $secret, 'GET', 'https://api.example.com/user/123?foo=bar');
</code></pre>
<p>You can also pass in additional application specific data with an <code class="highlighter-rouge">ext</code> key in the array.</p>
<p>Once you’ve got the Hawk string include it in your HTTP request as an <code class="highlighter-rouge">Authorization</code> header.</p>
<h3 id="server-usage">Server Usage</h3>
<p>On your API endpoint if the incoming request is missing an authorization header then return the following two headers:</p>
<pre>
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Hawk
</pre>
<p>If the request does contain a Hawk authorization header then process it like so:</p>
<pre><code data-language="php">$hawk = ''; // the authorisation header
// First parse the header to get the parts from the string
$hawk_parts = Hawk::parseHeader($hawk);
// Then with your own function, get the secret for the key from the database
$secret = getSecret($hark_parts['id']);
// Now validate the request
$valid = Hawk::verifyHeader($hawk, array(
'host' =&gt; 'api.example.com',
'port' =&gt; 443,
'path' =&gt; '/user/123',
'method' =&gt; 'GET'
), $secret); // return true if the request is valid, otherwise false
</code></pre>
<p><a href="http://alexbilbie.com/2012/11/hawk-a-new-http-authentication-scheme/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
What maketh the manhttp://alexbilbie.com/2012/11/27/what-maketh-the-manTue, 27 Nov 2012 00:00:00 +0000Alex Bilbie
<p>When I relaunched this blog I intended to not just talk about technology and code but also some other interests of mine.</p>
<blockquote>
<p>“And now for something completely different…”</p>
</blockquote>
<p>This evening I downloaded the new iPad app from luxury online retailer <a href="http://mrporter.com">Mr Porter</a> entitled <a href="https://itunes.apple.com/gb/app/mr-porter-the-tux/id575880306?mt=8">The Tux</a> (warning: 1.4GB download). The app is elegantly put together and features micro video interviews with fashion aficionados, cocktail making lessons with top New York barmen and guides on how to wear a tuxedo in a traditional manner and how to add a modern twist.</p>
<p>Having read through the app I’ve finally made the decision that in the new year I’m going to invest some money in buying a new tuxedo. I bought my current tuxedo about 18 months ago from the UK high street retailer Next as the jacket was the only one that I found (within my budget) with a shawl collar and a comfortable slim fitting cut. This suit is actually my second tuxedo, my first being one I bought reasonably cheaply in a sale from ASOS back in 2009.</p>
<p>I actually get a surprising amount of wear from my current tuxedo as I can count about 8 occasions in the last 12 months which have required black tie attire. The suit was definitely worth the money that I paid, both in terms of the upfront cost and the minor adjustments I had to it at the tailors.</p>
<p>So what do I want from a new tuxedo? Anyone who knows me personally is aware that I have a ridiculously large amount of clothes and they wouldn’t be surprised to hear that I’ve already put a fair bit of thought into this.</p>
<p>First of all I’m fairly pale skinned with dirty-blonde hair and I think that I should avoid a black suit going forward. Midnight to navy blue is the obvious choice as I’ve yet to see anyone pull off a burgundy or grey tuxedo well.</p>
<p>Second I do like shawl collars. Fewer men wear shawl collar jackets, opting for peak or notch lapels and I like to have something a bit different. I love Tom Ford’s oversized lapels on his suits, especially the grosgrain shawl lapels on his AW12 mens collection.</p>
<p>Next I want a new dress shirt. I like dress shirts that have a ribbed bib, I already have a nice one from the Jil Sander x Uniqlo collection, but I’ve always wanted one with cufflinks. I also don’t like black buttons, preferring hidden or white buttons.</p>
<p>Finally, I’d like to experiment with some accessories, and I’m inspired by items such as <a href="http://www.mrporter.com/product/197786">this buttonhole</a> by Lanvin and <a href="http://www.mrporter.com/product/312516">these gorgeous slippers</a> by Jimmy Choo or these <a href="http://www.asos.com/ASOS/ASOS-Velvet-Tassel-Loafers-With-Leather-Sole/Prod/pgeproduct.aspx?iid=2174212">loafers by ASOS</a>.</p>
<p>Whilst I certainly can’t afford (at the moment…he says longingly) a Tom Ford or Burberry tuxedo I will hopefully come across something in the new year that I can invest in, either from a high end high street retailer or a boutique vintage shop.</p>
<p>Whilst digging around for inspiration for this post I came across this fantastic quote which I’ve heard before but didn’t know who said it:</p>
<blockquote>
<p>What is it about wearing a tuxedo or that little black dress, that makes us feel confident, beautiful, splendid, even invincible?</p>
<p>We put on formal wear and suddenly we become extraordinary.</p>
<p>On the days when you feel low and invisible, why not try this on for size: imagine you are wearing a fantastic tailored tuxedo or a stunning formal gown.</p>
<p>And then proceed with your day.</p>
<p><em>- Vera Nazarian</em></p>
</blockquote>
<p><a href="http://alexbilbie.com/2012/11/27/what-maketh-the-man/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Exclude objects with .gitattributeshttp://alexbilbie.com/2012/11/exclude-objects-with-gitattributesMon, 26 Nov 2012 00:00:00 +0000Alex Bilbie
<p>Not many people know about the incredibly useful <code class="highlighter-rouge">.gitattributes</code> file which can be used to tell git how to handle certain files or folders.</p>
<p>One useful use case is when you need to distribute zip/tarballs of your repository but you don’t want to share certain files or folders such as unit tests or build configuration scripts.</p>
<p>In the repository root add a new <code class="highlighter-rouge">.gitattributes</code> file and for each file or folder you want to exclude add <code class="highlighter-rouge">export-ignore</code> after it:</p>
<pre>
tests/ export-ignore
build.xml export-ignore
phpunit.xml export-ignore
</pre>
<p><a href="http://alexbilbie.com/2012/11/exclude-objects-with-gitattributes/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Miles Davis improvising on LCD Soundsystemhttp://alexbilbie.com/2012/11/miles-davis-lcd-soundsystemSat, 24 Nov 2012 00:00:00 +0000Alex Bilbie
<div class="embed-container">
<iframe src="http://www.youtube.com/embed/huEtJw7pfLk" frameborder="0" allowfullscreen></iframe>
</div>
<p>
Via <a href="http://parislemon.com/post/35928834548/laughingsquid-an-impossible-duet-miles-davis">MG Siegler</a>
</p>
<p><a href="http://alexbilbie.com/2012/11/miles-davis-lcd-soundsystem/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Introducing MongoQBhttp://alexbilbie.com/2012/11/introducing-mongoqbThu, 15 Nov 2012 00:00:00 +0000Alex Bilbie
<p>A few years ago I released a <a href="https://github.com/alexbilbie/codeigniter-mongodb-library">MongoDB library</a> for the <a href="http://codeigniter.com/">CodeIgniter</a> PHP framework which has become quite popular thanks to it’s likeness to CodeIgniter’s query builder library.</p>
<p>I’ve just spent the last week travelling and to keep myself occupied I spent some time re-architecting the library’s code; removing the framework dependancy, making it <a href="http://getcomposer.org/">Composer</a> friendly and adding a full suite of unit tests. Check out the code on Github - <a href="https://github.com/alexbilbie/MongoQB">https://github.com/alexbilbie/MongoQB</a>.</p>
<h2 id="install-via-packagist-and-composer">Install via Packagist and Composer</h2>
<p>Add the following into your composer.json file:</p>
<pre><code data-language="javascript">{
"require": {
"alexbilbie/mongoqb": "*"
}
}
</code></pre>
<p>Then run</p>
<pre><code data-language="shell">composer install
</code></pre>
<h2 id="install-via-git">Install via Git</h2>
<pre><code data-language="shell">git clone git://git@github.com:alexbilbie/MongoQB
</code></pre>
<h2 id="download-a-ziptarball">Download a zip/tarball</h2>
<p>Download the latest version:</p>
<ul>
<li><a href="https://github.com/alexbilbie/MongoQB/archive/master.zip">zip</a></li>
<li><a href="https://github.com/alexbilbie/MongoQB/archive/master.tar.gz">tar</a></li>
</ul>
<p>(Note the zip/tarball won’t include any unit tests or composer files)</p>
<h2 id="unit-tests">Unit tests</h2>
<p>To run the unit test suite make sure you have MongoDB installed locally and running with no authentication and on the default port - 27017. The library currently has 100% unit test coverage.</p>
<p>Then run:</p>
<pre><code data-language="shell">composer update --dev
cd vendor/alexbilbie/mongoqb
phpunit -c tests/phpunit.xml
</code></pre>
<h2 id="example-usage">Example usage</h2>
<h3 id="connect-to-the-database">Connect to the database</h3>
<pre><code data-language="php">$qb = \MongoQB\Builder(array(
'dsn' =&gt; 'mongodb://user:pass@localhost:27017/databaseName'
);
</code></pre>
<h3 id="insert-a-document">Insert a document</h3>
<pre><code data-language="php">$qb-&gt;insert('collectionName', [
'name' =&gt; 'Alex',
'age' =&gt; 22,
'likes' =&gt; ['whisky', 'gin']
]);
</code></pre>
<h3 id="update-a-single-document">Update a single document</h3>
<pre><code data-language="php">$qb
-&gt;where(['name' =&gt; 'Alex'])
-&gt;set([
'country' =&gt; 'UK',
'job' =&gt; 'Developer'
])
-&gt;push('likes', ['PHP', 'coffee'])
-&gt;update('collectionName');
</code></pre>
<h3 id="delete-a-single-document">Delete a single document</h3>
<pre><code data-language="php">$qb
-&gt;where(['name' =&gt; 'Alex'])
-&gt;delete('collectionName');
</code></pre>
<h3 id="search-for-matching-documents">Search for matching documents</h3>
<pre><code data-language="php">$results = $qb
-&gt;whereGt('age', 21)
-&gt;whereIn('likes', ['whisky'])
-&gt;where('country', 'UK')
-&gt;get('collectionName');
</code></pre>
<p>If you find any bugs please file a report in the <a href="https://github.com/alexbilbie/MongoQB/Issues">Issue tracker</a></p>
<p><a href="http://alexbilbie.com/2012/11/introducing-mongoqb/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Authentication in the Libraryhttp://alexbilbie.com/2012/10/authentication-in-the-libraryMon, 22 Oct 2012 00:00:00 +0000Alex Bilbie
<p>Last week, <a href="http://lncn.eu/me/pstainthorp">Paul</a> and I sat down to list the IT resources that the library offer to staff and students are and how they authenticate users. We also identified services that allow us to customise the sign in experience in order to achieve at least stage one of our strategy for consistent sign in:</p>
<blockquote>
<p>1) To ensure a single, consistent identity for each person, all library (and ICT) applications that we operate internally must have Active Directory sign-in instead of local databases. Almost all of our applications achieve this already.
<em>(source <a href="https://github.com/lncd/AIM-project/blob/master/Linkey%20JISC%2001-12%20DI%20Proposal.pdf?raw=true">Linkey bid document</a> - section 3.1)</em></p>
</blockquote>
<p>Before proceeding there is some jargon to explain:</p>
<ul>
<li><strong>SAM</strong> - A SAM (security accounts manager) ID is a user’s AD username. For staff this will generally be the first letter of their forename + their surname - e.g. for me this is <em>abilbie</em>. For students this is their student number - e.g. <em>01234567</em>.</li>
<li><strong>Password</strong> - This a user’s AD password.</li>
<li><strong>Employee ID</strong> - for staff this is the ID number from our employee database. For students this is the same as their SAM ID.</li>
<li><strong>SafeCom PIN</strong> - SafeCom is our printing authentication service we use here at the university. Each staff and student has their own PIN number which they use with their employee ID.</li>
</ul>
<p>This is the list we came up with:</p>
<ol>
<li><strong>Horizon Information Portal (HIP)</strong> - This service allows staff and students to interact with things they’ve borrowed or want to borrow, for example renewing and reserving books and viewing fines. We can edit <a href="http://en.wikipedia.org/wiki/XSL">XSL</a> files which allow us to change the design of HIP. We can also add JavaScript files. HIP authenticates with a user’s employee ID and PIN number.</li>
<li><strong>library.lincoln.ac.uk</strong> - Hosted on our <a href="http://blogs.lincoln.ac.uk">WordPress</a> platform. We can completely customise every aspect of the site. Users sign in with their SAM ID and password.</li>
<li><strong>Blackboard</strong> - Our <a href="http://en.wikipedia.org/wiki/Virtual_learning_environment">VLE</a>. If a user is signed in it will provide infomation about their library account plus they can pay any fines. Digitised material stored is also stored in and access is granted based on a students’ course. Users sign in with their SAM ID and password.</li>
<li><strong>Clio</strong> - inter-library loans management website. Users sign in with their SAM ID and password. We can completely customise the experience.</li>
<li><strong>EPrints</strong> - our research repository. <a href="http://www.eprints.org/">EPrints</a> is open source so we can change anything. Users sign in with their SAM ID and password.</li>
<li><strong>EZProxy</strong> - allows for e-resources access based on IP address proxying. EZProxy is LDAP capable however it can inherit Blackboard/SharePoint authentication sessions. We can completely customise the experience.</li>
<li><strong>Open Athens LA (Local Authentication)</strong> - Enables users to securely access to online resources. Provides Athens-&gt;Athens, and Athens/SAML-&gt;UK Federation-&gt;SAML authentication. Users sign in with their SAM ID and password. This should be installed in the coming weeks. We <em>think</em> we can customise the experience.</li>
<li><strong>Resources that have their own username + password</strong>. A very subset of online resources the library subscribe don’t work with Athens or EZProxy and so give us a username and password to use. Users are directed to these services through our SharePoint site and are authenticate with these services in two ways:</li>
<li>The username and password are automatically injected into the service’s authentication screen with a JavaScript script or</li>
<li>The user is a presented with a 401 dialog and they have to manually enter the username and password.</li>
<li><strong>Thin Clients</strong> - The GCW library on the Brayford campus over the summer had a number of <a href="http://en.wikipedia.org/wiki/Thin_client">thin client</a> computers installed. When physically in front of the computer users’ authenticate with their SAM ID and password but because these machines use virtual instances we could provide a “desktop in the browser” experience via UAG.</li>
<li><strong>Find it @ Lincoln</strong> - A search engine of journals and databases that we subscribe to that is hosted remotely by Ebsco. Authentication is delegated to EZProxy.</li>
<li><strong>RefWorks</strong> - Allows users to collect references. Authentication is via Athens. We can’t customise the look and feel of RefWorks itself but we hope we can customise how our Open Athens LA looks.</li>
<li><strong>Aspire</strong> - Reading List software provided by Talis. Authentication is via Athens. See above note about customising Athens LA.</li>
<li><strong>Journals A to Z / OpenURL resolver</strong> - As above</li>
<li><strong>Databases</strong> - A combination of Athens and EZProxy authentication.</li>
<li><strong>Printing</strong> - The physical printers in the library require authentication using a user’s employee ID and their PIN number.</li>
<li><strong>Self service kiosks</strong> - These kiosks authenticate users by requiring them to scan their staff/student card (which has a <a href="http://en.wikipedia.org/wiki/Code_39">code 39 barcode </a> of their employee ID and then typing in their PIN onscreen. We can’t customise this experience.</li>
<li><strong>Print top up kiosks</strong> - These kiosks authenticate users by requiring them to type in their SAM ID and password. We can’t customise this experience.</li>
</ol>
<p>Visually of this looks like:</p>
<figure>
![http://i.imgur.com/nEKo4.png](http://i.imgur.com/nEKo4.png)](http://i.imgur.com/nEKo4.png)
</figure>
<p>When the UAG is installed we should be able to easily hook up services that require SAM ID and password over LDAP. Other services that use alternative authentication such as HIP will require us to write some middleware that will translate between SAM ID + password to employee ID + PIN.</p>
<p>Assuming it is as simple as that, then when these services are hooked up to the UAG then the map will look like this:</p>
<figure>
[![http://i.imgur.com/dyV6C.png](http://i.imgur.com/dyV6C.png)](http://i.imgur.com/dyV6C.png)
</figure>
<p>The model assumes that eventually the UAG will be like a Gateway for users to access most resources.</p>
<p>LDAP inject means that once a user has authenticated with the UAG their SAM ID and password will be stored in a session, and then when the user visits a service that uses LDAP authentication to the AD, UAG will inject their username and password into the sign-in form and click the submit button for them. At the end of the day single sign-in is essentially a user experience which takes some of the pain with accessing resources away from them.</p>
<p><a href="http://alexbilbie.com/2012/10/authentication-in-the-library/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
OAuth 2.0 has been standardisedhttp://alexbilbie.com/2012/10/oauth-2-0-has-been-standardisedWed, 17 Oct 2012 00:00:00 +0000Alex Bilbie
<p>The IETF has approved the OAuth 2.0 Core and Bearer specifications and have now been published as <a href="http://tools.ietf.org/html/rfc6749">RFC 6749</a> (Core) and <a href="http://tools.ietf.org/html/rfc6750">RFC 6750</a> (Bearer).</p>
<p>Dick Hardt, one of the editors of the spec has <a href="http://dickhardt.org/2012/10/oauth-2-0/">summarised three important enhancements</a> that OAuth 2.0 has over the old 1.0a spec:</p>
<blockquote>
<ul>
<li>Simplicity: Client developers don’t need to do any cryptography or use a library to call OAuth 2.0 protected resources. The token can be passed in the HTTP headers or as a URL parameter. While HTTP headers are preferred, a URL parameter is simpler and allows API exploration with a browser.</li>
<li>Token choice: implementers can use existing tokens that they already generate or consume. There are extension points so that the client can sign the token instead of it being a bearer token.</li>
<li>Separation of roles: if the token is self-contained, then the resource can verify the token independently of the authorization server. Resources don’t have to call back to the authorization server to verify the token on each call, enabling higher performance and separation of security contexts.</li>
</ul>
</blockquote>
<p><a href="http://alexbilbie.com/2012/10/oauth-2-0-has-been-standardised/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
JISC AIM programme meeting 16th Octoberhttp://alexbilbie.com/2012/10/jisc-aim-programme-meeting-16th-octoberWed, 17 Oct 2012 00:00:00 +0000Alex Bilbie
<p>
Yesterday I travelled to Birmingham for a JISC AIM programme meeting at the beautiful Aston University campus.
</p>
<p>
I presented a short talk about the Linkey project. My slides are embedded below. Note, I don't really like very "wordy" presentation slides so I keep them simple, however you should be able to get the gist of the talk :)
</p>
<script async class="speakerdeck-embed" data-id="507d494fa2a4030002041403" data-ratio="1.299492385786802" src="//speakerdeck.com/assets/embed.js"></script>
<p><a href="http://alexbilbie.com/2012/10/jisc-aim-programme-meeting-16th-october/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
XKCD 1121 Identityhttp://alexbilbie.com/2012/10/identityMon, 15 Oct 2012 00:00:00 +0000Alex Bilbie
<figure>
![http://imgs.xkcd.com/comics/identity.png](http://imgs.xkcd.com/comics/identity.png)](http://xkcd.com/1121/)
</figure>
<p><em>via <a href="http://xkcd.com/1121/">XKCD #1121</a></em></p>
<p><a href="http://alexbilbie.com/2012/10/identity/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Upcoming identity work from Google announcementhttp://alexbilbie.com/2012/10/upcoming-identity-work-from-googleFri, 12 Oct 2012 00:00:00 +0000Alex Bilbie
<p><a href="http://www.tbray.org/">Tim Bray</a>, a developer at Google who I <a href="http://linkey.blogs.lincoln.ac.uk/2012/07/13/how-oauth-2-0-works/">disagreed with in a previous post</a> has just <a href="http://www.tbray.org/ongoing/When/201x/2012/10/11/Lets-talk">posted on his blog</a> that the team he is currently working in is going to shortly be announcing some of their early work and thinkings soon.</p>
<p>He says problems they’ve identified and they want to try and solve include:</p>
<blockquote>
<ul>
<li>The username/password dance sucks and doesn’t scale, particularly on mobile.</li>
<li>People putting up apps and sites regard identity — getting people signed up &amp; signed in — purely as a tax; something they gotta do, but unrelated to what they care about.</li>
<li>Most developers don’t understand identity standards like OAuth, or the related crypto and signing technologies, don’t want to learn them, and shouldn’t have to.</li>
<li>If you can get new arrivals signed up quicker with less work, that’s a good thing.</li>
<li>If you can get people you know signed in quicker, ideally with one click, that’s a good thing.</li>
<li>People are paranoid and really don’t want to be in the headlines for next week’s embarrassing password leak.</li>
<li>People don’t want to think about privacy and tracking and transparency, but the risk of not doing so (just) exceeds the pain.</li>
<li>People like the notion of outsourcing the icky identity work, but are nervous about putting all their eggs in the Facebook’s or Google’s or Yahoo’s or whoever’s basket.</li>
<li>On the other hand, having a cluster of Sign in with… buttons on your landing page dilutes your brand and feels like watching NASCAR on TV.</li>
</ul>
</blockquote>
<p>I’m looking forward to seeing what they come up with.</p>
<p><a href="http://alexbilbie.com/2012/10/upcoming-identity-work-from-google/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Linkey Project Status Update 1http://alexbilbie.com/2012/09/linkey-project-status-updateFri, 28 Sep 2012 00:00:00 +0000Alex Bilbie
<p>We’re now a quarter of the way through the Linkey project calendar so I’m going to try and summarise where we are at and where the project is heading.</p>
<p>I’ve spent a considerable amount of time working away on the <a href="https://github.com/lncd/oauth2">OAuth PHP library</a> which features code to build an authorisation platform, a resource server, and an abstract client class so that you can easily interact with 3rd party OAuth endpoints.</p>
<p>With this code almost finished and tested I’ve started designing the next generation OAuth endpoint for use here at the university. Coupled with the work we’re doing on the side for our next generation API and open data platform, as well as ICT’s own enterprise service bus and <a href="http://linkey.blogs.lincoln.ac.uk/tag/uag/">UAG</a> development all together we’re developing a beautiful data driven environment that will allow us to go forth and build rich, personalised and secure services and applications.</p>
<p>My colleagues here in ICT have been testing the UAG on our development network over the past few months and they now feel comfortable to start building a production platform which we can start integrating services into. This will hopefully be ready in the next few weeks and I will be able to go into much more detail about how OAuth and UAG can work together.</p>
<p>The main clients for Linkey are the university library and they have already started reaping some of the benefits of a single sign on environment thanks to an installation of <a href="http://www.oclc.org/ezproxy/">EZProxy</a> which offers reverse proxy authentication to a large number of 3rd party journal and database services. Currently EZProxy is piggybacking off of our Blackboard installation for authentication which benefits students - we know from our analytics that most students access library services through Blackboard - because there are now 35 (at the time of writing) resources which they can access with one click and they won’t have to authenticate a second (or in some cases a third) time.</p>
<p>With a production UAG we should be able to hook up a large percentage of sites and services with relative ease. As a refresher here is the current authentication situation:</p>
<figure>
![https://raw.github.com/lncd/AIM-project/master/SSOCurrentSituation.png](https://raw.github.com/lncd/AIM-project/master/SSOCurrentSituation.png)
</figure>
<p>and here is the ideal situation which we should be able to achieve:</p>
<figure>
![https://raw.github.com/lncd/AIM-project/master/SSOIdealSituation.png](https://raw.github.com/lncd/AIM-project/master/SSOIdealSituation.png)
</figure>
<p>Over the next 9 months there are a few other areas of access and identity which I want to cover.</p>
<p>At EduServ’s <a href="http://www.eduserv.org.uk/newsandevents/events/fam11">Federated Access Management</a> conference last year there was a talk by Jonathon Richardson, assistant CIS director at the University of East Anglia where he discussed how students and staff can access some of his institutions’ services with their own 3rd party Internet services accounts (e.g. Facebook/Twitter/Google). I would like to look into what are the benefits and risks associated with allowing staff and students to access university resources with their own accounts instead of the brand new account which they are given by us when they start at the university.</p>
<p>Hopefully the OAuth 2.0 specification will also be completed very soon and I want to further investigate OAuth’s potential use cases. I have submitted a <a href="http://confoo.ca/en/call-for-papers/speaker/alex-bilbie">conference talk proposal</a> to ConFoo in Montreal, Canada to discuss my findings.</p>
<p>We have also committed to publishing a case study and organising a workshop about OAuth (and access and identity in general) which we will work with JISC to organise and promote.</p>
<p><a href="http://alexbilbie.com/2012/09/linkey-project-status-update?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
OAuth 2.0 Security - Going Beyond Bearer Tokenshttp://alexbilbie.com/2012/09/oauth-2-0-security-going-beyond-bearer-tokensThu, 20 Sep 2012 00:00:00 +0000Alex Bilbie
<p>The OAuth working group have released an initial security review of the OAuth 2.0 specification which looks at a number of potential threats that implementors could face and how to mitigate them.</p>
<p>The document can be read here <a href="http://tools.ietf.org/html/draft-tschofenig-oauth-security-00">http://tools.ietf.org/html/draft-tschofenig-oauth-security-00</a>.</p>
<p>The abstract of the document is below:</p>
<blockquote>
<p>The OAuth working group has finished work on the OAuth 2.0 core protocol as well as the Bearer Token specification. The Bearer Tokenis a TLS-based solution for ensuring that neither the interaction with the Authorization Server (when requesting a token) nor the interaction with the Resource Server (for accessing a protected resource) leads to token leakage. There has, however, always been the desire to develop a security solution that is “better” than Bearer Tokens (or at least different) where the Client needs to show
possession of some keying material when accessing a Resource Server.</p>
</blockquote>
<blockquote>
<p>This document tries to capture the discussion and to come up with requirements to process the work on solutions.</p>
</blockquote>
<blockquote>
<p>This document aims to discuss threats, security requirements and desired design properties of an enhanced OAuth security mechanism.</p>
</blockquote>
<p><a href="http://alexbilbie.com/2012/09/oauth-2-0-security-going-beyond-bearer-tokens?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Athens is a crappy experience for usershttp://alexbilbie.com/2012/09/athens-is-a-crappy-experience-for-usersWed, 12 Sep 2012 00:00:00 +0000Alex Bilbie
<p>This afternoon I decided to join the <a href="https://community.ja.net/groups/access-and-identity-management-aim">JANET Access and Identity Management group</a>.</p>
<p>I hit the join group button on the site and was then prompted to join the JANET community. Seeing that it supported UK Access Management Federation (UK AMF) sign in, I entered my university&#8217;s name and clicked continue.</p>
<p>I was then forwarded to a login screen on the OpenAthens site. I don&#8217;t think I have any OpenAthens credentials so I clicked &#8220;Alternative login&#8221; (but first I accidentally clicked &#8220;Forgotten password?&#8221; thanks to my haste and the tiny links).</p>
<p>Then I had to choose my institution (again???).</p>
<p>Then I was asked to click on a link to take me to my institution&#8217;s login page.</p>
<p>Then I was forwarded onto our current Athens sign-in endpoint where I authenticated with my University of Lincoln network credentials.</p>
<p>Finally I was returned to the JANET Community sign-up screen only to see that none of the form fields had been pre-filled because of course the UK AMF is anonymised.</p>
<p>What a waste of time and a terrible user experience.</p>
<div class="embed-container">
<iframe src="https://www.youtube.com/embed/H8MDRVva_bs?rel=0" frameborder="0"></iframe>
</div>
<p><a href="http://alexbilbie.com/2012/09/athens-is-a-crappy-experience-for-users/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
What is SAML?http://alexbilbie.com/2012/09/what-is-samlMon, 03 Sep 2012 00:00:00 +0000Alex Bilbie
<p>One of the outputs of the Linkey project is an open source PHP library that implements the <a href="http://tools.ietf.org/html/draft-ietf-oauth-saml2-bearer-13">SAML bearer assertion extension</a> (draft 13 at time of writing) to the OAuth 2.0 specification.</p>
<p><strong>But what is SAML?</strong></p>
<p>SAML, or Security Assertion Markup Language, is an XML-based framework that allows identity and security information to be shared across security domains - for example between two websites.</p>
<p>Information is exchanged through the concept of assertion tokens, which are XML documents that state facts about the assertion’s subject. For example, a SAML assertion about me might look like:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;saml:Response ID="_257f9d9e9fa14962c0803903a6ccad931245264310738" IssueInstant="2012-09-03T18:45:10Z" Version="2.0"&gt;
&lt;saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity"&gt;
https://www.lincoln.ac.uk
&lt;/saml:Issuer&gt;
&lt;saml:Status&gt;
&lt;saml:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/&gt;
&lt;/saml:Status&gt;
&lt;saml:Assertion ID="_3c39bc0fe7b13769cab2f6f45eba801b1245264310738" IssueInstant="2012-09-03T18:45:10Z" Version="2.0"&gt;
&lt;saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity"&gt;
https://www.lincoln.ac.uk
&lt;/saml:Issuer&gt;
&lt;saml:Subject&gt;
&lt;saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"&gt;
abilbie@lincoln.ac.uk
&lt;/saml:NameID&gt;
&lt;saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"&gt;
&lt;saml:SubjectConfirmationData NotOnOrAfter="2012-09-03T18:50:10Z" Recipient="https://sso.lincoln.ac.uk"/&gt;
&lt;/saml:SubjectConfirmation&gt;
&lt;/saml:Subject&gt;
&lt;saml:Conditions NotBefore="2012-09-03T18:45:10Z" NotOnOrAfter="2012-09-03T18:50:10Z"&gt;
&lt;saml:AudienceRestriction&gt;
&lt;saml:Audience&gt;https://sso.lincoln.ac.uk&lt;/saml:Audience&gt;
&lt;/saml:AudienceRestriction&gt;
&lt;/saml:Conditions&gt;
&lt;saml:AuthnStatement AuthnInstant="2012-09-03T18:45:10Z"&gt;
&lt;saml:AuthnContext&gt;
&lt;saml:AuthnContextClassRef&gt;urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified&lt;/saml:AuthnContextClassRef&gt;
&lt;/saml:AuthnContext&gt;
&lt;/saml:AuthnStatement&gt;
&lt;saml:AttributeStatement&gt;
&lt;saml:Attribute Name="name"&gt;
&lt;saml:AttributeValue xsi:type="xs:anyType"&gt;Alex Bilbie&lt;/saml:AttributeValue&gt;
&lt;/saml:Attribute&gt;
&lt;saml:Attribute Name="network_id"&gt;
&lt;saml:AttributeValue xsi:type="xs:anyType"&gt;abilbie&lt;/saml:AttributeValue&gt;
&lt;/saml:Attribute&gt;
&lt;saml:Attribute Name="division"&gt;
&lt;saml:AttributeValue xsi:type="xs:anyType"&gt;ICT Services&lt;/saml:AttributeValue&gt;
&lt;/saml:Attribute&gt;
&lt;saml:Attribute Name="staff_directory_url"&gt;
&lt;saml:AttributeValue xsi:type="xs:anyType"&gt;http://staff.lncd.org/abilbie&lt;/saml:AttributeValue&gt;
&lt;/saml:Attribute&gt;
&lt;/saml:AttributeStatement&gt;
&lt;/saml:Assertion&gt;
&lt;/saml:Response&gt;
</code></pre></div></div>
<p>This assertion here states that my name is <code class="highlighter-rouge">Alex Bilbie</code>, my network ID is <code class="highlighter-rouge">abilbie</code>, my division is <code class="highlighter-rouge">ICT Services</code> and that my staff directory page is <code class="highlighter-rouge">http://staff.lncd.org/abilbie</code>.</p>
<p>Generally the assertion will be provided by an “identity provider” (a.k.a an IDP) and consumed by a “service provider” (a.ka. a SDP).</p>
<p>SAML is often used in single sign on environments. Let’s consider a student trying to sign in to the student union website:</p>
<ol>
<li>The student (the user) would visit student union website (the SDP)</li>
<li>The SDP would realise the user isn’t yet signed in and so redirects the user to the single sign on endpoint (the IDP)</li>
<li>The user authenticates with the IDP</li>
<li>The IDP redirects the user back to the SDP with the assertion (by using a HTTP POST)</li>
<li>The SDP consumes the assertion, validates it and signs the user in</li>
</ol>
<p><strong>How does SAML compare to OAuth?</strong></p>
<p>For reference, this is how OAuth is used in a single sign on environment:</p>
<ol>
<li>The student (the user) would visit student union website (the client)</li>
<li>The client would realise the user isn’t yet signed in and so redirects the user to the single sign on endpoint (the authentication server)</li>
<li>The user authenticates with the authentication server</li>
<li>The user grants the client access to their private data</li>
<li>The authentication server redirects the user back to the client with an authorisation code in the URL</li>
<li>The client exchanges the authorisation code for an access token with the authentication server by itself authenticating</li>
<li>The client then sends a request to the resource server to request the user’s private data. The access token represents permission granted by the user for the client to act on their behalf.</li>
</ol>
<p>Now the OAuth flow looks longer it contains one important stage which is a requirement of the specification, specifically step 4 which is where the user is explicitly asked if they want to allow the client to access their data and also what data will be accessed. You could emulate this in the SAML flow but I think the upfront honesty so to speak in the OAuth flow is a huge advantage for users. Also most OAuth authentication servers allow users to revoke access to clients as well (i.e. their access token for that client is destroyed which immediately cuts access).</p>
<p>In both flows, the client/SDP itself is verified. In SAML this is done through certificate exchanges, in OAuth the client’s ID is validated at step 3 and step 6.</p>
<p><strong>How does the assertion extension work?</strong></p>
<p>Looking at the OAuth sign-in flow above, at step 6 the client exchanges the authorisation code for an access token. There are a number of ways this can step can actually work and each different method is called an authorisation grant type. The grant described above (and the grant is the generally used in most OAuth implementations) is the <code class="highlighter-rouge">authorization_code</code> grant.</p>
<p>The assertion extension defines a new authorisation grant type of <code class="highlighter-rouge">urn:ietf:params:oauth:client-assertion-type:saml2-bearer</code>. There is also another parameter called <code class="highlighter-rouge">client_assertion</code> which is a base64 encoded representation of the XML assertion. The client/SDP’s own credentials are in the assertion instead of being sent as <code class="highlighter-rouge">client_id</code> and <code class="highlighter-rouge">client_secret</code> parameters as in the authorisation code grant.</p>
<p>An example request would look like:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>POST /token.oauth2 HTTP/1.1
Host: authz.example.net
Content-Type: application/x-www-form-urlencoded
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Asaml2-
bearer&amp;assertion=PEFzc2VydGlvbiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDU
[...omitted for brevity...]aG5TdGF0ZW1lbnQ-PC9Bc3NlcnRpb24-
</code></pre></div></div>
<p>The specification includes a <a href="http://tools.ietf.org/html/draft-ietf-oauth-saml2-bearer-13#section-3">number of elements</a> that must be included the assertion in order to provide the authorisation server with all the details it needs about the request.</p>
<p>As I understand it there is also an optional <code class="highlighter-rouge">scope</code> parameter that can be passed in the request any scopes that the client/SDP requires.</p>
<p><a href="http://alexbilbie.com/2012/09/what-is-saml/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
OAuth 2.0 and the road to Hellhttp://alexbilbie.com/2012/07/oauth-2-0-and-the-road-to-hellThu, 26 Jul 2012 00:00:00 +0000Alex Bilbie
<p>Eran Hammer who, until a few days ago, was the main editor of OAuth 2.0 has written this very damning blog post about the protocol</p>
<p><a href="http://hueniverse.com/2012/07/oauth-2-0-and-the-road-to-hell/">http://hueniverse.com/2012/07/oauth-2-0-and-the-road-to-hell/</a></p>
<p>I’ve been following the working group for about a year now and there has been an awful lot of bickering and mindless discussion.</p>
<p>As I’ve stated already, I’ve spent the last few weeks working on a brand new library that implements the current spec (draft 30) and I do feel myself agreeing with some of his points:</p>
<ul>
<li>Yes the specification mess, I’ve highlighted and sticky noted the printed spec document to death and the flow between different sections is really bad</li>
<li>Bearer tokens over SSL/TLS by themselves are bad and I think signatures need to come back
<ul>
<li>Basically if I steal someone’s access token I can use that wily nilly, however with signatures the entire request is signed with the client’s secret key so unless the secret key is leaked you can’t just use access tokens by themselves</li>
</ul>
</li>
<li>I disagree however that the protocol (in it’s current state) is complicated, they’ve done great work at making it a 3 (or 4) legged protocol to just 2 legs and everyone agrees that bit of the protocol has been done well.</li>
</ul>
<p>In terms of his suggestion that alternatives to OAuth that are outside the reach of the IETF might crop up I’m quite interested in this and if something crops up I’ll definitely take a look, and if one doesn’t then I’d be interested in having a go in writing one myself as an output of Linkey.</p>
<p>In terms of the extension documents (which include the assertions (SAML) extension, I don’t know enough about SAML to make any sort of informed opinion about this, however I’ve also still yet to see any public implementation of it.</p>
<p><a href="http://alexbilbie.com/2012/07/oauth-2-0-and-the-road-to-hell/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
What is OAuth?http://alexbilbie.com/2012/07/what-is-oauthTue, 10 Jul 2012 00:00:00 +0000Alex Bilbie
<p>The <a href="http://oauth.org">OAuth website</a> describes OAuth as:</p>
<blockquote>
<p>An <strong>open protocol</strong> to allow <strong>secure API authorisation</strong> in a <strong>simple</strong> and <strong>standard</strong> method from desktop and web applications.</p>
</blockquote>
<p>Essentially OAuth is a security protocol that enables users to grant third-party access to their web resources without sharing their passwords.</p>
<p>OAuth grew out of discussions between developers from Twitter and Ma.gnolia who wanted to authorise desktop applications to access their services. A working group was formed in 2007 to draft a proposal for an open standard. Developers from both Google and Yahoo also contributed to this work.</p>
<p>The first OAuth Core 1.0 draft was released in late 2007. In 2008 it was decided that the Internet Engineering Task Force (IETF) would adopt the specification to allow wider discussion and further standardisation work.</p>
<p>A minor revision (<a href="http://oauth.net/core/1.0a/">OAuth 1.0 Revision A</a>) was published in June 2008 to fix a security hole. The OAuth 1.0 Protocol was published by the IETF OAuth Working Group in April 2010 as <a href="http://tools.ietf.org/html/rfc5849">RFC 5849</a>.</p>
<p>A number of Internet companies and services adopted OAuth 1.0 but it was considered too much of a pain in the arse to work with by developers because it involved complicated signatures being passed around and there were too many requests between clients and services.</p>
<p>In May 2010 work began on <a href="http://oauth.org/2">version 2.0</a> of the OAuth protocol. Version 2.0 is not backwards compatible with OAuth 1.0a and focuses on developer simplicity. It also features more flows to allow the use of OAuth in more situations, as well as extensions to the core protocol to enable interoperability with assertion based protocols such as <a href="http://en.wikipedia.org/wiki/Security_Assertion_Markup_Language">SAML</a>.</p>
<p>OAuth has been adopted by many large Internet services and companies, here are some to name a few:</p>
<ul>
<li>Google (v2.0)</li>
<li>Yahoo (v1.0a)</li>
<li>Twitter (v1.0a and v2.0<sup id="fnref:twitter_connect"><a href="#fn:twitter_connect" class="footnote">1</a></sup>))</li>
<li>Github (v2.0)</li>
<li>Microsoft (v2.0)</li>
<li>Foursquare (v2.0)</li>
<li>Salesforce (v2.0)</li>
<li>Facebook (v2.0)</li>
</ul>
<p>We have been using OAuth 2.0 here at the University of Lincoln since late 2011 where we investigated using it for the <a href="http://totalrecal.blogs.lincoln.ac.uk">Total ReCal project</a> so that students here at the university could access their event data. Our implementation was based on <a href="https://github.com/alexbilbie/CodeIgniter-OAuth-2.0-Server">some work</a> I’d already been doing in the area based in my own time.</p>
<p>We currently have over 30 application using OAuth to interact with our data sets including the Student Union website, the staff directory, <a href="http://orbital.lincoln.ac.uk">Orbital</a>, and four 3rd year student final projects.</p>
<p>In October 2011 I spoke at EduServ’s <a href="http://www.eduserv.org.uk/newsandevents/events/fam11">Federated Access Management conference</a> about how OAuth works and how we are using it. The slides for this presentation can be found at <a href="https://speakerdeck.com/u/alexbilbie/p/introduction-to-oauth">https://speakerdeck.com/u/alexbilbie/p/introduction-to-oauth</a>.</p>
<p>During the Linkey project I’m going to be redeveloping my <a href="https://github.com/alexbilbie/CodeIgniter-OAuth-2.0-Server">CodeIgniter OAuth 2.0 server</a> to a be a framework-agnostic <a href="http://getcomposer.org">Composer</a> package. I’m also going to be adding support for the <a href="http://tools.ietf.org/wg/oauth/draft-ietf-oauth-v2-bearer/">bearer extension</a> and the <a href="http://tools.ietf.org/wg/oauth/draft-ietf-oauth-assertions/">assertions extension</a>.</p>
<div class="footnotes">
<ol>
<li id="fn:twitter_connect">
<p>Currently on Twitter Connect supports OAuth 2.0 using the XXX flow. <a href="#fnref:twitter_connect" class="reversefootnote">&#8617;</a></p>
</li>
</ol>
</div>
<p><a href="http://alexbilbie.com/2012/07/what-is-oauth/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
What is Microsoft Forefront Unified Access Gateway (UAG)?http://alexbilbie.com/2012/06/what-is-microsoft-forefront-unified-access-gateway-uagFri, 06 Jul 2012 00:00:00 +0000Alex Bilbie
<h1 id="what-is-microsoft-forefront-unified-access-gateway-uag">What is Microsoft Forefront Unified Access Gateway (UAG)</h1>
<p><a href="http://www.microsoft.com/en-us/server-cloud/forefront/unified-access-gateway.aspx">Microsoft Forefront Unified Access Gateway</a> (UAG) is a piece of server side software which provides secure access to corporate networks, systems and applications. It incorporates a number of different access technologies including VPN, HTTP reverse proxies and the Microsoft-developed technologies DirectAccess and Remote Desktop Services. Remote clients can access these corporate resources through a special web site that is hosted on an <a href="http://www.iis.net/">IIS</a> server which is bound to the UAG software.</p>
<p>UAG includes built integrations for <a href="http://www.microsoft.com/exchange/en-us/default.aspx">Microsoft Exchange Server</a> (2003, 2007 and 2010), <a href="http://sharepoint.microsoft.com/en-au/Pages/default.aspx">SharePoint Server</a> (2003, 2007 and 2010), Remote Desktop Services and <a href="http://www.citrix.com/English/ps2/products/product.asp?contentID=186">Citrix Presentational Services</a>. It also includes a technology called SSL-VPN which allows for authentication integration with most 3rd party and custom software.</p>
<p>UAG can use a number of different authentication sources including Active Directory, LDAP, RADIUS and SecurID. Finally it can also “speak” SAML and ADFS.</p>
<p>Microsoft identifies a number of benefits of using UAG:</p>
<blockquote>
<p>Forefront Unified Access Gateway (UAG) is designed to provide secure remote access in a way that extends application intelligence, security and control, and ease of use. Key benefits include:</p>
</blockquote>
<blockquote>
<p><strong>Anywhere Access</strong></p>
</blockquote>
<blockquote>
<p>Forefront UAG makes it easier to deliver secure remote access to your applications and resources, and improve employee and partner productivity, by combining an intelligent access policy engine with a variety of connectivity options including SSL VPN and Direct Access. Forefront UAG:</p>
</blockquote>
<blockquote>
<p>Empowers employees, partners, and vendors to be productive from virtually any device or location through integrated SSL VPN capabilities.
Delivers simple and secure access optimised for applications such as SharePoint, Exchange, and Dynamics CRM.
Extends networking connectivity with Windows Direct Access to existing infrastructure and legacy applications.</p>
</blockquote>
<blockquote>
<p><strong>Integrated Security</strong></p>
</blockquote>
<blockquote>
<p>Forefront UAG improves the security in remote access scenarios by enforcing granular access controls and policies that are tailored to the applications being published, the identity of the user, and the health status of the device being used. Forefront UAG further improves security by enabling strong authentication to applications and mitigating the risks of downloaded data from unmanaged devices. Forefront UAG:</p>
</blockquote>
<blockquote>
<p>Protects IT assets through fine-grained and built-in policies that provide access to sensitive data based on identity and endpoint health.
Easily integrates with Active Directory and enables a variety of strong authentication methods.
Limits exposure and prevent data leakage to unmanaged endpoints.</p>
</blockquote>
<blockquote>
<p><strong>Simplified Management</strong></p>
</blockquote>
<blockquote>
<p>Forefront UAG offers a single platform through which to deliver and manage remote access. With built in policies and configurations for common applications and devices, you can gain more control, more efficient management, greater visibility, and lower total cost of ownership. Forefront UAG:</p>
</blockquote>
<blockquote>
<p>Consolidates remote access infrastructure and management.
Simplifies deployment and ongoing tasks through wizards and built-in policies.
Reduces support costs by delivering a simplified connectivity experience for users.</p>
</blockquote>
<blockquote>
<p>Source: <em><a href="http://www.microsoft.com/en-us/server-cloud/forefront/unified-access-gateway.aspx">http://www.microsoft.com/en-us/server-cloud/forefront/unified-access-gateway.aspx</a></em></p>
</blockquote>
<h2 id="how-uag-can-help-us">How UAG can help us</h2>
<p>At the university we have a number of existing web based applications which will benefit from having UAG integration.</p>
<p>We currently have SharePoint and Exchange 2003 installations (which will soon be upgraded to 2010) which UAG can natively integrate with.</p>
<p>We use <a href="http://www.blackboard.com/platforms/learn/overview.aspx">Blackboard Learn</a> as our LMS and <a href="http://zendesk.com/">Zendesk</a> as our support desk software, both of which have can use SAML for single sign on.</p>
<p>We are also looking into potentially using UAG as the access point for Windows 7 thin client access.</p>
<h2 id="how-can-uag-work-with-oauth">How can UAG work with OAuth?</h2>
<p>As UAG can use SAML to communicate with services it means that we can use the <a href="http://tools.ietf.org/wg/oauth/draft-ietf-oauth-assertions/">OAuth 2.0 assertions specification</a> to create a translation framework between SAML assertions and OAuth tokens. This will extend some of the work that we’ve originally done on our OAuth server and the updated code will be published.</p>
<p>One of the outcomes of this project will be a case study (with open source code examples) on how UAG and an OAuth server can work together (though because we don’t know how this may work at the moment it could be that it turns out they can’t work together…) and on this blog we will document our experience.</p>
<p><a href="http://alexbilbie.com/2012/06/what-is-microsoft-forefront-unified-access-gateway-uag/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Linkey, Chapter Onehttp://alexbilbie.com/2012/06/linkey-chapter-oneTue, 12 Jun 2012 00:00:00 +0000Alex Bilbie
<em>- This has been cross posted from the <a href="http://linkey.blogs.lincoln.ac.uk/">Linkey project blog</a>.</em>
<p>It&#8217;s 9am on Monday 25th June 2012 and the Linkey project is officially kicking off.</p>
<h2>What is Linkey</h2>
<p><em>Linkey</em> is a <a href="http://jisc.ac.uk">JISC</a> funded research project under the <a href="">Access and Identity Management programme</a>. It will run from June 2012 to May 2013.</p>
<p>The project will provide a detailed case study of the use of OAuth as an authorisation protocol here at the University of Lincoln. Working closely with the university Library, we will examine how the <a href="http://oauth.org/2">OAuth 2.0 specification</a> can be integrated into a ‘single sign on’ environment alongside <a href="http://www.microsoft.com/en-us/server-cloud/forefront/unified-access-gateway.aspx">Microsoft&#8217;s Unified Access Gateway</a>.</p>
<p>Our intention is to show how OAuth 2.0 can be used as part of an access and identity environment in higher education that improves the student experience by:</p>
<ol>
<li>A consistent and user centric sign-­in experience.</li>
<li>A richer exchange of user information between applications.</li>
<li>Easier development and implementation of new products.</li>
</ol>
<h2>Why?</h2>
<p>A recent review of the university&#8217;s library systems and services indicated that we had around 10 core applications which provide access to over 150 other resources, all of which have different methods of authenticating users - some used LDAP to authenticate users (and so users use their network username and password) and others had their own database of users (which require a different passwords - and in some cases usernames - and every single one of these flows have a different sign in experience; some are web based with various designs, others are desktop based with a mixture of custom sign-in windows and Microsoft sign-in screens. Over 80% of user queries sent to the Library&#8217;s support email address around about problems accessing resources.</p>
<p>Outside of the library there are over 100 other systems and services that have visibility in the business processes across the university which also authenticate in a number of different ways.</p>
<p>All of these different authentication flows lead to a very inconsistent user experience and consistently for the last few years this has been highlighted in numerous student surveys.</p>
<h2>Who?</h2>
<p>I (<a href="http://phone.online.lincoln.ac.uk/abilbie">Alex Bilbie</a>) will be undertaking the majority of the work on the project. This will include researching technological solutions, engaging with end users, developing the open source OAuth 2.0 PHP server and working on the final implementation.</p>
<p>The principal user on the project will be <a href="http://phone.online.lincoln.ac.uk/dmasterson">Dave Masterson</a>, Head of Electronic Library Services, who has been charged with improving the usability of our Library&#8217;s online services.</p>
<p>The project manager for the project will be <a href="http://phone.online.lincoln.ac.uk/jwinn">Joss Winn</a>, Senior Lecturer in CERD and co-ordinator of the <a href="http://lncd.org">LNCD group</a>.</p>
<p><a href="http://phone.online.lincoln.ac.uk/tsimmonds">Tim Simmonds</a>, Online Services Team Manager, will assume management and oversight of the technical implementation of both OAuth and UAG.</p>
<h2>When?</h2>
<p>The high level work plan is a below:</p>
<table class="table">
<thead>
<tr>
<th>
Month
</th>
<th>
1
</th>
<th>
2
</th>
<th>
3
</th>
<th>
4
</th>
<th>
5
</th>
<th>
6
</th>
<th>
7
</th>
<th>
8
</th>
<th>
9
</th>
<th>
10
</th>
<th>
11
</th>
<th>
12
</th>
</thead>
<tbody>
<tr>
<th>
Initiate project
</th>
<td>X</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th>
Community Engagement
</th>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<th>
Gather user requirements
</th>
<td></td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td></td>
</tr>
<tr>
<th>
Evaluate available technologies and options
</th>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th>
Design Solution
</th>
<td></td>
<td></td>
<td></td>
<td>X</td>
<td>X</td>
<td>X</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th>
Technical development and implementation
</th>
<td></td>
<td></td>
<td></td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td></td>
<td></td>
</tr>
<tr>
<th>
Write case study
</th>
<td></td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<th>
Write/submit conference paper
</th>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<th>
OAuth workshop
</th>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>X</td>
<td></td>
</tr>
<tr>
<th>
Project close
</th>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>X</td>
</tr>
</tbody>
</table>
<p>You can follow the day to day activity on our <a href="https://www.pivotaltracker.com/projects/557455">Pivotal Tracker project page</a>.</p>
<h2>Outcomes</h2>
<p>The anticipated outcomes of the project are:</p>
<ol>
<li>A case study of our implementation of OAuth 2.0 together with Microsoft&#8217;s UAG product. We will provide draft sections of the final case study in 12 monthly blog posts, allowing for early peer-review.</li>
<li>Continued development of our open source OAuth 2.0 server (based on <a href="https://github.com/alexbilbie/CodeIgniter-OAuth-2.0-Server">my server code</a>), including an implementation of the <a href="http://tools.ietf.org/wg/oauth/draft-ietf-oauth-saml2-bearer/">SAML 2.0 Bearer Assertion Profiles for OAuth 2.0</a> specification and other relevant extensions to the main standard. We aim to produce a ‘drop in’ solution for OAuth 2.0, in a similar way that the <a href="http://simplesamlphp.org/">SimpleSAMLphp</a> project supports SAML implementations.</li>
<li>A public workshop on the use of OAuth 2.0 in Further and Higher Education.</li>
<li>A conference/journal paper, based on our case study.</li>
<li>Expertise in the implementation of an institution-wide infrastructure for AIM.</li>
</ol>
<p><a href="http://alexbilbie.com/2012/06/linkey-chapter-one/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Dev8ed 2012http://alexbilbie.com/2012/05/dev8edWed, 30 May 2012 00:00:00 +0000Alex Bilbie
<p>
I’ve just got back from two days at <a href="http://devcsi.ukoln.ac.uk/upcoming-events/dev8ed/">Dev8ed</a> which was hosted at Conference Aston. This was my 6th or 7th <a href="http://devcsi.ukoln.ac.uk/">DevCSI</a> event as as with all the others it was very well organised at we were looked after throughout the event.
</p>
<p>
On day one I spent the morning discussing some of the potential use cases of <a href="http://xcri.org/">XCRI-CAP</a> feeds, which, for those who don’t know are XML dumps published by educational institutions to describe the courses they offer.
</p>
<p>
My favourite potential use case of the course data is a tool that will allow prospective students to download a personalised prospectus. The main problem with most institution prospectuses currently are that they contain every single course that is available. What would be nice is a way for a prospective student to express keywords or the types of course they are interested in and then they will be able to download a PDF prospectus that was generated on the fly that only includes courses that are relevant to them.
</p>
<p>
On day two I did two presentations. The first presentation was about the different tools and services we use in <a href="http://lncd.org/">LNCD</a> which help us be better developers.
</p>
<script async class="speakerdeck-embed" data-id="4fc62fda5fb56f00220116dd" data-ratio="1.3333333333333333" src="//speakerdeck.com/assets/embed.js"></script>
<p>
The second presentation was an introduction to HTML5 and CSS3 (based on my presentation I did at Dev8D).
</p>
<script async class="speakerdeck-embed" data-id="4fc630c2c41f0f002100fe3a" data-ratio="1.299492385786802" src="//speakerdeck.com/assets/embed.js"></script>
<p><a href="http://alexbilbie.com/2012/05/dev8ed/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
How to get all of the predicates of an object in SPARQLhttp://alexbilbie.com/2012/05/how-to-get-all-of-the-predicates-of-an-object-in-sparqlFri, 25 May 2012 00:00:00 +0000Alex Bilbie
I finally discovered the other day how to get all of the predicates of an object in SPARQL. For this example I'll query the University of <a href="http://data.lib.cam.ac.uk/endpoint.php">Cambridge endpoint</a> to get all of the information they have about The Lord of the Rings.
<code><pre>
SELECT * WHERE
{
'http://data.lib.cam.ac.uk/id/entry/cambrdgedb_1327612' ?p ?o .
}
</pre></code>
This query returns the following data:
<div style="width: auto; overflow: auto;">
<table><tbody><tr><th>p</th><th>o</th></tr><tr><td><a href="http://purl.org/dc/terms/title">http://purl.org/dc/terms/title</a></td><td>The Lord of the Rings</td></tr><tr><td><a href="http://purl.org/dc/terms/type">http://purl.org/dc/terms/type</a></td><td><a href="http://data.lib.cam.ac.uk/id/type/1cb251ec0d568de6a929b520c4aed8d1">http://data.lib.cam.ac.uk/id/type/1cb251ec0d568de6a929b520c4aed8d1</a></td></tr><tr><td><a href="http://purl.org/dc/terms/type">http://purl.org/dc/terms/type</a></td><td><a href="http://data.lib.cam.ac.uk/id/type/46657eb180382684090fda2b5670335d">http://data.lib.cam.ac.uk/id/type/46657eb180382684090fda2b5670335d</a></td></tr><tr><td><a href="http://purl.org/dc/terms/identifier">http://purl.org/dc/terms/identifier</a></td><td>UkCU1327612</td></tr><tr><td><a href="http://purl.org/dc/terms/identifier">http://purl.org/dc/terms/identifier</a></td><td>urn:isbn:0048231576</td></tr><tr><td><a href="http://purl.org/dc/terms/issued">http://purl.org/dc/terms/issued</a></td><td>1979</td></tr><tr><td><a href="http://purl.org/dc/terms/language">http://purl.org/dc/terms/language</a></td><td><a href="http://id.loc.gov/vocabulary/iso639-2/eng">http://id.loc.gov/vocabulary/iso639-2/eng</a></td></tr><tr><td><a href="http://RDVocab.info/ElementsplaceOfPublication">http://RDVocab.info/ElementsplaceOfPublication</a></td><td><a href="http://id.loc.gov/vocabulary/countries/enk">http://id.loc.gov/vocabulary/countries/enk</a></td></tr><tr><td><a href="http://purl.org/ontology/bibo/isbn">http://purl.org/ontology/bibo/isbn</a></td><td>0048231576</td></tr><tr><td><a href="http://purl.org/dc/terms/creator">http://purl.org/dc/terms/creator</a></td><td><a href="http://data.lib.cam.ac.uk/id/entity/cambrdgedb_041c446ee6c5c4bd5a63bcc2debe1351">http://data.lib.cam.ac.uk/id/entity/cambrdgedb_041c446ee6c5c4bd5a63bcc2debe1351</a></td></tr><tr><td><a href="http://iflastandards.info/ns/isbd/elements/P1016">http://iflastandards.info/ns/isbd/elements/P1016</a></td><td>London</td></tr><tr><td><a href="http://purl.org/dc/terms/publisher">http://purl.org/dc/terms/publisher</a></td><td><a href="http://data.lib.cam.ac.uk/id/entity/cambrdgedb_b7c309134a35a5455692006ee550ddf6">http://data.lib.cam.ac.uk/id/entity/cambrdgedb_b7c309134a35a5455692006ee550ddf6</a></td></tr><tr><td><a href="http://purl.org/dc/terms/created">http://purl.org/dc/terms/created</a></td><td>1979</td></tr><tr><td><a href="http://purl.org/dc/terms/extent">http://purl.org/dc/terms/extent</a></td><td><a href="http://data.lib.cam.ac.uk/id/entity/cambrdgedb_935bf1a181de0991dce6d3ee56b53ba4">http://data.lib.cam.ac.uk/id/entity/cambrdgedb_935bf1a181de0991dce6d3ee56b53ba4</a></td></tr><tr><td><a href="http://iflastandards.info/ns/isbd/elements/P1008">http://iflastandards.info/ns/isbd/elements/P1008</a></td><td>3rd ed</td></tr></tbody></table>
</div>
<a href="http://data.lib.cam.ac.uk/endpoint.php?query=SELECT+*+WHERE%0D%0A%7B%0D%0A++++%27http%3A%2F%2Fdata.lib.cam.ac.uk%2Fid%2Fentry%2Fcambrdgedb_1327612%27+%3Fp+%3Fo+.%0D%0A%7D&output=htmltab&jsonp=&key=&show_inline=1">You can run this query yourself</a>
<p><a href="http://alexbilbie.com/2012/05/how-to-get-all-of-the-predicates-of-an-object-in-sparql/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
CodeIgniter has a new reactor engineerhttp://alexbilbie.com/2012/05/codeigniter-has-a-new-reactor-engineerSat, 19 May 2012 00:00:00 +0000Alex Bilbie
<p>I’m very honoured to have been invited to join the <a href="https://github.com/ellislab/codeigniter">CodeIgniter</a> project as a core contributor (known as a <a href="http://codeigniter.com/news/codeigniter_in_2011_reactor_core_uservoice/">reactor engineer</a>).</p>
<p>I’m looking forward to getting stuck in fixing bugs, helping the community out and promoting the use of CodeIgniter.</p>
<p>I owe many thanks to Ellislab and Phil Sturgeon for their support.</p>
<p><a href="http://alexbilbie.com/2012/05/codeigniter-has-a-new-reactor-engineer/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Linkeyhttp://alexbilbie.com/2012/05/linkeyFri, 18 May 2012 00:00:00 +0000Alex Bilbie
<p>I&#8217;ve very pleased to announce that <a href="http://lncd.org">LNCD</a> have won another JISC funded project under the <a href="http://www.jisc.ac.uk/whatwedo/programmes/aim.aspx">Access and Identity Management programme</a>. This will be the fifth JISC project I&#8217;ll have worked on (for the other projects I&#8217;ve been involved with see <a href="/about">my bio</a>.</p>
<p>The project is called Linkey (yes we managed to make another Lincoln based pun to join our others - <a href="http://lncn.eu">lncn.eu</a> (&#8220;Linking You&#8221;) and <a href="http://lncd.org">LNCD</a> (&#8220;LNCD <em>is</em> Not <em>a</em> Central Development <em>group</em>&#8221;) and will be looking at how the <a href="http://tools.ietf.org/html/draft-ietf-oauth-v2">OAuth 2.0 specification</a> can be implemented in HEIs. The primary driver for this is to improve the student and staff experience and meet the following objectives:</p>
<ol>
<li>Richer sharing of data between applications: A student or lecturer should be able to identify themselves to multiple applications and approve access to the sharing of personal data between those applications.</li>
<li>A consistent user experience (UX): We are initially aiming for ‘consistent sign on’ rather than &#8216;single sign on&#8217;, where the user is presented with a consistent UX when signing into disparate applications.</li>
<li>Rapid deployment: New applications that we develop or purchase should be easier to implement, plugging into either OAuth or the UAG and immediately benefiting from 1) and 2).</li>
</ol>
<p>The project will last for 12 months and the primary outcomes will be:</p>
<ol>
<li>A case study about our use and implementation of OAuth here at the <a href="http://lincoln.ac.uk">University of Lincoln</a></li>
<li>Significantly adding to my <a href="https://github.com/alexbilbie/CodeIgniter-OAuth-2.0-Server">CodeIgniter OAuth 2.0 server</a> by implementing the OAuth SAML bearer specification as well as hopefully all of the main authentication flows. I&#8217;m also going to work with on turning it it into a generic PHP Composer package so any PHP application can get some OAuth love. Finally I want to look at implementing [Selenium] tests (in addition to the usual PHPUnit tests) so that there is an awesome user experience.</li>
<li>A public workshop on the use of OAuth 2.0 in Further and Higher Education.</li>
<li>A conference/journal paper, based on our case study.</li>
</ol>
<p>I&#8217;ve embedded the bid we submitted to JISC below:</p>
<iframe src="https://docs.google.com/viewer?authuser=0&srcid=0B-O04KEqnewAWXVyb0hNMXVKOE0&pid=explorer&a=v&chrome=false&embedded=true" width="640" height="480"></iframe>
<p><a href="http://alexbilbie.com/2012/05/linkey/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Learning SPARQLhttp://alexbilbie.com/2012/04/learning-sparqlTue, 24 Apr 2012 00:00:00 +0000Alex Bilbie
<p>In my <a href="http://httpster.org/the-future-of-data-lincoln-ac-uk/">post about the future of data.lincoln.ac.uk</a> I committed us to providing a <a href="http://en.wikipedia.org/wiki/Sparql">SPARQL</a> endpoint for University of Lincoln open linked data. Today I’ve spent an insane amount of time learning how on earth SPARQL works.</p>
<p>I set up a local triplestore on my laptop using <a href="https://github.com/semsol/arc2/">ARC2</a>, I used <a href="https://github.com/njh/easyrdf">EasyRDF</a> to output a dump of the <a href="http://phone.online.lincoln.ac.uk/">staff directory</a> as RDF XML, I used Chris Gutteridge’s <a href="http://graphite.ecs.soton.ac.uk/">Graphite</a> and <a href="http://graphite.ecs.soton.ac.uk/browser/">Browser</a> code to check the EasyRDF output looked right, then finally after I’d loaded the data into the triplestore I used Dave Challis’ <a href="https://github.com/davechallis/SPARQLfront">SPARQLfront</a> to query the data.</p>
<p>So far I’ve managed to work out the following queries:</p>
<p>(copied from <a href="https://gist.github.com/2475211/">https://gist.github.com/2475211/</a>)</p>
<hr />
<p><strong>Get all divisions</strong></p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt;
PREFIX org: &lt;http://www.w3.org/ns/org#&gt;
SELECT DISTINCT ?dept ?deptName
WHERE {
?dept a org:OrganizationalUnit .
?dept rdfs:label ?deptName .
?dept org:unitOf &lt;http://lincoln.ac.uk/&gt; .
}
</code></pre></div></div>
<p><strong>Get all departments in $DIVISION$</strong></p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt;
PREFIX org: &lt;http://www.w3.org/ns/org#&gt;
SELECT DISTINCT ?dept ?deptName
WHERE {
?dept a org:OrganizationalUnit .
?dept rdfs:label ?deptName .
?dept org:unitOf &lt;http://id.online.lincoln.ac.uk/division/$DIVISION$&gt; .
}
</code></pre></div></div>
<p><strong>Get all staff in $DIVISION$</strong></p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PREFIX foaf: &lt;http://xmlns.com/foaf/0.1/&gt;
PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt;
PREFIX org: &lt;http://www.w3.org/ns/org#&gt;
SELECT ?givenName ?familyName
WHERE {
?person a foaf:Person .
?person org:memberOf &lt;http://id.online.lincoln.ac.uk/division/$DIVISION$&gt; .
?person org:memberOf ?division .
?division a org:OrganizationalUnit .
?division org:unitOf ?parent .
?person foaf:givenName ?givenName .
?person foaf:familyName ?familyName .
FILTER (?parent = "http://lincoln.ac.uk/")
}
</code></pre></div></div>
<p><strong>Get all staff in $DEPARTMENT$</strong></p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PREFIX foaf: &lt;http://xmlns.com/foaf/0.1/&gt;
PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt;
PREFIX org: &lt;http://www.w3.org/ns/org#&gt;
SELECT ?givenName ?familyName
WHERE {
?person a foaf:Person .
?person org:memberOf &lt;http://id.online.lincoln.ac.uk/department/$DEPARTMENT$&gt; .
?person org:memberOf ?division .
?division a org:OrganizationalUnit .
?division org:unitOf ?parent .
?person foaf:givenName ?givenName .
?person foaf:familyName ?familyName .
FILTER (?parent != "http://lincoln.ac.uk/")
}
</code></pre></div></div>
<p><strong>Get the division that a member of staff is in</strong></p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PREFIX foaf: &lt;http://xmlns.com/foaf/0.1/&gt;
PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt;
PREFIX org: &lt;http://www.w3.org/ns/org#&gt;
SELECT ?name
WHERE {
?division a org:OrganizationalUnit .
?division org:unitOf &lt;http://lincoln.ac.uk/&gt; .
?division rdfs:label ?name .
?division org:hasMember &lt;http://id.online.lincoln.ac.uk/person/$ID$&gt; .
}
</code></pre></div></div>
<p><strong>Get the department that a member of staff in is</strong></p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PREFIX foaf: &lt;http://xmlns.com/foaf/0.1/&gt;
PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt;
PREFIX org: &lt;http://www.w3.org/ns/org#&gt;
SELECT ?name
WHERE {
?division a org:OrganizationalUnit .
?division org:unitOf ?parent .
?division rdfs:label ?name .
?division org:hasMember &lt;http://id.online.lincoln.ac.uk/person/$ID$&gt; .
FILTER (?parent != "http://lincoln.ac.uk/")
}
</code></pre></div></div>
<hr />
<p>So that is what I’ve worked out so far.</p>
<p>Once I’ve got the final spaces data in the next week or so I’ll figure out some more queries which mix people and spaces.</p>
<p>Some of the resources that I found useful whilst learning SPARQL include:</p>
<ul>
<li><a href="http://jena.sourceforge.net/ARQ/Tutorial/">http://jena.sourceforge.net/ARQ/Tutorial/</a></li>
<li><a href="http://www.pezholio.co.uk/2011/01/a-beginners-guide-to-sparqling-linked-data-part-1/">http://www.pezholio.co.uk/2011/01/a-beginners-guide-to-sparqling-linked-data-part-1/</a></li>
<li>Checking out the SPARQL queries that are executed when rendering any of the <a href="http://data.southampton.ac.uk/">data.southampton.ac.uk pages</a> (click the “This page was constructed using X queries to the SPARQL Endpoint.” link at the bottom of each page)</li>
</ul>
<p>My thanks also go to <a href="http://www.ecs.soton.ac.uk/people/cjg">Chris Gutteridge</a>, <a href="http://ouseful.info">Tony Hirst</a>, <a href="https://twitter.com/#!/davechallis">Dave Challis</a>, <a href="http://www.aelius.com/njh/">Nicholas J Humfrey</a>, and <a href="https://github.com/semsol">Benjamin Nowack</a> for their various blog posts and code libraries which I also found useful.</p>
<p><a href="http://alexbilbie.com/2012/04/learning-sparql/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Update to my CodeIgniter MongoDB libraryhttp://alexbilbie.com/2012/04/update-to-my-codeigniter-mongodb-libraryFri, 20 Apr 2012 00:00:00 +0000Alex Bilbie
<table>
<tbody>
<tr>
<td>I’ve updated my CodeIgniter MongoDB library to version 0.5.1 (<a href="https://github.com/alexbilbie/codeigniter-mongodb-library/zipball/0.5.1">zip</a></td>
<td><a href="https://github.com/alexbilbie/codeigniter-mongodb-library/tarball/0.5.1">tar.gz</a></td>
<td><a href="http://getsparks.org/packages/mongodb/versions/HEAD/show">spark</a>). It mostly contains bug fixes and optimisations.</td>
</tr>
</tbody>
</table>
<p>Version 2.0 of the library is almost finished - check it out at <a href="https://github.com/alexbilbie/codeigniter-mongodb-library/tree/v2">https://github.com/alexbilbie/codeigniter-mongodb-library/tree/v2</a>. I’m currently working out how <a href="https://github.com/sebastianbergmann/phpunit/">PHP Unit</a> works so that the library can be tested on <a href="http://travis-ci.org">Travis CI</a> each time a new commit is made.</p>
<p><a href="http://alexbilbie.com/2012/04/update-to-my-codeigniter-mongodb-library/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
My popular culture knowledge suckshttp://alexbilbie.com/2012/04/my-popular-cultural-knowledge-sucksMon, 16 Apr 2012 00:00:00 +0000Alex Bilbie
<p>It’s common knowledge amongst my friends that my popular culture knowledge really sucks. I’ve never really been one to watch TV, I generally discover bands several months after everyone else does and my housemates have carved head shaped holes behind the sofas where they’ve banged their heads after I’ve admitted not watching yet another “but everyone has seen it” film.</p>
<p>I recently counted how many of the <a href="http://www.imdb.com/chart/top">IMDB top 100 films</a> I’ve seen and it’s a pitiful 18:</p>
<ul>
<li>(8) <a href="http://www.imdb.com/title/tt0468569/">The Dark Knight</a></li>
<li>(9) <a href="http://www.imdb.com/title/tt0167260/">The Lord of the Rings: The Return of the King</a></li>
<li>(11) <a href="http://www.imdb.com/title/tt0080684/">Star Wars: Episode V - The Empire Strikes Back</a></li>
<li>(15) <a href="http://www.imdb.com/title/tt0120737/">The Lord of the Rings: The Fellowship of the Ring</a></li>
<li>(17) <a href="http://www.imdb.com/title/tt0076759/">Star Wars: Episode IV - A New Hope</a></li>
<li>(20) <a href="http://www.imdb.com/title/tt0133093/">The Matrix</a></li>
<li>(23) <a href="http://www.imdb.com/title/tt0082971/">Raiders of the Lost Ark</a></li>
<li>(26) <a href="http://www.imdb.com/title/tt0114369/">Se7en</a></li>
<li>(27) <a href="http://www.imdb.com/title/tt0167261/">The Lord of the Rings: The Two Towers</a></li>
<li>(40) <a href="http://www.imdb.com/title/tt0120815/">Saving Private Ryan</a></li>
<li>(52) <a href="http://www.imdb.com/title/tt0211915/">Amelie</a></li>
<li>(56) <a href="http://www.imdb.com/title/tt0910970/">WALL·E</a></li>
<li>(59) <a href="http://www.imdb.com/title/tt0066921/">A Clockwork Orange</a></li>
<li>(77) <a href="http://www.imdb.com/title/tt0172495/">Gladiator</a></li>
<li>(80) <a href="http://www.imdb.com/title/tt0071853/">Monty Python and the Holy Grail</a></li>
<li>(89) <a href="http://www.imdb.com/title/tt0112573/">Braveheart</a></li>
<li>(94) <a href="http://www.imdb.com/title/tt0086190/">Star Wars: Episode VI - Return of the Jedi</a></li>
<li>(95) <a href="http://www.imdb.com/title/tt0457430/">Pan’s Labyrinth</a></li>
</ul>
<p>I’ve obviously seen more than 18 films in my life - I quickly scanned over the next 150 “top” films and I can see at least another 20 that I’ve seen - but to have only seen 18 out of the top 100 films of all time is, I’m regularly told, a sorry state of affairs.</p>
<p>Therefore I’ve decided it’s time to do something about it. From next week onwards, for as long as it takes, I’m going to try and watch one or two of the IMDB top 100 files (in order) a week starting with the number one ranked film, <a href="http://www.imdb.com/title/tt0111161/">The Shawshank Redemption</a>.</p>
<p>I will write a small review of each film after I’ve watched it on this blog as a record of my “achievements”.</p>
<p><a href="http://alexbilbie.com/2012/04/my-popular-culture-knowledge-sucks/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
The future of data.lincoln.ac.ukhttp://alexbilbie.com/2012/04/the-future-of-data-dot-lincolnSun, 15 Apr 2012 00:00:00 +0000Alex Bilbie
<p>For the last year we have been <a href="https://github.com/unilincoln-ost/Nucleus-Docs/wiki">documenting a number of APIs</a> we have developed that allow anyone inside or outside the university to interact with public and private datasets that we have compiled. These datasets include academic timetable events, building and room locations, the staff directory, building energy statistics, blog tags, and many more that we’ve never documented. Many of these datasets were created as result of JISC projects we’ve done to date.</p>
<p>Following a <a href="http://lncd.org/">LNCD</a> away day last week we’ve agreed to formalise our commitment to the data.ac.uk movement by publishing <a href="http://lab.linkeddata.deri.ie/2010/star-scheme-by-example/">5★ linked data</a> on <a href="http://data.lincoln.ac.uk/">data.lincoln.ac.uk</a> complete with a <a href="http://en.wikipedia.org/wiki/SPARQL">SPARQL</a> endpoint.</p>
<p>The problem we’ve had to date with our set up was that our open data was being hosted on the same server as our Nucleus platform which powers our authenticated APIs. Nucleus is now powering more and more services at the university and so in order to ensure quality of service we need to create a formal distinction between the two platforms.</p>
<p>Before we can publish any data we need to agree on an open license for it. <a href="http://id.online.lincoln.ac.uk/sam/jwinn">Joss</a> will meet with the university’s IP manager and consult with our friends at other universities as to an appropriate license.</p>
<p>So what open data sets will we be publishing? Well, here is what we can commit to to start off with:</p>
<ul>
<li><strong>Course data</strong> - <a href="http://id.online.lincoln.ac.uk/sam/jmahoney">Jamie</a> has been working hard on collecting and categorising the university’s course information as part of the <a href="http://coursedata.blogs.lincoln.ac.uk/">On Course project</a>. Soon we will have full XCRI-CAP 1.2 feed for all credit-bearing courses at all levels across the institution.</li>
<li><strong>Location data</strong> - The university’s estates department has just moved to a brand new estates management system which stores more data about campuses, buildings, floors and rooms than they have stored in one place before.</li>
<li><strong>Energy data</strong> - For almost all of the buildings on our Brayford campus we have hourly energy data readings going back as far as December 2009.</li>
<li><strong>People data</strong> - <a href="http://id.online.lincoln.ac.uk/sam/nijackson">Nick</a> and I have worked with the marketing department on developing a new staff directory which in turn powers the staff lists on the corporate website (via an RDF-XML dump!), so we already have beautifully semantically marked up staff profiles available for all members of staff.</li>
<li><strong>Bibliographic data</strong> - As part of the Jerome project, we cracked open the university library’s digital catalogues and stored the data in a sane-format (i.e. not MARC). Now through the <a href="http://clock.blogs.lincoln.ac.uk/">CLOCK project</a> the data will be semantically marked-up and compatible with other institutions bibliographic data.</li>
</ul>
<p>In the future we may be able to add event data, blog data, and who knows what else…</p>
<p>We have also recently set up <a href="http://id.online.lincoln.ac.uk/">id.lincoln.ac.uk</a> which forwards identifiers onto HTML representations e.g. <a href="http://id.online.lincoln.ac.uk/sam/abilbie">http://id.lincoln.ac.uk/sam/abilbie</a> redirects to my entry on the phone directory. This is currently a virtualhost with alias endpoints however it needs extending so that it also forwards accept headers.</p>
<p>So, our plan of action going forward is:</p>
<ol>
<li>Agree on an open data license.</li>
<li>Set up a new server which will host the data.lincoln.ac.uk platform.</li>
<li>Collect and mark-up ALL OF THE DATA.</li>
<li>Extend id.lincoln so that it forwards accept headers.</li>
<li>Document everything.</li>
</ol>
<p>Also of note, <a href="http://www.ecs.soton.ac.uk/people/cjg">Chris Gutteridge</a> has now secured the <a href="http://data.ac.uk/">data.ac.uk</a> domain and we will do everything we can to support the development of the platform and the community.</p>
<p><a href="http://alexbilbie.com/2012/04/the-future-of-data-lincoln/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>
Hello, world!http://alexbilbie.com/2012/04/hello-worldWed, 04 Apr 2012 00:00:00 +0000Alex Bilbie
<p>A new year. A new blog. Here goes. I think this is attempt 4.</p>
<p><a href="http://alexbilbie.com/2012/04/hello-world/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=rss">∞ Permalink</a</p>