Session-Lock: Device-Token Binding in JavaScript #49
Replies: 2 comments 26 replies
-
This looks great! All of the drawbacks you list are fixable with including server challenges and browsers implementing the key storage in malware resistant ways. You would just lose the low latency property for many users. But therein also lies a catch. We did in fact experiment with something like this, as we were drawn to the simplicity. However we found even more complexity in how to retrofit this to existing webapps. To use your example: What does the server do when it inevitably receives a request with a timestamp that is too old? It needs to somehow signal back to the browser that it should regenerate a signature, and then retry the request. And generally when this happens, the browser has already sent multiple requests with the now expired token - so the browser-side mechanism here has to handle that. The best we came up with, that didn't require new complex APIs, was to signal that failure and retries with 302 redirect responses. But these aren't designed to be idempotent retries, so apps (both client and server side) would have to deal with that some other way. In addition, to avoid flooding e.g. a TPM with multiple simultaneous requests when this happens, the handling of the 302s by the browser had to be somehow special anyways, in order to coordinate them. In the end we ran aground with this, and that's why the somewhat strange new complexity in DBSC is there. |
Beta Was this translation helpful? Give feedback.
-
Two things:
|
Beta Was this translation helpful? Give feedback.
-
I put together a proof-of-concept library for device-token binding last year that's similar to this proposal in spirit (recently found this due to the announcement). It may or may not be ready for production use, but it can be implemented today and will work across all reasonably modern browsers, minus Firefox in private browsing mode. For better or worse, it does not need a TPM to work, so it should support most hardware. Server-side implementation should also be fairly quick and simple, or at least more so than the proposed DBSC flows. In addition to browser JS, the library includes functions to be used in Node.js servers to simplify validation.
Repo: https://github.com/zainazeem/session-lock
Writeup and demo: https://session-lock.keyri.com/
Flow
At login, the browser creates an ECDSA key pair with SubtleCrypto. The private CryptoKey is set to be "unextractable", and a reference to it is stored in IndexedDB. The public key is sent as part of the login request. The server adds this key to the payload of the JWT it returns to the browser. Whenever the browser wants to use the JWT, the library appends a timestamp to the JWT, generates a signature for this combined string, and appends the signature. The server then extracts the public key from the JWT and uses it to authenticate the JWT+timestamp, in addition to authenticating the JWT itself through the usual verification of its server signature. It also checks the timestamp to make sure it is recent enough to be within the server's recency threshold for preventing replay attacks. The CryptoKey reference may or may not be removed from IDB at logout.
Advantages
Drawbacks
extractable
property totrue
, and pull it out.Overall, such a flow can already be implemented by individual applications with little effort to protect almost all of their user base against current token theft threats. These threats would have to become a fair bit more sophisticated in order to defeat this strategy. The strategy can also be implemented in native mobile apps, in which case it would take advantage of TPMs and reduce the tampering risk.
Hopefully this was helpful in some way. Feedback/questions are welcome, and I look forward to this project's development.
Beta Was this translation helpful? Give feedback.
All reactions