SecurID-like web-service authentication

436 views Asked by At

I'm working on a very small ASP.NET ASHX web service that is running on Azure and I would like to secure. It has to be able to work without user interaction so I was thinking of just passing in some encrypted secret key to the request. But then I thought that, just in case, I should probably make that key change constantly.

So far, my idea is to generate a key in the same way both on the client and the server every 60 seconds, hash it, and use that as the key.

However, I've run into on thing I'm not sure how to handle. If it changes every 60 seconds and the client generates the key on second 59 and then it takes longer then 1 second for the server to respond to the request, it's key will no be different and the request will be denied.

Is there any good way of handling this case... maybe the key changes every 60 seconds, but is good for a few seconds after it changes?

I realize there's probably other ways to secure the service, but I already ruled out things like client side certificates for a few reasons and, in general, I'm OK with it being pretty simplistic. I just wanted it to be simpler than an unchanging password.

Thoughts?

2

There are 2 answers

1
Bart Czernicki On

You are obviously securing the service with HTTPs, that would be step 1.

Your identification/authentication you want the key to expire as you mention having the previous key be valid for a short timeframe. The server would auth against either of the two keys.

I would also add a third security measure...IP filtering. If this is an API that I assume will have some shared "secret" key it should, limit who can access this. This will prevent your keys getting out into the open and someone trying to attack your site maliciously if they happen to hack/acquire they key.

0
Syon On

What you're describing (RSA's SecureID) is based off of the TOTP algorithm.

Not only is the timing issue you've describe a problem, but you should also keep in mind that not all clocks run at the same speed. The client's clock may run slightly faster or slower than your server clock, and over time they may become desynchronized by several minutes. The way the TOTP algorithm handles this (see section 6 of the RFC) is by having the server validate the code it receives from the client against not just the current time code, but also several codes in the future and several codes in the past.

                            Client       Server
                    Time    Code         Code   Time    Offset
                                   Match 849207 8:30:00 -0:00
                                         641239 8:30:30 -0:00
                                         761548 8:31:00 -0:00
Current client time 8:30:00 849207       103970 8:31:30 -0:00 Current server time
                                         846541 8:32:00 -0:00
                                         861321 8:32:30 -0:00
                                         132465 8:33:00 -0:00

If the server detects that the codes are out of sync by a certain amount, it calculates the offset (how much time the clocks are out of sync by) and then takes that offset in to account in the future.

                            Client       Server
                    Time    Code         Code   Time    Offset
                                         628484 8:45:00 -1:30
                                         137864 8:45:30 -1:30
                                         679913 8:46:00 -1:30
Current client time 8:45:00 264951 Match 264951 8:46:30 -1:30 Current server time
                                         971034 8:47:00 -1:30
                                         626378 8:47:30 -1:30
                                         599171 8:48:00 -1:30

Even if the clocks continue to drift apart, the server will just resynchronize again by increasing the offset when the codes get too far out of sync.

If you do go forward with this, I highly encourage you to use a library that's compliant with the RFC. Most languages have open source implementations that are relatively easy to find, which will make integrating this authentication easier for your consumers. There's several C# implementations, this one claims to work with Google authenticator (which I know to be compliant with the TOTP RFC).

Note: Most TOTP libraries do not handle the resynchronization process for you because you need to store the synchronization offset. This is fairly simple to build on your own though, just read through the relevant sections of the RFC so that you understand the process thoroughly.

P.S.

If you're planning to use this for machine to machine authentication, I'd urge you to consider if it's really worth it. While it's fairly easy to implement, it's still a lot more work than just a straight username and password, and it probably doesn't add much (if any) real security (if you were not using SSL, then I'd say otherwise.)

TOTP-like systems operate on a shared secret key (code=TOTP(key, time)). This is useful for humans because attackers cannot steal the code or shared secret without physical access to the SecureID (or whatever brand) token. The only attack is to get the current code from the user and use it immediately. This is not true for machine to machine authentication though, because the client machine must have access to the shared secret to generate codes. If an administrator or attacker could steal a static password off the client system, there's no reason they couldn't steal the shared secret instead.

I would argue that, under most circumstances, the only thing that TOTP-like authentication adds to machine-machine communication is a layer of obscurity. Just my two cents.