Authentication and Authorisation
Ocean's authentication is designed to scale without limit. It is based on DynamoDB, which means authentication times are constant regardless of the number of users in the system.
Authentication and Authorisation
All services require authentication and authorisation. In practice, this means that all clients, before they attempt to access any services, first must make a call to the Auth service to obtain an authorisation token. This token must be included in all requests to services using a special HTTP header.
If the token isn't included, or if the token has expired or is invalid, the service will return a status code of
419, in which case a new token must be obtained from the Auth service. The request should then be retried.
If the service returns a status code of
403 Forbidden, then the token provided the necessary authentication – the service knows "who you are" as a client – but the level of authorisation was insufficient. This means that the ApiUser for which the Authentication was created doesn't have authority to perform the operation embodied by the request. Thus, the request should not be retried.
- A client which wishes to access a resource R makes a POST request to the Authentication resource via HTTPS, passing username and password using the
- If the credentials are valid, then the ApiUser is known, and Auth generates an Authentication with a valid token.
- Auth returns an Authentication resource representation.
- The client makes a request to resource R, including the
X-API-TokenHTTP header using the
tokenstring from the Authentication resource.
- The service of Resource R returns a
400 Bad dataif the
X-API-Tokenheader is missing or the token is unknown or a
419 Authentication Expiredif it has expired.
- The Rights of the ApiUser to which the token belongs are examined (through a
GETrequest to the Authentication resource, as always via the HTTP cache Varnish).
- If the the user doesn't have authorisation to perform the operation, Resource R returns a
- Otherwise the operation is permitted, carried out and the result is returned.
- The token is re-used by the client for subsequent API requests (from step 4).
- When the token times out, the cycle starts over at step 1.
For more information, including UML sequence information, please refer to the Auth service documentation.
All accesses web clients make to the back end Ocean services are of course also authenticated and authorised. For maximum caching efficiency and speed, such authorisations are shared between all clients authenticating as a particular user. Each web application client must have a corresponding ApiUser for authentication purposes. All Authentications made on behalf of the ApiUser share their authorisations in the Varnish cache, which maximises the speed of the application for all end users and lightens the load on the servers dramatically.
Thus, a web client which presents the public parts of a website (all of it might indeed be public) authenticates with the credentials of the corresponding application ApiUser. No time will be spent on superfluous authorisations for API requests for which other, identlcal clients already have received authorisation.
When a section of the website is reached where the user is required to log in, the front end client simply authenticates with the user's credentials and uses the resulting Authentication token. When the user logs out, the front end client destroys the user's Authentication and resumes using its own token.
Design for Full Exposure
There's no such thing as an internal API in this architecture. Remember, admin client applications use exactly the same API as everything else. This means that the full API for resources, even if they can be seen as purely internal, always is fully exposed in the public documentation.
Usually, when building an API, the impulse is that of trying to shield resources from potential misuse by exposing as little as possible in the API or by creating only tailored operations on a resource, optimised for a specific client's use. This is clearly wrong in this context. Instead, the API developer should treat all clients as first-class citizens and allow them full access to the resource, providing as rich an interface as possible. Nothing in the API should be hidden – the Auth service's Rights, Roles and Groups will take care of all access authorisation.
Safety by obscurity is no substitute, especially in a distributed architecture, for strong authentication and authorisation. Since those things have been built into the API at the atomic level, the developer should shift their mindset from protecting the resources handled by the system, to that of trusting the system: resources and all possible operations on them are deliberately exposed in full: a client should be able to manipulate the resource using all standard CRUD operations.