Facelift time and on to WordPress 3

Well I finally upgraded to the new WordPress.

To be honest there’s not really a great deal I was interested in, although the new Twenty-Ten theme is nice.

I took the opportunity to the give the site a bit of a facelift, since it was starting to look a bit cluttered. The new theme actually allows for more content, and doesn’t feel so cramped.

I did consider for a moment, writing my own blog engine and moving the site on to Google App Engine, but then I thought of the 100 other things I’d rather be building, and sat down until the thought went away.

WordPress is pretty great for what it is. There are times when I would like to get under the covers and have a bit more control (without learning PHP), but for the most part it does everything I need and is very user friendly.

Maybe when I get that “spare time” I hear about, I’ll reconsider, but for now, I heart WP.

Posted in General | Tagged off-topic | Leave a comment

MHTML Browser Compatibility – CSS Inlining

MHTML is a technology implementing by Microsoft in Internet Explorer for packaging images, stylesheets and other resources inside a single HTML file. Typically this is used for things like help files, ebooks or other “published” content, but more recently has been proposed as a way of supporting CSS image inline in IE6 and IE7, which don’t support “Data URIs”.

MHTML is as far as I know, only implemented in Internet Explorer. And given that IE8 supports data URI’s there’s no reason to use it outside of IE6/IE7.

I’ve done some testing and, as cited in the comments of this thread on MHTML, there are issues with using MHTML to inline images in CSS on Windows Vista running IE7. This specific platform has problems and will not accept a CSS file with inlined MHTML images.

I tried fixing this, as some others have suggested, by separating the MHTML images into a separate file, and keeping the CSS by itself, referencing the MHTML file.

This appears to work — at least, it works the first time. But a subsequent reload will then display blank images. Essentially the next time it reloads from the cache, it breaks.

That pretty much rules out using MHTML on Windows Vista, since the whole point of MHTML is to load one file rather than making multiple requests. If you can’t cache the file, then there is no benefit!

What about other platforms?

Well on Windows XP, IE6 and IE7 appear to work just fine.

However – in some corporate environments there are browser security flags that may cause the inlined MHTML to not load initially. Subsequently you may get strange behaviour when the user does try to load them.

Update: I’ve resolved this one – this can occur when the MHTML content is not matched with appropriate MIME types and formatted as IE expects it. Most of the other articles about using MHTML in this manner do not adhere strictly to the MHTML format and exhibit this issue.

My Verdict

For the open-web, I’d suggest that MHTML is too much of a liability to use across the board. You really can’t be sure that people are actually seeing your site as intended.

Update: Actually, if you have a Java web app, my ResourceTransformFilter will apply MHTML in a reliable way across your application – only to the clients that can use it.

If you have a controlled environment (e.g. intranet or WAN) then MHTML might be a valid choice, since you can be sure that the browser configuration is suitable for your served content.

At least the future for Data URI’s is bright and as IE6/IE7 market share shrinks this whole issue will disappear.

Posted in Design, Software Engineering | Tagged browsers, css, performance, tips | Leave a comment

What’s In A Name? (or “my right to be an anonymous jerk on the Internets”)

I found it interesting to watch the reactions around Blizzard’s recent announcement that from now on, the community forums provided for customers to discuss their games will use the user’s real names, and not a character name or alias.

When I designed “On My Doorstep“, this was something that I gave quite a lot of thought, and came to the same decision as the one Blizzard just made.

It’s an interesting thing to consider for any web startup or application – what sort of community do you want to foster? Is it ok for people to be anonymous?

Generally we’ve shied away from using real names, I think for practical reasons (having a unique identifier for someone to log in with) and culturally (that’s the way everyone has always done it).

But, with social networking, users are encouraged to be themselves and be “celebrities in their own communities”, so to speak. As social networks merge and inter-operate with each other and web-based apps, it’s sensible to assume that our real identities will go with us to each service and community that we interact with.

I saw this as a useful thing for the type of community, I had planned for onmydoorstep.com.au.

Social sites revolve around one thing – the community of users that use them. I haven’t used a single community focused website that hasn’t experienced some amount of trolling, griefing or user-to-user abuse. It’s something of a joke actually – arguing on the Internet is probably one of the single biggest reasons for it’s success. Remember this XKCD comic -

