Authentication in DADI API
DADI API uses the client credentials flow of OAuth 2.0 to allow clients to access protected resources by obtaining an access token. First we’ll setup an instance of API, then we’ll go through creating some credentials, and using them to obtain a Bearer token, before we query a protected resource with our new token.
API 2.X requires a MongoDB instance to work. If you don’t have one of those setup already, you can easily start one with Docker to test with:
$ docker run -d -p 27017:27017 mongo:3.2
Let’s create a new API app using the DADI CLI (npm install @dadi/cli -g
):
$ dadi api new simple-api
✔ Checking the available versions of DADI API
✔ Downloading boilerplate (100%)
✔ Installing DADI API (2.2.x)
All done! Run the following command to launch your new instance of DADI API:
cd simple-api && npm start
Cool, now let’s create some credentials:
$ cd simple-api
$ dadi api clients:add
? What is the client ID? testUser
? What is the secret? testPassword
? What type of access does the user require? user
✔ Created client with ID testUser and type user
So now we have API setup, and a new user created, but where is this information stored? If you have a look in the config/config.development.json
file, you'll find the auth
block:
"auth": {
"tokenUrl": "/token",
"tokenTtl": 1800,
"clientCollection": "clientStore",
"tokenCollection": "tokenStore",
"database": {
"hosts": [
{
"host": "127.0.0.1",
"port": 27017
}
],
"username": "",
"password": "",
"database": "dadi-api"
}
}
The tokenUrl
defines where we query for a Bearer token
. The tokenTtl
is how long it will live for. The clientCollection
is the Mongo collection which stores client credentials such as the one we created above, and the tokenCollection
will store any Bearer token
s that we generate.
The database
block contains an array of hosts
(allowing multiple in the case that you are using replica sets), a username
, password
, and finally, a database
.
Let’s look in that database, assuming you have the mongo
CLI tool installed:
$ mongo dadi-api
> show collections
clientStore
tokenStore
Now query the clientStore
collection to see if our user from earlier is in there:
> db.clientStore.find()
{ "_id" : ObjectId("5a1403634e822a1250e45c56"), "clientId" : "testUser", "secret" : "testPassword", "type" : "user" }
Perfect. Now let’s start the API and generate some tokens.
Cancel out of the mongo prompt with ctrl
+c
if you haven't already, then start API:
$ npm start
...
----------------------------
DADI API
Started 'DADI API'
----------------------------
Server: 127.0.0.1:3000
Version: 2.2.5
Node.JS: 8.9
Environment: development
----------------------------
Cool! Now let’s try and access a resource without a token:
$ curl http://127.0.0.1:3000/1.0/library/books
{"statusCode":401}
Now let’s get a token. We’ll need to send a POST
request to /token
with some JSON containing our clientId
and our secret
:
curl \
--request POST \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data "{\"clientId\":\"testUser\",\"secret\":\"testPassword\"}" \
http://127.0.0.1:3000/token
{"accessToken":"36afb59e-e26a-4a3b-bb03-c6226efdc4f0","tokenType":"Bearer","expiresIn":1800}
We now have our Bearer token
. We can use that to query the books collection again, but first, let's go back to mongo now and take a look in the tokenStore
collection:
$ mongo dadi-api
> db.tokenStore.find()
{ "_id" : ObjectId("5a1405ac61977e126ced4fae"), "token" : "36afb59e-e26a-4a3b-bb03-c6226efdc4f0", "tokenExpire" : 1511263412358, "created" : ISODate("2017-11-21T10:53:32.358Z"), "value" : { "_id" : ObjectId("5a1403634e822a1250e45c56"), "clientId" : "testUser", "secret" : "testPassword", "type" : "user" } }
As you can see, our token is sat in the tokenStore
collection now.
Now let’s query the books collection, this time, with our Bearer token
in the Authorization
header:
curl \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer 36afb59e-e26a-4a3b-bb03-c6226efdc4f0" \
http://127.0.0.1:3000/1.0/library/books
{"results":[],"metadata":{"limit":40,"page":1,"fields":{},"sort":{"name":1},"offset":0,"totalCount":0,"totalPages":0}}
Bingo. We’re in.
You don’t have to use cURL though, you can use anything that implements HTTP, so long as it follows the pattern above. If you use DADI Web, you don’t even need to worry about the authorization flow as it’s all built in.
See our docs to more about Authentication in DADI API.
Written by Adam K Dean, a Senior Engineer at DADI.