Blog | CoWhite Softwarehttp://django.cowhite.com/blog/2017-07-10T08:01:49+00:00BlogDJango Oauth Toolkit - Authenticating users with access tokens2017-07-10T08:01:49+00:00ravi/blog/author/ravi/http://django.cowhite.com/blog/django-oauth-toolkit-authenticating-users-with-access-tokens/<p>This is the continuation of our previous post which explains <a href="http:///blog/building-oauth2-services-in-django-with-django-oauth-toolkit/">how to build APIs that are protected with OAuth2</a>.
We are using <a href="https://github.com/evonove/django-oauth-toolkit" target="_blank">Django OAuth Toolkit</a> and I am assuming that you have already followed the <a href="http:///blog/building-oauth2-services-in-django-with-django-oauth-toolkit/">previous post</a>.</p>
<p>Well, we have protected our API end-points with OAuth2 but we need to identify the user (<strong>resource owner</strong> in OAuth terms) who has provided the <strong><em>access token</em></strong>. To understand the scenario let us change our previous view. Our view previously was</p>
<div class="codehilite"><pre><span class="k">class</span> <span class="n">MyProtectedEndPoint</span>(<span class="n">ProtectedResourceView</span>):
<span class="n">def</span> <span class="n">get</span>(<span class="k">self</span>, <span class="n">request</span>, *<span class="n">args</span>, **<span class="n">kwargs</span>):
<span class="k">return</span> <span class="n">HttpResponse</span>(<span class="s">'Hello, there!!\n'</span>)
</pre></div>
<p>Let us change it slightly to the following.</p>
<div class="codehilite"><pre><span class="k">class</span> <span class="n">MyProtectedEndPoint</span>(<span class="n">ProtectedResourceView</span>):
<span class="n">def</span> <span class="n">get</span>(<span class="k">self</span>, <span class="n">request</span>, *<span class="n">args</span>, **<span class="n">kwargs</span>):
<span class="k">if</span> <span class="n">request</span>.<span class="n">user</span>.<span class="n">is_authenticated</span>():
<span class="k">return</span> <span class="n">HttpResponse</span>(
<span class="s">'Hello there! You are acting on behalf of "%s"\n'</span>
% (<span class="n">request</span>.<span class="n">user</span>))
<span class="n">else:</span>
<span class="k">return</span> <span class="n">HttpResponse</span>(<span class="s">'Hello! I do not recognize you\n'</span>)
</pre></div>
<p>Now let us make a request to the view using <strong>curl</strong> with the following command.</p>
<div class="codehilite"><pre>curl -i -H "Accept: application/json" -H "Authorization: Bearer 3EhQHLbGv5rJ4cCaNnACnvwed89N1c" -X GET http://localhost:8000/api/posts/protected_view/
</pre></div>
<p>The result should look something like this.</p>
<div class="codehilite"><pre><span class="nt">HTTP</span><span class="o">/</span><span class="nt">1</span><span class="nc">.0</span> <span class="nt">200</span> <span class="nt">OK</span>
<span class="nt">Date</span><span class="o">:</span> <span class="nt">Mon</span><span class="o">,</span> <span class="nt">10</span> <span class="nt">Jul</span> <span class="nt">2017</span> <span class="nt">07</span><span class="nd">:08:54</span> <span class="nt">GMT</span>
<span class="nt">Server</span><span class="o">:</span> <span class="nt">WSGIServer</span><span class="o">/</span><span class="nt">0</span><span class="nc">.2</span> <span class="nt">CPython</span><span class="o">/</span><span class="nt">3</span><span class="nc">.5.2</span>
<span class="nt">X-Frame-Options</span><span class="o">:</span> <span class="nt">SAMEORIGIN</span>
<span class="nt">Content-Type</span><span class="o">:</span> <span class="nt">text</span><span class="o">/</span><span class="nt">html</span><span class="o">;</span> <span class="nt">charset</span><span class="o">=</span><span class="nt">utf-8</span>
<span class="nt">Content-Length</span><span class="o">:</span> <span class="nt">30</span>
<span class="nt">Vary</span><span class="o">:</span> <span class="nt">Cookie</span>
<span class="nt">Hello</span><span class="o">!</span> <span class="nt">I</span> <span class="nt">do</span> <span class="nt">not</span> <span class="nt">recognize</span> <span class="nt">you</span>
</pre></div>
<p>The client (curl in our case) though has the credentials to access the API, our service was clearly unable to identify on whose behalf it is making the requests. Say, the client requests the profile information of the user, our service fails to serve the right user's data.</p>
<p>To resolve this we need to configure our authentication backends and middleware. In our django application settings set the <code>AUTHENTICATION_BACKENDS</code> and <code>MIDDLEWARE</code> to</p>
<div class="codehilite"><pre>AUTHENTICATION_BACKENDS = [
'oauth2_provider.backends.OAuth2Backend',
'django.contrib.auth.backends.ModelBackend' # Only if you want to use admin
]
MIDDLEWARE = [
# ... other middlewares like
# 'django.contrib.auth.middleware.AuthenticationMiddleware',
'oauth2_provider.middleware.OAuth2TokenMiddleware',
# ...
]
</pre></div>
<p>That is all we need to do to identify the resource owner (user). Now when we run our curl command, the result is as follows.</p>
<div class="codehilite"><pre><span class="nt">curl</span> <span class="nt">-i</span> <span class="nt">-H</span> <span class="s2">"Accept: application/json"</span> <span class="nt">-H</span> <span class="s2">"Authorization: Bearer 3EhQHLbGv5rJ4cCaNnACnvwed89N1c"</span> <span class="nt">-X</span> <span class="nt">GET</span> <span class="nt">http</span><span class="o">://</span><span class="nt">localhost</span><span class="nd">:8000</span><span class="o">/</span><span class="nt">api</span><span class="o">/</span><span class="nt">posts</span><span class="o">/</span><span class="nt">protected_view</span><span class="o">/</span>
<span class="nt">HTTP</span><span class="o">/</span><span class="nt">1</span><span class="nc">.0</span> <span class="nt">200</span> <span class="nt">OK</span>
<span class="nt">Date</span><span class="o">:</span> <span class="nt">Mon</span><span class="o">,</span> <span class="nt">10</span> <span class="nt">Jul</span> <span class="nt">2017</span> <span class="nt">07</span><span class="nd">:09:00</span> <span class="nt">GMT</span>
<span class="nt">Server</span><span class="o">:</span> <span class="nt">WSGIServer</span><span class="o">/</span><span class="nt">0</span><span class="nc">.2</span> <span class="nt">CPython</span><span class="o">/</span><span class="nt">3</span><span class="nc">.5.2</span>
<span class="nt">Content-Type</span><span class="o">:</span> <span class="nt">text</span><span class="o">/</span><span class="nt">html</span><span class="o">;</span> <span class="nt">charset</span><span class="o">=</span><span class="nt">utf-8</span>
<span class="nt">Content-Length</span><span class="o">:</span> <span class="nt">48</span>
<span class="nt">Vary</span><span class="o">:</span> <span class="nt">Authorization</span><span class="o">,</span> <span class="nt">Cookie</span>
<span class="nt">X-Frame-Options</span><span class="o">:</span> <span class="nt">SAMEORIGIN</span>
<span class="nt">Hello</span> <span class="nt">there</span><span class="o">!</span> <span class="nt">You</span> <span class="nt">are</span> <span class="nt">acting</span> <span class="nt">on</span> <span class="nt">behalf</span> <span class="nt">of</span> <span class="s2">"ravi"</span>
</pre></div>
<p>Now that these settings are in place, we can also use the <code>login_required</code> decorator from <code>django.contrib.auth.decorators</code>.</p>