2019-06-05 21:05 — By Erik van Eykelen
Recently I was investigating the Makerlog API. The API offers three different authentication methods namely Basic Authentication, Bearer Authentication, and oAuth. I chose the latter because I wanted to write a basic oAuth authentication flow from scratch. I’ve documented my steps, perhaps it’s useful to the reader.
With oAuth you first need to register your app with the service that contains the data you want to access. The oAuth 2 Simplified article explains this in more detail.
Open https://api.getmakerlog.com/oauth/applications/ to create your Makerlog app.
Once you’ve done this you are provided with a client ID and client secret.
I’m using the oauth2 Ruby gem to generate the authorization URL (but as you can see it’s fairly easy to craft this URL yourself):
client = OAuth2::Client.new("YOUR-MAKERLOG-CLIENT-ID",
"YOUR-MAKERLOG-CLIENT-SECRET",
{ site: "https://api.getmakerlog.com/oauth/authorize/" })
client.auth_code.authorize_url(redirect_uri: 'http://localhost:5000/oauth/getmakerlog',
scope: "tasks:read tasks:write",
state: "...")
=> "https://api.getmakerlog.com/oauth/authorize?client_id=YOUR-MAKERLOG-CLIENT-ID&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2Foauth%2Fgetmakerlog&response_type=code&scope=tasks%3Aread+tasks%3Awrite&state=abc123"
Notice the space between tasks:read
and tasks:write
, a space is required when requesting more than one scope.
You must generate a value for state
yourself, store it in a session, and compare it with the state value returned by the Makerlog authorization dialog. This prevents malicious authorization attempts.
Now paste the authorization URL in your browser. You’ll be presented with Makerlog’s authorization dialog, asking the user whether it’s OK to provide task reading and writing rights.
After clicking “Authorize” the dialog redirects to your app. In my case I had set up a web server on localhost (port 5000) to capture the redirect.
The GET request looks like this (taken from the Rails log):
Started GET "/oauth/getmakerlog?code=ASFT...kAbM&state=abc123"
Completed 200 OK in 1ms (Views: 0.5ms | ActiveRecord: 0.0ms)
You now have an authorization code. Again, don’t forget to compare the state
value with the value you’ve remembered by storing it as a session variable.
Now it’s time to exchange the authentication code for an access token.
This is done by performing a (server-side) POST to the Makerlog API:
curl -X POST -d "grant_type=authorization_code&code=TOKEN-FROM-GET-REQUEST" -u "YOUR-MAKERLOG-CLIENT-ID:YOUR-MAKERLOG-CLIENT-SECRET" https://api.getmakerlog.com/oauth/token/
The result should look like this:
{
"access_token": "yBB9...vppN",
"expires_in": 36000,
"token_type": "Bearer",
"scope": "tasks:read tasks:write",
"refresh_token": "teu4...OnXf"
}
Note: you can only exchange a code for an access token once!
You can now use the access token to perform all API requests allowed by the requested scope.
The access token will expire after 36000 seconds (10 hours). To receive a new set of tokens, you need to make a POST request using grant_type=refresh_token
:
curl -X POST -d "grant_type=refresh_token&refresh_token=lcIg...3mtc" -u "YOUR-MAKERLOG-CLIENT-ID:YOUR-MAKERLOG-CLIENT-SECRET" https://api.getmakerlog.com/oauth/token/
Notice the trailing slash after .../oauth/token/
. Without the / the POST fails silently.
The result should look like this:
{
"access_token": "zjeA...ezN0",
"expires_in": 36000,
"token_type": "Bearer",
"scope": "tasks:read tasks:write",
"refresh_token": "5Nm0...Zqw9"
}
Note: you can only use a refresh token once!
Rinse and repeat every time your access_token
expires.
Since we’ve asked permission to read and write tasks, let’s use the newly minted access token to obtain the latest 20 public tasks (note: the API uses pagination, the default page size is 20):
curl -X GET -L -H 'authorization: Bearer J44D...fRqP' https://api.getmakerlog.com/tasks
Note: the -L
directive (“follow redirects”) is necessary with the Makerlog API because it performs a redirect. You can see this by adding --verbose
to your curl command.
The result should look like this:
{
"count": 93448,
"next": "https://api.getmakerlog.com/tasks/?limit=20&offset=20",
"previous": null,
"results": [
{
"id": 150371,
"event": null,
"done": true,
"in_progress": false,
...
Have fun exploring the Makerlog API!