In my last two posts, I wrote about how I’ve been thinking about building yet another microblogging tool and how I think it might be interesting to separate web publishing apps from web hosting. Well, I started tinkering, and I’ve got a rough prototype working.

S3 is not simple enough

When I think about dead simple web hosting, the first thing that comes to mind is Amazon S3. I’ve been a fan of S3 for long enough that digging up my old code freaked me out.

There’s not much to the API: GET, PUT, & DELETE web content in URLspace under a “bucket” that you pay for by the byte. Overall S3 fits my criteria of “dead simple hosting service” rather nicely.

Amazon S3 is super cheap. I’ve never paid much more than US$0.50 in a month, and that’s even when I was experimenting with a public-access wiki built atop the service that folks from Amazon itself were playing with. I’ll probably move my blog there, someday, once I get the notion to revisit static site generators again.

Amazon S3 is, however, a professional’s tool. It expects documentation to be read and training to be had. For a busy person with non-developer things do to, it’s a twisty maze of passages, all alike. That makes it a poor consumer product.

So, I wondered: How hard would it be to smooth over some of the rough parts and make the experience almost as easy as a normal social media site?

Login with Amazon

First, the on-ramp has to be easy. Filling out a form with username, password, nickname, and email address would be an okay start. (Billing info would be nice, too, but let’s not go there quite yet.)

What would be even better, though, is to click one button and reuse data already filled out elsewhere! Filling out forms with personal data is part of the problem web wonks call “identity”. Apropos of that, did you know that Amazon has an identity service? I didn’t, at least not until last weekend. (Man, am I behind!)

I can put a “Login with Amazon” button on my web app. You login with your Amazon username & password, but my app doesn’t see them. Instead, Amazon offers my app some simple profile details – user ID, email, & full name.

But, having access to your Amazon identity offers even more power:

  • Clicking “Login with Amazon” gives your Amazon identity to my app.
  • My app can use your Amazon identity to assume a temporary role.
  • This temporary role enables use of a portion of an S3 bucket.
  • This is hewing pretty close to the publishing app / hosting service notions I laid out in my last post. So, how does it work?

    Well, one of the things my app receives when you click the “Login” button is an access_token. Chasing that access_token down the rabbit hole, I rediscovered Amazon IAM and STS – Identity & Access Management and Secure Token Service.

    IAM and Roles

    Among other things, Amazon IAM lets you define roles and associate them with apps. Roles contain policies that grant access to resources controlled by your account – e.g. an S3 bucket.

    For example, here’s a policy snippet for a role I created on IAM:

    {
     "Effect": "Allow",
     "Action": [
       "s3:PutObject",
       "s3:PutObjectAcl",
       "s3:DeleteObject",
       "s3:GetObject",
       "s3:GetObjectAcl"
     ],
     "Resource": [
       "arn:aws:s3:::tootr/users/amazon/${www.amazon.com:user_id}",
       "arn:aws:s3:::tootr/users/amazon/${www.amazon.com:user_id}/*"
     ]
    }

    This role grants access to GET, PUT, & DELETE web resources in my S3 bucket named “tootr” – but only as long as the resources are under the “users/amazon/{USER_ID}” URLspace, where {USER_ID} is a uniquely generated identifier supplied by an Amazon profile.

    STS and Temporary Credentials

    So, how can someone assume such a role? That’s where Amazon STS comes in:

    $.ajax('https://sts.amazonaws.com/?' + $.param({
    
      'Action': 'AssumeRoleWithWebIdentity',
      'Version': '2011-06-15',
      'RoleArn': 'arn:aws:iam::8675309:role/tootr-amazon-user-buckets',
      'RoleSessionName': 'web-identity-federation',
      'ProviderId': 'www.amazon.com',
      'DurationSeconds': '900',
      'WebIdentityToken': access_token
    
    })).then(function (dataXML, status, xhr) {
    
      var data = misc.xmlToObj(dataXML);
      var credentials = data
        .AssumeRoleWithWebIdentityResponse
        .AssumeRoleWithWebIdentityResult
        .Credentials;
    
    });

    The RoleArn parameter identifies the IAM role created earlier. The access_token is what my app got when you logged in. The AssumeRoleWithWebIdentity API on Amazon STS lets me connect the two and generate temporary credentials.

    Those credentials look something like this:

    {
      "SessionToken":"NIweiunfiunIUWNLFIsd87",
      "Expiration":"2014-10-11T19:15:58Z",
      "AccessKeyId":"ASIAQWERTYUIOP",
      "SecretAccessKey":"SKLN9869KJnisdhfli"
    }

    As it turns out, these credentials work with Amazon S3. So, after accepting a login and doing the AssumeRoleWithWebIdentity dance, my app can manage web hosting at Amazon S3 on your behalf.

    For further reading, check out “Creating Temporary Security Credentials for Mobile Apps Using Identity Providers” in Amazon’s documentation. That’s from where I stole most of this stuff.

    Demo time and next steps

    I’ve rolled all of this into a microblogging app called “tootr”. Here’s a demo:

  • https://lmorchard.github.io/tootr/
  • You can visit the app, click “Login with Amazon”, and you’ll soon be tooting up a storm. But, you should notice some serious drawbacks:

    • The app is terrible and missing almost every interesting feature.
    • Your username is something like AF5OSES2YSFJEKYBANBHRFB25RXQ and that’s also terrible.
    • You’re tooting into my Amazon S3 bucket. You’re not paying me or Amazon. I will vandalize & delete your stuff and not feel bad about it.

    As a proof-of-concept, though, I think it works: The “tootr” app at lmorchard.github.io publishes to a hosting API at s3.amazonaws.com. The on-ramp is a single button click and an Amazon sign-in dialog.

    But, I think all the above issues can be addressed. Also, Amazon is an interesting core for this stuff: Many people have an Amazon account, and Amazon is a place where people generally pay for things. So, it’s different territory than most social media sites.

    The challenge will be keeping the on-ramp simple while improving the app and switching to a user-owned web hosting space. Still, I think this is promising stuff. At any rate, it’s tinkering I’ve been procrastinating for years now, so I’ve got plenty of ideas to chase down.