someone is wrong in the Internet

Who hasn’t been the anonymous jerk, madly typing into the Internet to prove to some moron how wrong they are?

Pretty much everyone has done it, and had it done to them.

Certainly stuff like this happens in everyday life…. it’s not just an Internet problem?

Well, it seems to happen a lot more on the Internet, and the commonly cited reason (for both doing it and recieving it) is anonymity.

It’s a lot easier to act like an ass-hat and flame someone when you can’t be held responsible for your actions. Similarly when you’re telling “doomslayer1975” what’s what, it’s easier not to think of them as “Fred Williams, a 35 year old father of three from New Zealand who likes playing Half-life 2 and taking long walks on the beach“.

When they don’t appear as real people, you don’t have to treat them as real people.

So for “On My Doorstep“, it was apparent that for a site focused on the local community, the services, activities and events in your local neighbourhood, it was crucial that the user’s be real people. It adds to the feeling of locality, and encourages credibility and transparency in the information presented and the discussion of the users.

Was this the right decision? It’s early days yet, and the site hasn’t grown enough to know for sure.

I did receive some feedback from early users who were a little surprised to see their real names being used on the site. Other users don’t seem to be worried one way or another. So I would guess that some users may be discouraged to participate given the lack of anonymity, but others would not be phased. However I think that the potential cost in terms of engagement, is balanced in part by the quality of content and communication.

So to that end, I certainly understand what Blizzard are doing.

Robert Couse-Baker - http://www.flickr.com/photos/29233640@N07/3645211083/

One thing about Blizzard though, which is different, is that they have an existing community, that was built upon the understanding of anonymity. They also have a line of products which up until now have presented users not as themselves, but actively as fictional individuals.

It’s one thing to build a community of users who are presenting themselves, as themselves, but to change an incumbent (and vocal) community of anonymous users into a publicly-outed one, is a Big Deal…. and I think this is the source of the backlash.

There are people in that community who value the anonymity they have, and the freedom to interact under the cover it provides. Those users are going to be upset.

Other users are going to simply be adverse to change regardless of what it is. They don’t like to see anything that’s going to fragment or disrupt the community that they interact with and value… I understand where those people are coming from.

There’s probably going to be a sweeping change to Blizzard’s hosted gaming community as a result of this change. Some people will leave, they’ll find other places to go which they feel more at home in. I’m also sure that other users, both old and new will find the new community to be a better one, and stick around.

Whether Blizzard’s community grows or shrinks as a result of this decision only time will tell, but I’m sure it will be interesting to see how it all pans out.

I hope that the use of real identity becomes a trend for web applications & startups which have appropriate communities. It’s probably not something that is appropriate in every instance, but hopefully we will see some balance, and as a result an improvement in the quality of discussion and interaction provided online.

Posted in Design, Software Engineering | Tagged community, Design, soap-box | Leave a comment

Implementing Facebook OAuth 2.0 Authentication in Java

I recently switched onmydoorstep.com.au‘s Facebook login feature from the old “Facebook Connect” API implemented with facebook-java-api over to the new Facebook Graph API / OAuth 2.0 authentication.

This was far easier to implement than the original authentication, particular under Apache Wicket, but it should be easier regardless of your Java framework of choice.

Here’s how I did it.

First I developed a basic “magic” class for the Facebook API -

public class Facebook {
    // get these from your FB Dev App
    private static final String api_key = "MYAPIKEY";
    private static final String secret = "MYSECRETKEY";
    private static final String client_id = "MYCLIENTID";  

    // set this to your servlet URL for the authentication servlet/filter
    private static final String redirect_uri = "http://www.onmydoorstep.com.au/fbauth";
    /// set this to the list of extended permissions you want
    private static final String[] perms = new String[] {"publish_stream", "email"};

    public static String getAPIKey() {
        return api_key;
    }

    public static String getSecret() {
        return secret;
    }

    public static String getLoginRedirectURL() {
        return "https://graph.facebook.com/oauth/authorize?client_id=" +
            client_id + "&display=page&redirect_uri=" +
            redirect_uri+"&scope="+StringUtil.delimitObjectsToString(",", perms);
    }

