<?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>Veggerby : IBlog &#187; OAuth</title>
	<atom:link href="http://blog.veggerby.dk/category/oauth/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.veggerby.dk</link>
	<description>Low decoupling, highly incoherent</description>
	<lastBuildDate>Fri, 28 May 2010 19:47:45 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>OAuth for Dummies</title>
		<link>http://blog.veggerby.dk/2009/10/06/oauth-for-dummies/</link>
		<comments>http://blog.veggerby.dk/2009/10/06/oauth-for-dummies/#comments</comments>
		<pubDate>Tue, 06 Oct 2009 20:40:00 +0000</pubDate>
		<dc:creator>nosey</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[OAuth]]></category>

		<guid isPermaLink="false">http://blog.veggerby.dk/2009/09/29/oauth-for-dummies/</guid>
		<description><![CDATA[Having developed a little feature where I had to publish a Tweet to uh… Twitter, I did a checkup on how OAuth actually works. If you have the time you can go through Beginner’s Guide to OAuth, which is really excellent and was my source or introduction to OAuth. I’ll just condense it a little [...]]]></description>
			<content:encoded><![CDATA[<p>Having developed a little feature where I had to publish a Tweet to uh… <a href="http://twitter.com/">Twitter</a>, I did a checkup on how <a href="http://oauth.net/">OAuth</a> actually works. If you have the time you can go through <a href="http://hueniverse.com/oauth/">Beginner’s Guide to OAuth</a>, which is really excellent and was my source or introduction to OAuth. I’ll just condense it a little further, mostly because it is a good way to actually “get it”.</p>
<h2>What is OAuth?</h2>
<p><strong>OAUth makes it possible for providers to communicate in a secure and authenticated manor, without needing to share user secrets (username/password).</strong> For example it can allow the users of my web application to post Tweets to their Twitter account without needing to specify their username and password (except if the need to login to the Twitter site).</p>
<h2>Who is involved?</h2>
<p>Just to set the scene and get into the terms used, the actors involved are:</p>
<p>We want to get access to the <strong>Service Provider</strong>, e.g. Twitter.</p>
<p>The <strong>Consumer </strong>would like to access a resource on the Service Provider, e.g. my application.</p>
<p>The <strong>User</strong> want to access a resource on the Service Provider via the Consumer, e.g. post a Tweet using my application.</p>
<h2>How does it work?</h2>
<p>Seen from a larger perspective the idea is that the 3 actors (the Service Provider, the Consumer and the User) communicate with each other in such a way that all agree on who is who.</p>
<p>In more technical terms, all 3 actors generates and present various tokens (share secrets) to each other, which when combined establishes a trusted relationship between the Consumer and the Service Provider on behalf of the User.</p>
<h3>Step-by-Step</h3>
<p>A User want to perform an action on the Consumer which requires access to the/a protected resource on the Service Provider, e.g. create a Tweet.</p>
<ol>
<li>The Consumer contacts the Service Provider, requesting a <strong>Request Token</strong> and a <strong>Request Secret</strong>. </li>
<li>The User (e.g. his/her browser) is then redirected to the Service Provider presenting the <strong>Request Token</strong>. </li>
<li>The Service Provider validates the user and request approval from the User that the Consumer (found via the <strong>Request Token</strong>) can access the User’s protected resource. </li>
<li>The Service Provider generates an <strong>Access Token</strong> and an <strong>Access Secret</strong>. </li>
<li>The User (e.g. his/her browser) is then redirected to the Consumer, presenting the <strong>Access Token</strong> (the <strong>Access Secret</strong> is kept um… secret). </li>
<li>The Consumer now takes the <strong>Access Token</strong> and the <strong>Request Secret</strong> and asks the Service Provider for the <strong>Access Secret</strong>. </li>
<li>Once the Consumer has the <strong>Access Token</strong> and the <strong>Access Secret</strong>, it can access the protected resource. </li>
</ol>
<p>The point of presenting the <strong>Request Secret</strong> to the Service Provider in step 6 is so that replays cannot be performed using the <strong>Access Token</strong> alone.</p>
<p>The <strong>Tokens</strong> are used to communicate between the Consumer and the Service Provider <u>via</u> the User (his/her browser). The <strong>Secrets</strong> are kept between the Consumer and the Service Provider.</p>
<h2>Now what?</h2>
<p>Once the relationship is in place, the “real” communication can take place. This is where it gets hairy and where we’ll stop for this dummy introduction. </p>
<p>However during my implementation I found a little problem with the way .NET <a href="http://msdn.microsoft.com/en-us/library/zttxte6w.aspx">UrlEncode</a> works – it is simply not compatible with OAuth. I found an <a href="http://stackoverflow.com/questions/846487/how-to-get-uri-escapedatastring-to-comply-with-rfc-3986">implementation</a> by <a href="http://blog.nerdbank.net/">Andrew Arnott</a>, who is OAuth/OpenID aficionado and author of <a href="https://www.ohloh.net/p/dotnetopenauth/">DotNetOpenAuth</a> that does this and is <a href="http://www.faqs.org/rfcs/rfc3986.html">RFC 3986</a> compliant (it basically used the UrlEncode from .NET and then fixes what is broken):</p>
<pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 100%; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px">
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px"><span style="color: #808080">/// &lt;summary&gt;</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px"><span style="color: #808080">/// The set of characters that are unreserved in RFC 2396 but are NOT unreserved in RFC 3986.</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px"><span style="color: #808080">/// &lt;/summary&gt;</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px"><span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">readonly</span> <span style="color: #0000ff">string</span>[] UriRfc3986CharsToEscape = <span style="color: #0000ff">new</span>[] { &quot;<span style="color: #8b0000">!</span>&quot;, &quot;<span style="color: #8b0000">*</span>&quot;, &quot;<span style="color: #8b0000">'</span>&quot;, &quot;<span style="color: #8b0000">(</span>&quot;, &quot;<span style="color: #8b0000">)</span>&quot; };
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px"></pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px"><span style="color: #808080">/// &lt;summary&gt;</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px"><span style="color: #808080">/// Escapes a string according to the URI data string rules given in RFC 3986.</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px"><span style="color: #808080">/// &lt;/summary&gt;</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px"><span style="color: #808080">/// &lt;param name=&quot;value&quot;&gt;The value to escape.&lt;/param&gt;</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px"><span style="color: #808080">/// &lt;returns&gt;The escaped value.&lt;/returns&gt;</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px"><span style="color: #808080">/// &lt;remarks&gt;</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px"><span style="color: #808080">/// The &lt;see cref=&quot;Uri.EscapeDataString&quot;/&gt; method is &lt;i&gt;supposed&lt;/i&gt; to take on</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px"><span style="color: #808080">/// RFC 3986 behavior if certain elements are present in a .config file.  Even if this</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px"><span style="color: #808080">/// actually worked (which in my experiments it &lt;i&gt;doesn't&lt;/i&gt;), we can't rely on every</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px"><span style="color: #808080">/// host actually having this configuration element present.</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px"><span style="color: #808080">/// &lt;/remarks&gt;</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">string</span> UrlEncodeRfc3986(<span style="color: #0000ff">this</span> <span style="color: #0000ff">string</span> <span style="color: #0000ff">value</span>)
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px">{
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px">    <span style="color: #008000">// Start with RFC 2396 escaping by calling the .NET method to do the work.</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px">    <span style="color: #008000">// This MAY sometimes exhibit RFC 3986 behavior (according to the documentation).</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px">    <span style="color: #008000">// If it does, the escaping we do that follows it will be a no-op since the</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px">    <span style="color: #008000">// characters we search for to replace can't possibly exist in the string.</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px">    var escaped = <span style="color: #0000ff">new</span> StringBuilder(Uri.EscapeDataString(<span style="color: #0000ff">value</span>));
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px"></pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px">    <span style="color: #008000">// Upgrade the escaping to RFC 3986, if necessary.</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px">    <span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 0; i &lt; UriRfc3986CharsToEscape.Length; i++)
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px">    {
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px">        escaped.Replace(UriRfc3986CharsToEscape[i], Uri.HexEscape(UriRfc3986CharsToEscape[i][0]));
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px">    }
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px"></pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px">    <span style="color: #008000">// Return the fully-RFC3986-escaped string.</span>
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px">    <span style="color: #0000ff">return</span> escaped.ToString();
</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,&#39;Courier New&#39;,courier,monospace; font-size: 12px">}</pre>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.veggerby.dk/2009/10/06/oauth-for-dummies/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
