Masonite API

Introduction

Masonite API is a package designed to make it dead simple to add externally facing API's with various types of authentication and permission scopes. There is a new concept called "API Resources" which you will use to build your specific endpoint. In this documentation we will walk through how to make a User Resource so we can walk through the various moving parts.

Installation

Just run:

$ pip install masonite-api

Creating a Resource

We can create API Resources by building them wherever you want to. In this documentation we will put them in app/resources. We just need to create a simple resource class which inherits from api.resources.Resource.

from api.resources import Resource

class UserResource(Resource):
    pass

You should also specify a model by importing it and specifying the model attribute:

from api.resources import Resource
from app.User import User

class UserResource(Resource):
    model = User

Lastly for simplicity sake, we can specify a serializer. This will take any Orator models or Collection we return and serialize them into a dictionary which will be picked up via the JsonResponseMiddleware.

Awesome! Now we are ready to go!

Specifying our routes

Our resource has several routes that it will build based on the information we provided so let's import it into our web.py file so it will build the routes for us. We can also specify the base route which will be used for all routes.

This will build a route list that looks like:

We can also specify the routes that we want to create by setting the methods attribute:

This will only build those routes dependent on the methods specified:

Adding Middleware

You can easily add middleware to routes by specifying them using the middleware method:

Or of course you can add the middleware to a group:

Overriding Methods

You may want to override some methods that are used internally by the API endpoint to return the necessary data.

The methods are: create, index, show, update, delete.

You can check the repo on how these methods are used and how you should modify them but it's pretty straight forward. The show method is used to show all the results are is what is returned when the endpoint is something like /api/user.

Overriding a method will look something like:

This will not only return all the results where active is 1. Keep in mind as well that these methods are resolved via the container so we can use dependency injection:

The index method is ran when getting all records with: POST /api/user.

Removing model attributes

Currently our response may look something like:

You might not want to display all the model attributes like id, email or password. We can choose to remove these with the without class attribute:

Now our response will look like:

Yes, it's that easy.

Authentication

For any API package to be awesome, it really needs to have powerful and simple authentication.

JWT Authentication

We can specify our authentication for our specific endpoint by inheriting from a class:

Now our endpoint is being JWT Authentication. If we hit our endpoint now in the browser by sending a GET request to http://localhost:8000/api/user. we will see:

Great! If we specify a token by hitting http://localhost:8000/api/user?token=1234 then we will see a different error:

JWT Tokens

We can easily create an endpoint for giving out and refreshing API tokens by adding some routes to our web.py:

Now we can make a POST request to http://localhost:8000/token with your username and password which will give us back a JWT token.

Retrieve a JWT Token

POST http://localhost:8000/token

Use this endpoint to retrieve new tokens using a username and password. The username and password will default to your regular authentication model located in config/auth.py.

Query Parameters

Name
Type
Description

username

string

The username to authenticate using your authentication model

password

string

The password to authenticate using your authentication model

we can now use this token to make our calls by using that new token. This token is good for 5 minutes and it will be required to refresh the token once expired.

Refreshing Tokens

Once our JWT token expires, we need to refresh it by sending our old expired token to

Refresh JWT Tokens

POST http://localhost:8000/token/refresh

Path Parameters

Name
Type
Description

token

string

The expired JWT token

Permission Scopes

You can also specify any permission scopes you need. Most of the time some API endpoints will need to have more restrictive scopes than others. We can specify whatever scopes we need to with the scopes attribute as well as inheriting another class.

Now all API endpoint will need to have the correct permission scopes. Hitting this API endpoint now will result in:

We can request the scopes we need by spending a POST request back to the endpoint with a scopes input. The scopes should be comma separated. The request should look like:

This will generate a new token with the correct permission scopes.

Filter Scopes

Filter scopes is an extension of the scopes above. It will filter the data based on the scope level. This is useful if you want a specific scope to have more permission than other scopes.

To do this we can extend our resource with the FilterScopes class:

Now when you make this request it will return the columns in accordance with the user scopes.

Creating Authentication Classes

Authentication classes are extremely simple classes. They just need to inherit the BaseAuthentication class and contain 2 methods: authenticate and get_token.

Authenticate

This method is resolved via the container. it is important to note that if the authenticate is successful, it should not return anything. Masonite will only look for exceptions thrown in this method and then correlate an error response to it.

For example if we want to return an error because the token was not found, we can raise that exception:

Which will result in an error response:

Get Token

This method is used to return a dictionary which is the decrypted version of the token. So however your authentication class should decrypt the token, it needs to do so in this method. This all depends on how the token was encrypted in the first place. This may look something like:

Creating Serializers

Serializers are simple classes with a single serialize method on them. The serialize method takes a single parameter which is the response returned from one of the create, index, show, update, delete methods.

For example if we return something like a model instance:

We will receive this output into our serialize method:

which we can then serialize how we need to and return it. Here is an example of a JSON serializer:

notice we take the response and then convert that response into a dictionary depending on the response type.

Once we convert to a dictionary here, the JSONResponseMiddleware will pick that dictionary up and return a JSON response.

Builtin Methods

We have access to a few builtin methods from anywhere in our resource.

Getting the token

The token can be in several different forms coming into the request. It can be either a JWT token or a regular token or some other form of token. Either way it needs to be "unencrypted" in order for it to be used and since the authentication class is responsible for un-encrypting it, it is the responsibility of the authentication class to get the token.

Fetching the token

There are a few locations the token can be. The two main locations are in the query string itself (/endpoint?token=123..) or inside a header (the HTTP_AUTHORIZATION header). We can get the token regardless of where it is with the fetch_token() method:

Last updated