REST
Representational state transfer
REST
Architectural constraints
REST
Architectural constraints
REST
Request methods (HTTP VERBS)
GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS,...
"Safe" means that if a given HTTP method is invoked, the resource state on the server remains unchanged. GET is safe
"idempotent" means that multiple identical requests should have the same effect as a single request .
GET, PUT, DELETE are idempotent
| HTTP Method | Safe | Idempotent |
|---|---|---|
| GET | Yes | Yes |
| POST | No | No |
| PUT | No | Yes |
| DELETE | No | Yes |
is BEdita API RESTful compliant?
But... WTF!
74% of APIs claiming to be “RESTful” do not actually use hypermedia*
Setup frontend to consume API
$ cd /path/to/bedita
$ ./cake.sh frontend init// frontend.ini.php or frontend.cfg.php
$config['api'] = array(
'baseUrl' => '/api/v1'
);
// core.php (used for authentication)
Configure::write('Security.salt', 'my-security-random-string');Init frontend
Minimum setup
API response
{
"api": "objects",
"data": {},
"method": "get",
"params": [],
"url": "http://example.com/api/v1/objects/1"
}
{
"api": "objects",
"data": {...},
"method": "get",
"paging": {
"page": 1,
"page_size": 10,
"page_count": 10,
"total": 995,
"total_pages": 100
},
"params": [],
"url": "http://example.com/api/v1/objects/1/children"
}API errors
{
"error": {
"status": 405,
"code": null,
"message": "Method Not Allowed",
"details": "Method Not Allowed",
"more_info": null,
"url": "http://example.com/api/v1/foobar"
}
}HTTP Status Code: 405 Method Not Allowed
GET API /objects
GET /api/objects
Dispatcher,
Routes,
Controller
ApiValidator
Get data
from datasource
ApiFormatter
Response
POST API /objects
POST /api/objects
Dispatcher,
Routes,
Controller
ApiValidator
Save
data
Response
ApiFormatter
Prepare response
ApiAuth
Unauthorized
token valid
ApiValidator Component
It takes care of validate data, for example
ApiFormatter Component
It takes care of data to make it consistent and well formatted
Authentication
The API follow a token based authentication flow using a Json Web Token as access_token and an opaque token as refresh_token useful to renew the access_token without ask again the user credentials.
The access_token must be used in every request that require permission. To use the access_token it has to be sent in HTTP headers as bearer token
+--------+ +---------------+ | |--(A)- Authorization Request ------->| Resource | | | | Owner | | |<-(B)-- Authorization Grant ---------| | | | +---------------+ | | | | +---------------+ | |--(C)-- Authorization Grant -------->| Authorization | | Client | | Server | | |<-(D)----- Access Token (JWT) -------| | | | and | | | | Refresh Token | | | | +---------------+ | | | | +---------------+ | |--(E)----- Access Token (JWT) ------>| Resource | | | | Server | | |<-(F)--- Protected Resource ---------| | +--------+ +---------------+
Authorization: Bearer eyJ0eXAi......
Json Web Token (JWT, pronounced jot)
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
JWT anathomy
A JWT is represented as a sequence of base64url encoded json (URL-safe) that are separated by period ('.') characters.
It is composed by three parts:
aaaaaa
bbbbbb
cccccc
.
.
JWT Header
The header contains the metadata for the token (type of token and the algorithm used to sign the token).
{
"typ": "JWT",
"alg": "HS256"
}eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
base64url encoded
JWT Payload
Carry JWT Claims (informations we want to transmit). There are registered claims, public claims and private claims.
JWT Payload
{
"iss": "https://example.com",
"iat": "1441749523",
"exp": "1441707000",
"id": "15"
}eyJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tIiwiaWF0IjoiMTQ0MTc0OTUyMyIsImV4cCI6IjE0NDE3MDcwMDAiLCJpZCI6IjE1In0
base64url encoded
JWT Signature
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tIiwiaWF0IjoiMTQ0MTc0OTUyMyIsImV4cCI6IjE0NDE3MDcwMDAiLCJpZCI6IjE1In0.DcsoLlT1a_wivzFSCO9XjvTW84VK_hFGJJzmohCsFdE
The JWT standard follows the JSON Web Signature (JWS) specification to generate the final signed token.
HMACSHA256(
base64UrlEncode(header) + '.' + base64UrlEncode(payload),
'secret'
)JWT
Default API endpoints
What can I do to customize API?
$config['api'] = array(
'baseUrl' => '/api/v1',
'allowedOrigins' => array(),
'auth' => array(
'component' => 'MyCustomAuth',
'JWT' => array(
'expiresIn' => 600,
'alg' => 'HS256'
),
),
'formatting' => array(
'fields' => array(
// fields that should be removed from results
'remove' => array(
'title',
'Category' => array('name')
),
// fields (removed by default) that should be kept
'keep' => array(
'ip_created',
'Category' => array('object_type_id', 'priority')
)
)
),
'validation' => array(
'writableObjects' => array('document', 'event')
)
);What is missing?