Category: django

Using django-oauth-toolkit for Client credentials Oauth Flow

I've been wanting to secure my api - so unidentified and unathorized parties cannot view, update, create or delete data.
This api is internal to the company and will only be used by other services - in other words no end users.
Hence the delegation of authorization need not happen and the services will be authneticating directly with the api.

That is why the Oauth client credentials flow is used - it is for server to server communication. (As far as I know)

There is alot of conflicting information on Oauth but in the RFC6749 on Oauth 2 Client credentials is mentioned:

1.3.4.  Client Credentials

   The client credentials (or other forms of client authentication) can
   be used as an authorization grant when the authorization scope is
   limited to the protected resources under the control of the client,
   or to protected resources previously arranged with the authorization
   server.  Client credentials are used as an authorization grant
   typically when the client is acting on its own behalf (the client is
   also the resource owner) or is requesting access to protected
   resources based on an authorization previously arranged with the
   authorization server.

Nordic API's: Securing the API Stronghold book mentions:

Oauth: It’s for delegation, and delegation only

I agree except when the client is the resource owner in the client credentials instance.
In that case surely there is no delegation?

Should we use it

What is the advantage over a basic auth or token authentication method?

It seems to just be an added step for the client but the key is that the token expires. So if a bad actor gets our token it will not last long before it is of no use.
The client id and secret is the thing that is used to generate tokend for future calling of the api.

Difference between Resource Owner Password Based flow and client Credentials

Django-oauth-tollkit provides both and their example uses the resource owner password based flow.
In both cases the resource owner is the client - so there is no delegation.

So what is the difference?

I checked on stackoverflow, and it turns out I was wrong.

In the resource owner client based way, the resource owner (end user) trusts the client application enough to give it it's username and password.
We don't really want this.

Implementing Client Credentials flow

Since users are not going to use the API and only services/clients will, I want to disable the other authorization flows and disable registering of clients.

I will manage the clients and they will be the resource owners.

So if you follow the information in the django-oauth-toolkit and setting it up for client credentials that should help

Permissions are significantly different from Django Permissions

What I found out durinng testing is that OauthToolkit implements it's own seperate permissions. So if you were wanting to use django model permissions (add, change, view and delete), you don't be able to.

Wait...I spoke too fast.

You can allow this with:

permission_classes = [IsAuthenticatedOrTokenHasScope, DjangoModelPermission]

However that means that you actually have to test with scopes if you expect a client to use it with Oauth and not django auth.

This is the view to use ClientProtectedResourceView

VueJS and Django using them together

If you have been a web developer for some time, eventually you realise you have been wasting a lot of time and doing things wrong (or at least making your life difficult) if you have not been using Django and VueJS.

Django being the backend where the data is stored and where resources are maintained, deleted and created. VueJS being the frontend where relevant data is displayed in a concise and logical way. They both do there respective duties pretty well...in my opinion like a dream.

They also both benefit from a relatively shallow learning curve to start with.

Getting these 2 great frameworks to play well together is an important part of creating a web application that is versatile and a joy to work with.

So without further ado...how do we get them working together

VueJS and Django a quick overview

There is a great presentation given by Andrew McCracken on this topic and a lot of the info in this blog post is derived from that presentation.

Something to keep in mind when thinking in the MVC context: With django the view is really the controller and the template is really the view.

So django already has the template part and VueJS is also a templating library amongst other thing, so there is a bit of overlap. However, if we create a frontend agnostic backend (An API) then they will work together much like how they were designed.

So Django can be used with the Django Rest Framework (DRF) to provide the API and Vue can be used with vue-resource to interact with the API.

Django, Vue and the template

One aspect which jumps right at you is that when displaying a variable from data in a template...both django and vue uses the {{ my_var }}double braces (for a reference on brackets, braces and parenthesis)

Django's variables will be resolved first and it will break your intended template.

There is a horrible way to get around this that I have used:


{% templatetag openvariable %} build.fields.description {% templatetag closevariable %}

But there is a nicer way to do this by just changing the configuration in vue to use the square brackets instead of braces

In the global configuration add:

Vue.config.delimiters = ["[[", "]]"];

So Vue template tags can now be easily distinguished from django ones.

You can set this up in the vue instance with:


var app = Vue({
    el: '#app',
    delimiters: ['[[', ']]']
});

 

Other aspects

I am building out a project with a bit more than just including the pre-packaged Vue file and am using webpack to bring in Vue so a few issues will no doubt come up and I will post them

 

Getting Started VueJS

To bootstrap the project execute the following commands


sudo npm install -g vue-init
vue init webpack frontend
cd frontend/
npm install
npm run dev

This install vue-init so you can bootstrap your project which in this case I have called frontend

But now you must be thinking...well node is serving the site wouldn't django be serving the site in my case. And yes, I think the same way but then maybe we won't have access to the auto-reload and other features

Now after doing this I was Unsure...

About how to wire up Django and Vue with webpack, so I reached out to the community and Jarrod Hobbs suggested looking at django-webpack-loader

Bringing data into Django View

However if you want to keep things simple you can have django bring a queryset into your view instance.

The most simple way to do this provided the model does not have date or time fields:


from django.core.serializers import serialize

context_data['accounts'] = serialize('json', 
    Account.objects.filter(
        user=self.request.user
    )
)

Which would give serialised data of the form:


{'accounts': '[{"model": "app.model", "pk": 1, "fields": {"name": ' '"name", "capital_currency": "ZAR", "capital": ' '"100000.00", "strategy": 1, "broker": null, "user": 1, "slug": ' '"cfd-account", "risk_percentage": "1.00", "is_long_only": ' 'false}}]',}