The authentication is going to be signature-based. The signature will be generated using:
HMAC_SHA256(SHA1(secret_key) + '#' + request_data + '#' + utc_timestamp)
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
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-Keyheader or the
_api_keyURL parameter and the
X-API-Signatureheader or the
User credentials based – the signature will use the password as the secret key. Will use the
X-API-Signatureheader or the
_signatureURL parameter and the
Session based – the signature will use the user's password or a specially generated code (more details below)... Will use the
X-Session-Signatureheader or the
_session_signatureURL parameter and the
X-Session-IDheader or the
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).
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:
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:
The server will reply with
201 Createdand 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 Acceptedwith 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-IDheader or in the
_session_idURL 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?