Decentralized Authentication and Identity Hijack Backdoor


In the centralized applications world, authentication and authorization techniques and practices have been well established for as long as the www internet has emerged. They are based on the centralized services and data stores and a server -or cluster- playing the main role of distributing data to the eligible user and/or connection session, all controlled by the hosting machine/s. On the other hand, for decentralized applications the scenario is completely different, the concepts of authentication and authorization are meant to be achieved on the client-side, which raises new kinds of techniques and practices, hence new kind of security issues.


The authentication/authorization techniques introduced by Blockstack are based on generating a JWT token using the user keys and a browser-generated transient key. Like oAuth, authentication with Blockstack aimed a less-hassle user experience by generating the token for the user session and store it on the client-side. Depending heavily on the browser localStorage to keep all the user keys and identification data safe in client-side, it exposes them to users and allows them manipulating it, of course, will not change it on the Blockchain ledger, yet as mentioned above, those data are the authentication and authorization used by the app which is fetched from local storage upon app loading.

Identity Hijack

It’s a common practice that upon a dapp reloads, if it is an already authenticated app (has valid authResponseToken and transitKey stored in localStorage), the dapp fetchs the userData from localStorage to use it, with the risk of loading other previously manipulated values by an identity hijack attacker. Relying on those data -for example in Radiks models- will allow such attackers to hijack others identity.

Case studies

After logging to Banter, I changed the username in localStorage to another (here, refresh, made a post, and voila:

Changing the username value and reloading the dapp allows the attacker to hijack the identity of the victim

Same attack was tried on different dapp, here Mumble was it:

Proposed Solution

Since authResponseToken and transitKey are stored in the localstorage which are responsible for creating the blockstack-session, would be a good practice to re-generate them on every time the app reloads and use them to re-create then blockstack-session.

if(userSession.isUserSignedIn()) {
        const {authResponseToken} = userSession.loadUserData();
        const {transitKey} = JSON.parse(localStorage.getItem('blockstack-session'));
        await userSession.handlePendingSignIn(authResponseToken);

On the preview piece of code, upon the dapp loads, we reset the user data using the the transitKey genereted from the successful authentication, hence on every dapp reload we re-retreive the right user data on every time the dapp reloads, avoiding any previous attempt to modify them hence cut the way in front of that identiy hijack backdoor.


Building Dapp requires a closer care about information security due to its different nature to a common centralized app. Without a deep understanding of the tools and the relatively new technology in hand, simple -but serious- issues will always find their way. A common user doesn’t care about what is happening behind the scene and may don’t understand how actually the technology works, but it’s the developers duty to always optimize and follow the core values the technology stands behind and commit to adhere, mainly security and privacy. 

Bad developers practices usually open invalid arguments about the reliability of any technology or platform, in particular when it comes to relatively new ones like Blockchain and Blockstack ecosystem.