Authentication
The authentication is going to be signature-based. The signature will be generated using:
HMAC_SHA256(SHA1(secret_key) + '#' + request_data + '#' + utc_timestamp)
The utc_timestamp
will also be included into the X-Timestamp
header or into the URL using the _timestamp
parameter. The request_data
will contain all parameters (URL and POST) and API-related headers. All these data will be lowercased, sorted and joined using =
and &
.
Generally, the REST API will support three authentication schemas:
API keys based – the signature will include the special secret key associated with the particular API key. Will use the
X-API-Key
header or the_api_key
URL parameter and theX-API-Signature
header or the_signature
URL parameter.User credentials based – the signature will use the password as the secret key. Will use the
X-API-Signature
header or the_signature
URL parameter and thestaff_name
URL parameter.Session based – the signature will use the user's password or a specially generated code (more details below)... Will use the
X-Session-Signature
header or the_session_signature
URL parameter and theX-Session-ID
header or the_session_id
URL parameter.
Please note, that the specification allows to use User credentials and Session at the same time (i.e., their headers and parameters do not conflict).
Session
Disclaimer: Yes, I know – sessions are not RESTful, as they are stateful... However, our product requires sessions for some functionality, and in the interests of simplicity we want to maintain one API/protocol – so I am not looking to get into a RESTful debate. I prefer to think, that a session is just a resource, which you need to maintain while working with the API.
The session will be just a resource: /api/v1/session
.
So, the standard procedure:
To create a session a client application will need to send a POST request using the staff credentials authentication, which has been described above:
POST /api/v1/session&staff_name=s-andy
.The server will reply with
201 Created
and will deliver the session id in the response body.Afterwards the client application will use this session id and the staff password to access API.
Having gotten a request with particular session id the server will update the last access time of the appropriate session resource.
But our users will also have an option to use the two-factor authentication. In the UI after logging in such users will be requested to enter the verification code, which will come to their mobile devices. When designing the authentication I thought that it would be great to have some special 'secret' instead of the user password for the session. Then it dawned upon me – why not using this verification code?
So the flow for two-factor authentication will be:
A client application sends a POST request using the staff credentials.
Server initiates the verification code generation and delivery and returns
202 Accepted
with the session id, but the session is not verified yet.Within 30 seconds the client application sends any request using the session id in the
X-Session-ID
header or in the_session_id
URL parameter and the verification code as the secret for generating the signature.Having gotten such request the server updates the session making it verified and saves the verification code (a.k.a. one-time password) as the secret key for this session.
Afterwards the client application will use the session id and the verification code (as the secret key) to access API.
When the session times out, and, therefore, gets deleted, or when the user deletes the session (i.e., performs logout), the session id and the "one time password" become unusable.
I wanted to use this community of experts as a sounding board for this two-factor authentication idea; can you see any pitfalls that I cannot?