Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

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:

  1. 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 the X-API-Signature header or the _signature URL parameter.

  2. 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 the staff_name URL parameter.

  3. 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 the X-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:

  1. 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.

  2. The server will reply with 201 Created and will deliver the session id in the response body.

  3. 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:

  1. A client application sends a POST request using the staff credentials.

  2. Server initiates the verification code generation and delivery and returns 202 Accepted with the session id, but the session is not verified yet.

  3. 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.

  4. 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.

  5. Afterwards the client application will use the session id and the verification code (as the secret key) to access API.

  6. 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?

share|improve this question
add comment

migrated from stackoverflow.com Mar 19 '13 at 12:46

This question came from our site for professional and enthusiast programmers.

2 Answers

The problem is that what you call verification code is actually a Two-Factor Token. Tokens are normally short (like 6-7 characters).

So you'll do:

HMAC_SHA256(SHA1(TOKEN) + '#' + request_data + '#' + utc_timestamp)

And token is too short.

I also don't understand what a verified session_id vs an unverified session_id looks like.

The biggest problem is that this authentication scheme seems unnecessarily complex. Complexity and security are mostly opposites.

The way we suggest our customers (www.authy.com) to do two-factor auth is:

  1. User sends a POST request with their credentials.

  2. Server validates credentials. If correct the server generates a 256 bit string and saves it on to the database as well as returns it back to the browser. We'll call this string "otp".

  3. The user is petitioned his two-factor token.

  4. In the POST request of step 3 there will be:

    hidden_field otp -> which comes back from the server on step 2
    text-field two-factor-token -> which the person gets from his mobile app

  5. At this point on your server you verify the two-factor token and the otp. If correct you create the session and reset the otp so it can't be used again.

share|improve this answer
    
That's why we are going to use SHA1 for the token - this will make it longer. –  Andriy Lesyuk Mar 15 '13 at 0:01
    
An unverified session is the session, which waits for the two-factor token to be submitted (used). A session becomes verified, if either the verification code has been provided or it does not require it. –  Andriy Lesyuk Mar 15 '13 at 0:03
    
In fact, your steps 1-4 are almost exactly the same as I've described. The difference is that we are not going to submit two-factor token as it is but will use it for creating signature. Also here you do not cover how do you authenticate the session - we are going to do this using the two-factor token as the secret for creating the signature. –  Andriy Lesyuk Mar 15 '13 at 0:04
    
The reason I don't cover how to verify the session is that I recommend to never generate a session until both password and two-factor token are verified. –  daniel Mar 15 '13 at 0:04
1  
The reason you would'nt brutforce the password is that it requires a POST request and you can actually limit them easily, like max 3 tries. In this case the person would just generate different cookies and point them to different GET resources. So they can bypass your authentication flow and i'll be very hard to rate limit them. –  daniel Mar 15 '13 at 1:00
show 3 more comments

Your verification code sounds a lot like the way google two step verification works. If it is secure enough for google accounts then it will probably work for you.

The big question is how you are going to deliver the verification code to user? It is the classic problem of symmetrical key encyrption systems.

Also, what language are you implementing this in? Have you found any open source solutions that do these kinds of things? For instance in c# ServiceStack Auth does the same kinds of things with credentials and sessions.

share|improve this answer
    
The verification code will be delivered to user's mobile phone mostly. The authentication will be implemented in PHP. Currently we look for the design and afterwards we will think on implemenation details. –  Andriy Lesyuk Mar 14 '13 at 23:47
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.