Authentication and Authorisation

From Ocean Framework Documentation Wiki
Jump to: navigation, search

Scalability

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 400 or 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.

Bottle.jpg NOTE: Authentication tokens should be re-used until they expire - under no circumstances should you create a new authentication for each API request, or small group of API requests. Failure to do so will compromise scalability.

Also, your code must always be prepared to handle 400 and 419 responses and re-authenticate transparently to the user. Since all tokens are shared, you may get a 419 the very first time you use a token, even if it's newly acquired. You must always re-authenticate transparently. This cannot be emphasised enough.

Flow

  1. 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 X-API-Authenticate HTTP header.
  2. If the credentials are valid, then the ApiUser is known, and Auth generates an Authentication with a valid token.
  3. Auth returns an Authentication resource representation.
  4. The client makes a request to resource R, including the X-API-Token HTTP header using the token string from the Authentication resource.
  5. The service of Resource R returns a 400 Bad data if the X-API-Token header is missing or the token is unknown or a 419 Authentication Expired if it has expired.
  6. The Rights of the ApiUser to which the token belongs are examined (through a GET request to the Authentication resource, as always via the HTTP cache Varnish).
  7. If the the user doesn't have authorisation to perform the operation, Resource R returns a 403 Forbidden.
  8. Otherwise the operation is permitted, carried out and the result is returned.
  9. The token is re-used by the client for subsequent API requests (from step 4).
  10. 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.

Web Clients

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.

Bottle.jpg NOTE: An Authentication created for an ApiUser with multiple simultaneous users should never be DELETEd, as all shared authorisations would be invalidated. Clients should transparently re-authenticate, but the slight increase in load on the servers can easily be avoided.

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.