<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>n8blog &#187; HexaLex</title>
	<atom:link href="http://www.n8gray.org/blog/category/projects/hexalex/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.n8gray.org</link>
	<description>distraction in action</description>
	<lastBuildDate>Thu, 01 Jul 2010 18:21:04 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>A Simple Facebook Session Proxy for Google App Engine</title>
		<link>http://www.n8gray.org/blog/2010/06/09/a-simple-facebook-session-proxy-for-google-app-engine/</link>
		<comments>http://www.n8gray.org/blog/2010/06/09/a-simple-facebook-session-proxy-for-google-app-engine/#comments</comments>
		<pubDate>Wed, 09 Jun 2010 18:53:35 +0000</pubDate>
		<dc:creator>n8</dc:creator>
				<category><![CDATA[HexaLex]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[iOS]]></category>

		<guid isPermaLink="false">http://www.n8gray.org/?p=268</guid>
		<description><![CDATA[If you&#8217;re building an iPhone app that uses Facebook Connect you&#8217;re eventually going to need a session proxy.  The session proxy acts as a middleman between your iPhone app and Facebook&#8217;s servers, so that you don&#8217;t have to distribute your Facebook app secret with your app, where it can easily be extracted by someone [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re building an iPhone app that uses Facebook Connect you&#8217;re eventually going to need a session proxy.  The session proxy acts as a middleman between your iPhone app and Facebook&#8217;s servers, so that you don&#8217;t have to distribute your Facebook app secret with your app, where it can easily be extracted by someone knowledgeable with a hex editor.<br />
<span id="more-268"></span></p>

<p>Before I start, I should address the inevitable &#8220;what about OAuth2&#8243; comments.  Yes, OAuth2 is the new hotness for Facebook authentication, but the Facebook Connect iPhone <span class="caps">SDK </span>isn&#8217;t going to get broken (intentionally!) any time soon.  (I have that on authority from a friend inside Facebook, <span class="caps">BTW.</span>)  If you&#8217;ve got the time to replicate the functionality of <span class="caps">FBC</span>onnect for the new world order I salute you, but otherwise this code may come in handy and will continue to function until a full-featured replacement for <span class="caps">FBC</span>onnect arrives.</p>

<p>With a session proxy (say at http://your-server.example.com/fbproxy), this is how the client establishes a session:</p>


<ul>
<li>Phone:  <br />
   &#8211; <span class="caps">GET </span>http://your-server.example.com/fbproxy?auth_token=A_TOKEN&#038;&#8230;</li>
<li>To respond, your server relays the results of this <span class="caps">POST</span>: <br />
   &#8211; <span class="caps">POST</span>: http://api.facebook/com/restserver.php<br />
   &#8211; <span class="caps">POST </span>body: auth_token=A_TOKEN&#038;sig=A_SIGNATURE&#038;&#8230;</li>
</ul>



<p>A_SIGNATURE is generated using your FB app secret, so Facebook knows the request is legit.  Facebook returns a session key &#038; secret that can be used to make Facebook <span class="caps">API </span>calls from the phone.  If you&#8217;re wondering (like I did) how this is any more secure than shipping your app secret directly, you should understand that a session key is much less powerful than an app secret.  The app secret is basically the root password for your app, while a session key gets you an unprivileged user account.</p>

<p>With HexaLex I&#8217;ve used Google App Engine to host most of the backend service, so I ended up adapting some sample code I found online to do the job.  (<a href="http://code.google.com/p/minifb/">minifb</a> is particularly readable.)  I didn&#8217;t want to pull in a bunch of other dependencies, so this code is self-sufficient.  I&#8217;m using Google&#8217;s webapp framework so that&#8217;s what&#8217;s used in the code, but it should be easy to adapt to whatever framework you favor.  Without further ado, here&#8217;s the code:</p>


<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;
To use this, write in your Facebook API key and secret below and then
add FacebookSessionProxy to your list of url handlers:
    application = webapp.WSGIApplication(
        [('/fbproxy', FacebookSessionProxy),
         ...])
&nbsp;
Then in your iPhone code use something like
session = [FBSession sessionForApplication:myApiKey 
             getSessionProxy:@&quot;http://yourApp.appspot.com/fbproxy&quot;
             delegate:self];
&quot;&quot;&quot;</span>
<span style="color: #ff7700;font-weight:bold;">import</span> hashlib
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">httplib</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">urllib</span>
<span style="color: #ff7700;font-weight:bold;">from</span> google.<span style="color: black;">appengine</span>.<span style="color: black;">ext</span> <span style="color: #ff7700;font-weight:bold;">import</span> webapp
&nbsp;
<span style="color: #808080; font-style: italic;"># This lambda prevents the secret from appearing in cgitb backtraces</span>
FB_API_SECRET = <span style="color: #ff7700;font-weight:bold;">lambda</span>:<span style="color: #483d8b;">&quot;YOUR_API_SECRET&quot;</span>
FB_API_KEY = <span style="color: #483d8b;">&quot;YOUR_API_KEY&quot;</span>
&nbsp;
FB_API_HOST=<span style="color: #483d8b;">&quot;api.facebook.com&quot;</span>
FB_API_PATH=<span style="color: #483d8b;">&quot;/restserver.php&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> facebook_signature<span style="color: black;">&#40;</span>paramsDict<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Compute the signature of a Facebook request&quot;&quot;&quot;</span>
    <span style="color: #008000;">sorted</span> = paramsDict.<span style="color: black;">items</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">sorted</span>.<span style="color: black;">sort</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    trace = <span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;%s=%s&quot;</span> <span style="color: #66cc66;">%</span> x <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">sorted</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    trace += FB_API_SECRET<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #dc143c;">md5</span> = hashlib.<span style="color: #dc143c;">md5</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">md5</span>.<span style="color: black;">update</span><span style="color: black;">&#40;</span>trace<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #dc143c;">md5</span>.<span style="color: black;">hexdigest</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> get_fb_session<span style="color: black;">&#40;</span>auth_token<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Request a Facebook session using the given auth_token&quot;&quot;&quot;</span>
    params=<span style="color: black;">&#123;</span>
            <span style="color: #483d8b;">&quot;api_key&quot;</span>:FB_API_KEY,
            <span style="color: #483d8b;">&quot;v&quot;</span>:<span style="color: #483d8b;">&quot;1.0&quot;</span>,
            <span style="color: #483d8b;">&quot;auth_token&quot;</span>:auth_token,
            <span style="color: #483d8b;">&quot;generate_session_secret&quot;</span>:<span style="color: #483d8b;">&quot;1&quot;</span>,
            <span style="color: #483d8b;">&quot;method&quot;</span>:<span style="color: #483d8b;">&quot;auth.getSession&quot;</span>,
    <span style="color: black;">&#125;</span>
    params<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;sig&quot;</span><span style="color: black;">&#93;</span> = facebook_signature<span style="color: black;">&#40;</span>params<span style="color: black;">&#41;</span>
&nbsp;
    encoded_params = <span style="color: #dc143c;">urllib</span>.<span style="color: black;">urlencode</span><span style="color: black;">&#40;</span>params<span style="color: black;">&#41;</span>
    headers = <span style="color: black;">&#123;</span>
            <span style="color: #483d8b;">&quot;Content-type&quot;</span>:<span style="color: #483d8b;">&quot;application/x-www-form-urlencoded&quot;</span>,
    <span style="color: black;">&#125;</span>
&nbsp;
    conn = <span style="color: #dc143c;">httplib</span>.<span style="color: black;">HTTPConnection</span><span style="color: black;">&#40;</span>FB_API_HOST<span style="color: black;">&#41;</span>
    conn.<span style="color: black;">request</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;POST&quot;</span>, FB_API_PATH, encoded_params, headers<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> conn.<span style="color: black;">getresponse</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> FacebookSessionProxy<span style="color: black;">&#40;</span>webapp.<span style="color: black;">RequestHandler</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> get<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        response = <span style="color: #008000;">self</span>.<span style="color: black;">response</span>
        auth_token = <span style="color: #008000;">self</span>.<span style="color: black;">request</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'auth_token'</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>auth_token<span style="color: black;">&#41;</span> == <span style="color: #ff4500;">0</span>:
            response.<span style="color: black;">set_status</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">httplib</span>.<span style="color: black;">BAD_REQUEST</span><span style="color: black;">&#41;</span>
            response.<span style="color: black;">out</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Facebook login error: no auth_token given.&quot;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">return</span>
        fbResponse = get_fb_session<span style="color: black;">&#40;</span>auth_token<span style="color: black;">&#41;</span>
        response.<span style="color: black;">out</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span>fbResponse.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        response.<span style="color: black;">set_status</span><span style="color: black;">&#40;</span>fbResponse.<span style="color: black;">status</span>, fbResponse.<span style="color: black;">reason</span><span style="color: black;">&#41;</span>
        response.<span style="color: black;">headers</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'Content-Type'</span><span style="color: black;">&#93;</span> = fbResponse.<span style="color: black;">getheader</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'content-type'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># The End</span></pre></div></div>




<p><strong>Update</strong>: I fixed a bug in the call to get_fb_session.  Thanks to Justin Williams for reporting it.</p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fwww.n8gray.org%2Fblog%2F2010%2F06%2F09%2Fa-simple-facebook-session-proxy-for-google-app-engine%2F&amp;linkname=A%20Simple%20Facebook%20Session%20Proxy%20for%20Google%20App%20Engine"><img src="http://www.n8gray.org/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://www.n8gray.org/blog/2010/06/09/a-simple-facebook-session-proxy-for-google-app-engine/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>World, meet HexaLex for iPhone</title>
		<link>http://www.n8gray.org/blog/2009/12/09/world-meet-hexalex-for-iphone/</link>
		<comments>http://www.n8gray.org/blog/2009/12/09/world-meet-hexalex-for-iphone/#comments</comments>
		<pubDate>Wed, 09 Dec 2009 22:00:08 +0000</pubDate>
		<dc:creator>n8</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[HexaLex]]></category>

		<guid isPermaLink="false">http://www.n8gray.org/?p=184</guid>
		<description><![CDATA[
Some of you have probably noticed that I&#8217;ve been neglecting some of my other projects and complaining about being busy a lot lately.  Well here&#8217;s what I&#8217;ve been working on.  I&#8217;m pleased to announce HexaLex, a new angle on crossword games!  The first platform for HexaLex is iPhone and iPod Touch, but [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://hexalex.com"><img src="http://www.n8gray.org/wp-content/uploads/2009/12/Hexalex-logo.png" alt="Hexalex-logo" title="The HexaLex Logo" width="286" height="112" class="aligncenter clearnone noborder size-full wp-image-186" /></a></p>

    <div class="alignleft">
    <script type="text/javascript"> digg_url = "http://digg.com/apple/Scrabble_Gets_Hexed";</script>
    <script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script>
    </div>

<p>Some of you have probably noticed that I&#8217;ve been neglecting <a href="http://www.n8gray.org/blog/2007/12/03/announcing-qlcolorcode/">some of</a> <a href="http://www.n8gray.org/blog/2007/04/27/introducing-backup-bouncer/">my other projects</a> and complaining about being busy a lot lately.  Well here&#8217;s what I&#8217;ve been working on.  I&#8217;m pleased to announce <a href="http://hexalex.com">HexaLex, a new angle on crossword games</a>!  The first platform for HexaLex is iPhone and iPod Touch, but I&#8217;m planning to expand to Facebook in the near future.</p>
<div id="attachment_192" class="wp-caption alignright" style="width: 218px"><a href="http://www.n8gray.org/wp-content/uploads/2009/12/game.png"><img src="http://www.n8gray.org/wp-content/uploads/2009/12/game-208x300.png" alt="HexaLex as it looks in-game" title="game" width="208" height="300" class="size-medium wp-image-192" /></a><p class="wp-caption-text">HexaLex as it looks in-game</p></div>
<p>If you want to get a quick overview of the game and a list of features go ahead and visit <a href="http://hexalex.com">the HexaLex.com website</a>.  If you want to read some great 5-star reviews or buy the game just pop on over to <a href="http://itunes.apple.com/us/app/hexalex/id337380581?mt=8">the App Store</a>.  Continue reading for a little more detail on the core concept of the game.</p>
<p>HexaLex is an idea I came up with a little over a year ago as a grad student.  The core gameplay is a lot like Scrabble, Words With Friends, or Lexulous, so if you&#8217;ve played one of those games you&#8217;ll get the idea right away.  You use tiles to build words on a game board.  But HexaLex has a big difference &#8212; it&#8217;s played with hexagonal tiles.  Looks interesting, right?</p>
<p>Playing a crossword game with hexagonal tiles sounds like a simple idea but it actually requires a bit of creative thinking to make it playable and fun.  (This is probably why it hasn&#8217;t been done a million times already!)  You see, when two words cross with square tiles they only interact at one tile &#8212; the tile of intersection.  With hexagonal tiles, that&#8217;s not the case.  Hex tiles cause interactions at the tile of intersection <em>and</em> its neighbors!  This means that playing one word across another word also forms two new two-letter words.  This is sort of hard to describe, but easy to see as a picture (like the one below).</p>
<div id="attachment_187" class="wp-caption alignleft" style="width: 227px"><img src="http://www.n8gray.org/wp-content/uploads/2009/12/start-crazy.png" alt="Crossing START with CRAZY forms RT and RZ" title="start-crazy" width="217" height="147" class="clearboth imgborder size-full wp-image-187" /><p class="wp-caption-text">Crossing START with CRAZY forms RT and RZ</p></div>
<p>Traditionally, in crossword games you have to make every word on the board valid.  If you just take the standard rules and try to use them with hexagonal tiles you&#8217;ll quickly discover that the game is unplayably hard.  It&#8217;s just frustrating to have to work out two valid two-letter words for each and every crossing play.</p>
<p>The way I solved this in HexaLex was to introduce the idea of <em>junk words</em>.  A junk word is a two-letter word that&#8217;s not a valid word.  So XR, TQ, and ZA are examples of junk words.  (Oops, ZA is actually a valid word, at least in the strange world of crossword games.)  In HexaLex you are allowed to play junk words subject to a few restrictions:</p>
<div id="attachment_201" class="wp-caption alignright" style="width: 218px"><a href="http://www.n8gray.org/wp-content/uploads/2009/12/main-menu.png"><img src="http://www.n8gray.org/wp-content/uploads/2009/12/main-menu-208x300.png" alt="The main menu features a sliding word animation" title="The main menu" width="208" height="300" class="size-medium wp-image-201" /></a><p class="wp-caption-text">The main menu features a sliding word animation</p></div>
<div>
<ul>
<li>You can only play 2 of them per turn</li>
<li>You can&#8217;t use a junk word as your only link to the tiles that are already on the board.</li>
<li>You don&#8217;t get any points for junk words</li>
</ul>
</div>
<p>With junk words, a simple play of one word crossing another is always possible provided the two words share a letter.  The game is playable once again and balance is restored!</p>
<p>So now you know that when you look at a HexaLex game it&#8217;s OK that some of the two-letter words are bogus, but all of the longer words have to be legit.</p>
<p>Junk words aren&#8217;t the only break from Scrabble tradition in HexaLex but I&#8217;ll leave the rest for another post.  <img src='http://www.n8gray.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

    <div class="alignleft">
    <script type="text/javascript"> digg_url = "http://digg.com/apple/Scrabble_Gets_Hexed";</script>
    <script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script>
    </div>

<p>HexaLex is available now in the App Store.   Give it a shot!  Initial App Store reviews have been overwhelmingly positive, with fourteen unanimous 5-star ratings and reviews so far.  If you enjoy HexaLex please let me know!  You can also <a target="_blank" href="http://www.facebook.com/pages/HexaLex/329287970006">become a HexaLex fan on Facebook</a> and/or <a target="_blank" href="http://twitter.com/hexalexgame">follow HexaLexGame on Twitter</a>.  Also, please help spread the word by clicking the digg button!</p>
<p><a href="http://hexalex.com"><img src="http://www.n8gray.org/wp-content/uploads/2009/12/get-hexalex.png" alt="Get HexaLex" title="Get HexaLex" width="159" height="57" class="aligncenter noborder size-full wp-image-206" /></a></p>
<div class="aligncenter" style="width:72px">
<a target="_blank" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fwww.n8gray.org%2Fblog%2F2009%2F12%2F09%2Fworld-meet-hexalex-for-iphone%2F&#038;t=World%2C%20meet%20HexaLex%20for%20iPhone"><img src="http://www.n8gray.org/wp-content/uploads/2009/12/facebookicon.png" alt="Share on Facebook" title="Share on Facebook" width="32" height="32" class="noborder size-full wp-image-234" /></a> <a target="_blank" href="http://twitter.com/home?status=World%2C%20meet%20HexaLex%20for%20iPhone.%20Like%20Scrabble%20with%20hexagonal%20tiles%3A%20http%3A%2F%2Fbit.ly%2F7drkeN"><img src="http://www.n8gray.org/wp-content/uploads/2009/12/twittericon.png" alt="Tweet this" title="Tweet this" width="32" height="32" class="noborder size-full wp-image-233" /></a>
</div>
<p><img src="http://www.n8gray.org/wp-content/uploads/2009/12/Icon-rounded-75x75.png" alt="The HexaLex Icon" title="The HexaLex Icon" width="75" height="75" class="aligncenter size-full wp-image-245" /></p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fwww.n8gray.org%2Fblog%2F2009%2F12%2F09%2Fworld-meet-hexalex-for-iphone%2F&amp;linkname=World%2C%20meet%20HexaLex%20for%20iPhone"><img src="http://www.n8gray.org/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://www.n8gray.org/blog/2009/12/09/world-meet-hexalex-for-iphone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