    public static String getAuthURL(String authCode) {
        return "https://graph.facebook.com/oauth/access_token?client_id=" +
            client_id+"&redirect_uri=" +
            redirect_uri+"&client_secret="+secret+"&code="+authCode;
    }
}

You’ll need the visural-common library for some of the code above.

I want the “email” and “publish_stream” extended permissions, so that I can get the user’s email address and post updates back to their stream in Facebook. You can customise this list with the permissions that you need.

The process of authentication is simple.

  1. You create a link on your web UI (generally labelled “Login With Facebook” or something like that) to the Facebook.getLoginRedirectURL() URL.
  2. Facebook will authorise the user with the permissions you requested, and redirect the user to your “redirect_uri” as specified above.
  3. In a servlet or filter at your “redirect_uri” you need to
    • Retrieve the request parameter “code”
    • Make another request to the URL – Facebook.getAuthURL(request.getParameter(“code”))
    • Parse the response for the “access_token” and “expires”, assuming that it was a valid response that contained them.
  4. You use your access token to retrieve data about the user and/or make other calls to the Facebook Graph API

Due to the way Apache Wicket works, I implemented a Servlet Filter for the “redirect_uri” (/fbauth) –

public class FBOAuth implements Filter {

    public void init(FilterConfig fc) throws ServletException {
    }

    public void doFilter(ServletRequest sr, ServletResponse sr1, FilterChain fc) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest)sr;
        HttpServletResponse res = (HttpServletResponse)sr1;
        String code = sr.getParameter("code");
        if (StringUtil.isNotBlankStr(code)) {
            String authURL = Facebook.getAuthURL(code);
            URL url = new URL(authURL);
            try {
                String result = readURL(url);
                String accessToken = null;
                Integer expires = null;
                String[] pairs = result.split("&");
                for (String pair : pairs) {
                    String[] kv = pair.split("=");
                    if (kv.length != 2) {
                        throw new RuntimeException("Unexpected auth response");
                    } else {
                        if (kv[0].equals("access_token")) {
                            accessToken = kv[1];
                        }
                        if (kv[0].equals("expires")) {
                            expires = Integer.valueOf(kv[1]);
                        }
                    }
                }
                if (accessToken != null && expires != null) {
                    UserService us = UserService.get();
                    us.authFacebookLogin(accessToken, expires);
                    res.sendRedirect("http://www.onmydoorstep.com.au/");
                } else {
                    throw new RuntimeException("Access token and expires not found");
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private String readURL(URL url) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        InputStream is = url.openStream();
        int r;
        while ((r = is.read()) != -1) {
            baos.write(r);
        }
        return new String(baos.toByteArray());
    }

    public void destroy() {
    }
}

This is a cut-down version of my actual code as I do a bunch of other things on onmydoorstep.com.au which is more related to internal house-keeping and UX.

Your “UserService” might look something like -

class UserService {

    // ....

    public void authFacebookLogin(String accessToken, int expires) {
        try {
            JSONObject resp = new JSONObject(
                IOUtil.urlToString(new URL("https://graph.facebook.com/me?access_token=" + accessToken)));
            String id = resp.getString("id");
            String firstName = resp.getString("first_name");
            String lastName = resp.getString("last_name");
            String email = resp.getString("email");

            // ...
            // create and authorise the user in your current system w/ data above
            // ...

        } catch (Throwable ex) {
            throw new RuntimeException("failed login", ex);
        }
    }
}

So, just to recap, the sequence of authentication is as follows –

  1. User clicks a link on your site to Facebook.getLoginRedirectURL()
  2. Facebook asks them for their username/password to log in to your application
  3. Assuming they authenticate with Facebook, Facebook then redirects the user to your “redirect_uri” with a parameter “code” passed along.
  4. You use the “code” parameter to query the Facebook authentication service – Facebook.getAuthURL(request.getParameter(“code”))
  5. Assuming it was a valid authentication code, Facebook will pass you back an “access_token” that you can use to access the Facebook Graph API for the given user.

This could certainly be formalised into a reusable chunk of code. I may get around to adding it to visural-common, but right now there’s a lot of onmydoorstep-specific stuff in the real code.

Anyhow, hope it helps someone out!

Posted in Java, Software Engineering | Tagged facebook, Java, oauth, tips | 24 Comments