When a client is invoking the Rest API it may supply information to allow the Rest API to identify it:
Header | Description | Example |
---|---|---|
enactor-device-id | This header will identify the id of the device making the request | pos1@0001.enactor |
enactor-location-id | This header will specify the location of the device making the request | 0001 |
enactor-user-id | This header will specify the id of the user making the request Note that unlike the subject header, this identifier should be for information only and should not be used for authorisation. | 1 |
Returning Errors and Status Messages #
In some cases you may want to return details about an error that occurred on the server to the client. You may also need to return a status message or include an error as a part of a normal response.
To support this, all responses from the Rest API should allow for an ErrorMessage object as a part of their response.
This object has the following properties:
Field | Description |
---|---|
errorCode | A simple code that describes the nature of the error, or the status message |
messageBase | An Enactor format Message Base that is used to provide for client-side translation of the message |
messageId | The ID of the message to display |
messageText | A server-side resolved message text – the locale of the message is not guaranteed to match that supplied in any request |
trace | A stack trace describing the location of the error in the server-side code. This field is not typically available in a production system. |
For cases where a normal response cannot be produced, the api may return an ErrorMessage as its response. In that case you should use one of the static helper methods on the ErrorMessageHelper
class:
Given the HTTP status code and a simple message
createErrorMessageResponse(Status status, String errorCode, String message) |
Given the HTTP status code, an application error code, and a simple message
createErrorMessageResponseFromException(Status status, XMLException exception) |
Given the HTTP status code and an Exception which will be returned to the client. Note – this last variant should only be used in development environments. Stack traces can “leak” information about the server to a client and therefore should be avoided
Each of these method will produce a response object that can be serialised to JSON which will have the following form:
{
"httpStatus": 123,
"errorCode": "application error code",
"messageText": "application error message",
"trace": "stack trace details"
}
Authentication and Authorisation Filter #
In order to protect access to the rest services, they must be protected from access by random parties on the internet (even in cases where anonymous access is allowed). This will be enforced by a filter added ‘in front’ of the rest services. This filter will perform the following:
- Capture and validate the Authorisation header or Access token (supplied as a JSON Web Token in the headers) with the Identity Service. If the header or token is invalid the filter will prevent access to the API
- Check that the merchant supplied associated with the Access token is authorised to access the API – this could be done by the identity service itself.
Once these conditions have been passed, the filter will then pass the request onto the API method. Using the filter allows us to remove the requirement for the individual services to perform their own authentication and authorisation tests.
Basic/Digest Authentication #
In some cases we may wish to support basic or digest based authentication for inter-system communication. The credentials supplied in a Basic or Digest based authentication will currently be validated against the Enactor Users database – not the identity service. Where authentication is performed using Basic or Digest based authentication, the user authentication will be used as the ‘subject’ for the benefit of the rest api call. As this option does not allow for sensitive data to be encoded into a JWT, this option should only really be used during development, or where the authenticity of the source and content of the request can be guaranteed.
Access Tokens #
Services can be authenticated using an Access Token to be supplied when they are invoked. This will be provided by the Enactor Identity Service as a JSON Web Token in the HTTP Headers. It will be used to validate the caller has access to any sensitive data, or to validate that the API being invoked is available to the caller.
Enactor will support two tokens can be passed as http headers:
- Authorization – This token should be used to validate the identity of the caller of the service
- site_token – (Not Implemented yet) This token should be used to validate the identity of the company on whose behalf the caller is making the request.
Sensitive Data #
In some cases the rest services will need to update transactions and retrieve customer details or other sensitive data. In all cases access to sensitive data must be verified by retrieving the keys used to access it from the identity service before any changes are allowed. For example:
- A client calls the ‘Update Delivery Address’ function, supplying an address id and an Access Token.
- The Access Token is validated by the Enactor Identity Service which returns a Customer Id as the related data for the logged in principal.
- The service validates that the customer id from the Identity Service is associated with the selected address before continuing.
The rest API should not trust any key data (customer id’s for example) that are present in the request.
Anonymous Data Access #
In other cases, the rest services will allow anonymous access to data. For example a Customer is permitted to add items to a Basket before they are logged in. In these scenarios there must be some unique, non-sequential identifier used to access the data. For example:
- A client calls the ‘Add Item to Basket’ function. The do not specify a transaction, or include an access token. The service prepares a new basket, adds the item and associates it with a new random identifier. It returns the identifier back to the caller as the transaction reference.
- A client calls the ‘Add Item to Basket’ function again, this time supplying the transaction reference. The service loads the transaction associated with the reference and updates it.
Authorisation Filter #
The authorisation filter is used to prevent users which do not have authorisation using the Rest API. It works by verifying the request includes a valid Authorisation header with either Basic, Digest or Bearer based authentication. When using Bearer, this will be a JWT (Json Web Token) and must have a valid signature and expiration date.
Enactors JWT follows the typical structure of header.payload.signature. For more information on the identity server and JWTs see the confluence page: Enactor Identity Server – Integration Specification V 1.0#IntegrationSpecificationV1.0-Signatureverification(Must) An example JWT:
eyJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJjbGllbnQiLCJzdWIiOiIxIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJ1cGRhdGVkX2F0IjoxNTIyMzIwOTAyLCJpc3MiOiJodHRwOlwvXC93d3cuZW5hY3Rvci5jb1wvIiwicGhvbmVfbnVtYmVyX3ZlcmlmaWVkIjpmYWxzZSwiZXhwIjoxNTIzMzU4MTQwLCJpYXQiOjE1MjMzNTQ1NDQ4Njh9.mQZM3WfaV29MBa_fGepTmUKEAZ82waCtqcmSBA7YVmLL5yPrbGAFS0HIAYmfpJ31R5lPvbTAavyKbFSgB9rXREw8mFErXDosGVn3PNPvHI5trF7QHDsa2ONsNS_nB-0IUAsxkaivamw54oFVgCpZhJRrM1q8r0Cap52wrDXG6cZozJ64jTcpk6Si9yLc1p1OkibTJJ2Z4_l221KknAuGyLgFJp84bLgjRcUCC4BU_womfRSnXCDDBtNpLuPEf2o9JC7GAL4ENtgzY-uKogdegox-NFijGzJT7GAR8H7biScb564SWC_V_4uEsL4s4pR7wmrgi-f9FMEgAinIrvBMaw |
The authorisation filter can be bypassed through an enactor.xml property called REST.AuthenticateRestAPI. Without this property, the value defaults to true. True requires authorisation (JWT) to use the Rest API. False does not require authorisation, however the client needs to add a header called “subject” with its value is the customers customer number.
Example enactor.xml property.
<coreProperty name= "REST.AuthenticateRestAPI" value= "false" /> |
Common.env equivalent:
ENACTOR_REST_AUTHENTICATERESTAPI= false |
Example request with the value set to false:
GET /WebRestApi/rest/baskets/PRIMARY HTTP/1.1
Host: api.james.enactor:8080
subject: 1
Cache-Control: no-cache
Postman-Token: e832402c-002e-4e49-8fe3-f37fed392787
Example request with the value set to true;
GET /WebRestApi/rest/baskets/PRIMARY HTTP/1.1
Host: api.james.enactor:8080
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJjbGllbnQiLCJzdWIiOiIxIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJpc3MiOiJodHRwOlwvXC93d3cuZW5hY3Rvci5jb1wvIiwicGhvbmVfbnVtYmVyX3ZlcmlmaWVkIjpmYWxzZSwiZXhwIjoxNjEwNDYyOTk4LCJpYXQiOjE2MDI2ODY5OTgxMjR9.lgk6mVVzfjaNYf53a39E0-1fV6nb0UPMvbCPpSfK49-McHFlKB-OJwsLjN_wJ3Sz_fxcGdQf8do4EpGek_jkGzahRB44HUcmoTocnieJufELZWSfx64G0JFD8I0vWbiFU76egXHMxkiGUou-v0eVYAsvE-bp_ATCXrPzZm1sb4MO5sufMEON1eF1UpUt5E9PFyKbCP3nZCLtaJ-52dZmcRt-8Xm_PpQujyiJPRF9IaVuofxpafoCih6au1oV0PojdZjKjx2bE7cVJkgXRxytIECfpwPCp3Xx_GyvzEZjAUauMIeKTH4Nu7BFJlXQZ-kY40VlSChKnB88q8dZlp5zyA
Cache-Control: no-cache
Postman-Token: bb3dff61-d4b5-48d3-8bb3-2d81d678fcee