<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Ole Riesenberg]]></title>
  <link href="http://oleriesenberg.com/atom.xml" rel="self"/>
  <link href="http://oleriesenberg.com/"/>
  <updated>2015-12-14T00:29:42+01:00</updated>
  <id>http://oleriesenberg.com/</id>
  <author>
    <name><![CDATA[Ole Riesenberg]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Facebook Graph API With FBML Canvas Apps]]></title>
    <link href="http://oleriesenberg.com/blog/2010/07/22/facebook-graph-api-with-fbml-canvas-apps/"/>
    <updated>2010-07-22T09:12:00+02:00</updated>
    <id>http://oleriesenberg.com/blog/2010/07/22/facebook-graph-api-with-fbml-canvas-apps</id>
    <content type="html"><![CDATA[<p>Facebook is now sending a new parameter to canvas applications, <em>signed_request</em>.
This parameter is the concatenation of a JSON object and a signature, both Base64 encoded.
The JSON object contains 4 other parameters:</p>

<p><strong>user_id</strong>: <em>ID of the logged in user</em><br />
<strong>oauth_token</strong>: <em>The users OAuth access token</em><br />
<strong>expires</strong>: <em>When the token expires</em> <br />
<strong>profile_id</strong>: <em>ID of the profile when rendered in tab</em></p>

<p>The signature is a HMAC-SHA265 of the JSON and is needed to verify that the request originates from Facebook.</p>

<p>With this new parameter it&rsquo;s finally possible to use the Graph API in an affordably way with FBML apps.
Just store the access token in your users session and pass it along with your Graph API requests.</p>

<h3>Parsing signed_request</h3>

<p>I implemented support for the <em>signed_request</em> to my Facebook library for Rails.
The code I&rsquo;m using for verifying the signature and adding the JSON params to the Rails params via Rack middleware looks like this (extract):</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">ParamsParser</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">app</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">condition</span><span class="p">)</span>
</span><span class='line'>    <span class="vi">@app</span> <span class="o">=</span> <span class="n">app</span>
</span><span class='line'>    <span class="vi">@condition</span> <span class="o">=</span> <span class="n">condition</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">call</span><span class="p">(</span><span class="n">env</span><span class="p">)</span>
</span><span class='line'>    <span class="n">request</span> <span class="o">=</span> <span class="no">Rack</span><span class="o">::</span><span class="no">Request</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">env</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">signed_request</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">params</span><span class="o">[</span><span class="s2">&quot;signed_request&quot;</span><span class="o">]</span>
</span><span class='line'>    <span class="n">signature</span><span class="p">,</span> <span class="n">signed_params</span> <span class="o">=</span> <span class="n">signed_request</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;.&#39;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1"># Verify signature</span>
</span><span class='line'>    <span class="k">unless</span> <span class="n">signed_request_is_valid?</span><span class="p">(</span><span class="no">FB</span><span class="o">[</span><span class="s1">&#39;secret&#39;</span><span class="o">]</span><span class="p">,</span> <span class="n">signature</span><span class="p">,</span> <span class="n">signed_params</span><span class="p">)</span>
</span><span class='line'>      <span class="k">return</span> <span class="no">Rack</span><span class="o">::</span><span class="no">Response</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="o">[</span><span class="s2">&quot;Invalid Facebook signature&quot;</span><span class="o">]</span><span class="p">,</span> <span class="mi">400</span><span class="p">)</span><span class="o">.</span><span class="n">finish</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1"># Parse JSON</span>
</span><span class='line'>    <span class="n">signed_params</span> <span class="o">=</span> <span class="no">Yajl</span><span class="o">::</span><span class="no">Parser</span><span class="o">.</span><span class="n">new</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">base64_url_decode</span><span class="p">(</span><span class="n">signed_params</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1"># Add JSON parameters to Rails params</span>
</span><span class='line'>    <span class="n">signed_params</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">k</span><span class="p">,</span><span class="n">v</span><span class="o">|</span>
</span><span class='line'>      <span class="n">request</span><span class="o">.</span><span class="n">params</span><span class="o">[</span><span class="n">k</span><span class="o">]</span> <span class="o">=</span> <span class="n">v</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>    <span class="vi">@app</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="n">env</span><span class="p">)</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="kp">private</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">signed_request_is_valid?</span><span class="p">(</span><span class="n">secret</span><span class="p">,</span> <span class="n">signature</span><span class="p">,</span> <span class="n">params</span><span class="p">)</span>
</span><span class='line'>    <span class="n">signature</span> <span class="o">=</span> <span class="n">base64_url_decode</span><span class="p">(</span><span class="n">signature</span><span class="p">)</span>
</span><span class='line'>    <span class="n">expected_signature</span> <span class="o">=</span> <span class="no">OpenSSL</span><span class="o">::</span><span class="no">HMAC</span><span class="o">.</span><span class="n">digest</span><span class="p">(</span>
</span><span class='line'>      <span class="s1">&#39;SHA256&#39;</span><span class="p">,</span> <span class="n">secret</span><span class="p">,</span> <span class="n">params</span><span class="o">.</span><span class="n">tr</span><span class="p">(</span><span class="s2">&quot;-_&quot;</span><span class="p">,</span> <span class="s2">&quot;+/&quot;</span><span class="p">))</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">signature</span> <span class="o">==</span> <span class="n">expected_signature</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1"># Stolen from mini_fb.</span>
</span><span class='line'>  <span class="c1"># Ruby&#39;s implementation of base64 decoding reads the string in multiples of</span>
</span><span class='line'>  <span class="c1"># 6 and ignores any extra bytes.</span>
</span><span class='line'>  <span class="c1"># Since facebook does not take this into account, this function fills any</span>
</span><span class='line'>  <span class="c1"># string with white spaces up to</span>
</span><span class='line'>  <span class="c1"># the point where it becomes divisible by 6, then it replaces &#39;-&#39; with &#39;+&#39;</span>
</span><span class='line'>  <span class="c1"># and &#39;_&#39; with &#39;/&#39; (URL-safe decoding),</span>
</span><span class='line'>  <span class="c1"># and decodes the result.</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">base64_url_decode</span><span class="p">(</span><span class="n">str</span><span class="p">)</span>
</span><span class='line'>    <span class="n">str</span> <span class="o">=</span> <span class="n">str</span> <span class="o">+</span> <span class="s2">&quot;=&quot;</span> <span class="o">*</span> <span class="p">(</span><span class="mi">6</span> <span class="o">-</span> <span class="n">str</span><span class="o">.</span><span class="n">size</span> <span class="o">%</span> <span class="mi">6</span><span class="p">)</span> <span class="k">unless</span> <span class="n">str</span><span class="o">.</span><span class="n">size</span> <span class="o">%</span> <span class="mi">6</span> <span class="o">==</span> <span class="mi">0</span>
</span><span class='line'>    <span class="k">return</span> <span class="no">Base64</span><span class="o">.</span><span class="n">decode64</span><span class="p">(</span><span class="n">str</span><span class="o">.</span><span class="n">tr</span><span class="p">(</span><span class="s2">&quot;-_&quot;</span><span class="p">,</span> <span class="s2">&quot;+/&quot;</span><span class="p">))</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Using the Graph API</h3>

<p>Using the Graph API is just as simple as this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>curl https://graph.facebook.com/me?access_token<span class="o">=</span>YOUR_TOKEN
</span></code></pre></td></tr></table></div></figure>


<p>This will respond with a JSON object containing your basic user info.</p>

<p>Talking to the Graph API with Ruby / HTTParty is not much more complicated then using curl:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="no">HTTParty</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;https://graph.facebook.com/me&quot;</span><span class="p">,</span> <span class="ss">:access_token</span> <span class="o">=&gt;</span> <span class="s2">&quot;YOUR TOKEN&quot;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Old params deprecation</h3>

<p>In the future Facebook will deprecate all other parameters than <em>signed_request</em>, but there&rsquo;s no exact timing right now.</p>

<p>There&rsquo;s some official documentation on how to migrate from the old params to <em>signed_request</em> available at <a href="http://developers.facebook.com/docs/authentication/canvas">developers.facebook.com</a>.</p>

<h3>UPDATE 2010-07-26</h3>

<p>Facebook silently stopped sending the <em>signed_request</em> parameter.</p>

<p>You can enable them again by activating the &ldquo;OAuth 2.0 for Canvas (beta)&rdquo; migration in you app settings on Facebook, but this disables all other parameters. So make sure to <a href="http://developers.facebook.com/docs/authentication/canvas">migrate your app to only rely on signed_request</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Bitly API]]></title>
    <link href="http://oleriesenberg.com/blog/2009/07/10/bitly-api/"/>
    <updated>2009-07-10T13:28:26+02:00</updated>
    <id>http://oleriesenberg.com/blog/2009/07/10/bitly-api</id>
    <content type="html"><![CDATA[<p>I created a small and simple library to access the <a href="http://bit.ly">bitly</a> API.</p>

<p>Usage is simple:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="o">&gt;&gt;</span> <span class="n">api</span> <span class="o">=</span> <span class="no">BitlyApi</span><span class="o">::</span><span class="no">Bitly</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="ss">:login</span> <span class="o">=&gt;</span> <span class="no">BITLY_LOGIN</span><span class="p">,</span> <span class="ss">:api_key</span> <span class="o">=&gt;</span> <span class="no">BITLY_API_KEY</span><span class="p">)</span>
</span><span class='line'><span class="o">=&gt;</span> <span class="c1">#&lt;BitlyApi::Bitly:0x7f93177c87e0 @api_version=&quot;2.0.1&quot;, @api_key=BITLY_API_KEY, @login=BITLY_LOGIN&gt;</span>
</span><span class='line'><span class="o">&gt;&gt;</span> <span class="n">api</span><span class="o">.</span><span class="n">shorten</span> <span class="s2">&quot;http://pickhost.eu&quot;</span>
</span><span class='line'><span class="o">=&gt;</span> <span class="p">{</span><span class="s2">&quot;userHash&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;2wzb4d&quot;</span><span class="p">,</span> <span class="s2">&quot;hash&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;zNgN6&quot;</span><span class="p">,</span> <span class="s2">&quot;shortKeywordUrl&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;shortUrl&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;http://bit.ly/2wzb4d&quot;</span><span class="p">}</span>
</span><span class='line'><span class="o">&gt;&gt;</span> <span class="n">api</span><span class="o">.</span><span class="n">expand</span> <span class="s2">&quot;2wzb4d&quot;</span>
</span><span class='line'><span class="o">=&gt;</span> <span class="p">{</span><span class="s2">&quot;longUrl&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;http://pickhost.eu/&quot;</span><span class="p">}</span>
</span><span class='line'><span class="o">&gt;&gt;</span> <span class="n">api</span><span class="o">.</span><span class="n">stats</span> <span class="s2">&quot;2wzb4d&quot;</span>
</span><span class='line'><span class="o">=&gt;</span> <span class="p">{</span><span class="s2">&quot;userClicks&quot;</span><span class="o">=&gt;</span><span class="mi">1</span><span class="p">,</span> <span class="s2">&quot;referrers&quot;</span><span class="o">=&gt;</span><span class="p">{</span><span class="s2">&quot;&quot;</span><span class="o">=&gt;</span><span class="p">{</span><span class="s2">&quot;direct&quot;</span><span class="o">=&gt;</span><span class="mi">1</span><span class="p">}},</span> <span class="s2">&quot;userHash&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;2wzb4d&quot;</span><span class="p">,</span> <span class="s2">&quot;hash&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;zNgN6&quot;</span><span class="p">,</span> <span class="s2">&quot;clicks&quot;</span><span class="o">=&gt;</span><span class="mi">1</span><span class="p">,</span> <span class="s2">&quot;userReferrers&quot;</span><span class="o">=&gt;</span><span class="p">{</span><span class="s2">&quot;&quot;</span><span class="o">=&gt;</span><span class="p">{</span><span class="s2">&quot;direct&quot;</span><span class="o">=&gt;</span><span class="mi">1</span><span class="p">}}}</span>
</span><span class='line'><span class="o">&gt;&gt;</span> <span class="n">api</span><span class="o">.</span><span class="n">info</span> <span class="s2">&quot;2wzb4d&quot;</span>
</span><span class='line'><span class="o">=&gt;</span> <span class="p">{</span><span class="s2">&quot;thumbnail&quot;</span><span class="o">=&gt;</span><span class="p">{</span><span class="s2">&quot;small&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;http://s.bit.ly/bitly/zNgN6/thumbnail_small.png&quot;</span><span class="p">,</span> <span class="s2">&quot;medium&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;http://s.bit.ly/bitly/zNgN6/thumbnail_medium.png&quot;</span><span class="p">,</span> <span class="s2">&quot;large&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;http://s.bit.ly/bitly/zNgN6/thumbnail_large.png&quot;</span><span class="p">},</span> <span class="s2">&quot;id3&quot;</span><span class="o">=&gt;</span><span class="p">{},</span> <span class="s2">&quot;userHash&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;2wzb4d&quot;</span><span class="p">,</span> <span class="s2">&quot;hash&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;zNgN6&quot;</span><span class="p">,</span> <span class="s2">&quot;mirrorUrl&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;htmlMetaDescription&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;An image hosting service with simplicity and speed in mind.&quot;</span><span class="p">,</span> <span class="s2">&quot;version&quot;</span><span class="o">=&gt;</span><span class="mi">1</span><span class="o">.</span><span class="mi">0</span><span class="p">,</span> <span class="s2">&quot;htmlTitle&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;Pic(k)host :: Upload your Images!&quot;</span><span class="p">,</span> <span class="s2">&quot;globalHash&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;zNgN6&quot;</span><span class="p">,</span> <span class="s2">&quot;calaisId&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;calais&quot;</span><span class="o">=&gt;</span><span class="p">{},</span> <span class="s2">&quot;users&quot;</span><span class="o">=&gt;[</span><span class="s2">&quot;pickhost&quot;</span><span class="o">]</span><span class="p">,</span> <span class="s2">&quot;surbl&quot;</span><span class="o">=&gt;</span><span class="mi">0</span><span class="p">,</span> <span class="s2">&quot;longUrl&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;http://pickhost.eu/&quot;</span><span class="p">,</span> <span class="s2">&quot;htmlMetaKeywords&quot;</span><span class="o">=&gt;[</span><span class="s2">&quot;Bilder hochladen&quot;</span><span class="p">,</span> <span class="s2">&quot;Bilder upload&quot;</span><span class="p">,</span> <span class="s2">&quot;Foto upload&quot;</span><span class="p">,</span> <span class="s2">&quot;Bilderhoster&quot;</span><span class="p">,</span> <span class="s2">&quot;Imagehoster&quot;</span><span class="p">,</span> <span class="s2">&quot;Foto&quot;</span><span class="p">,</span> <span class="s2">&quot;Bild&quot;</span><span class="p">,</span> <span class="s2">&quot;Photo&quot;</span><span class="p">,</span> <span class="s2">&quot;Image&quot;</span><span class="p">,</span> <span class="s2">&quot;Pic&quot;</span><span class="p">,</span> <span class="s2">&quot;Hoster&quot;</span><span class="o">]</span><span class="p">,</span> <span class="s2">&quot;contentType&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;text/html; charset=utf-8&quot;</span><span class="p">,</span> <span class="s2">&quot;keyword&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;exif&quot;</span><span class="o">=&gt;</span><span class="p">{},</span> <span class="s2">&quot;contentLength&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;shortenedByUser&quot;</span><span class="o">=&gt;</span><span class="s2">&quot;pickhost&quot;</span><span class="p">,</span> <span class="s2">&quot;metacarta&quot;</span><span class="o">=&gt;[]</span><span class="p">,</span> <span class="s2">&quot;keywords&quot;</span><span class="o">=&gt;[]</span><span class="p">,</span> <span class="s2">&quot;calaisResolutions&quot;</span><span class="o">=&gt;</span><span class="p">{}}</span>
</span></code></pre></td></tr></table></div></figure>


<p>The project is located at <a href="http://github.com/oleriesenberg/bitly-api">GitHub</a>.</p>
]]></content>
  </entry>
  
</feed>
