Search code examples
securityauthenticationtokennancy

Is it possible to revoke a token with Nancy.Authentication.Token?


I've looked through the source code and tests, but don't see a way to revoke a token. I need to cover scenarios where I disable access for a user and need that occur immediately.

Given that the token is stored in keyChain.bin, it might be possible to deserialize the collections, detokenize all tokens, remove the desired on, the serialize the collection again. This sounds elaborate. Are there any other methods I could use?

Update

Potentially I can keep a separate list of user ids and the token that they have been issued, then match the token with the keyChain collection.

Update 2

After playing with the keyChain file, things are little more confusing. After creating a new user, I issue a token:

var newServiceIdentity = siteSecurityManager.CreateServiceUser(user.UserId, user.Password)
                                                        .GetServiceIdentity();

string token = _tokenizer.Tokenize(newServiceIdentity, this.Context);
newServiceIdentity.Token = token;
siteSecurityManager.RegisterToken(newServiceIdentity);

var fileStore = new FileSystemTokenKeyStore(_rootPathProvider);
var allKeys = fileStore.Retrieve() as Dictionary<DateTime, byte[]>;

return new { Token = token };

By default, Nancy will store each token in a binary file so that should your server need to be bounced, the user sessions will survive. With a different browser session, I connect with the new users credentials and gain access to the site. When I add another user, I would expect that the allKeys count would incremented to reflect my admin session as well as the new user that is connected with a different browser. I see a count of one, and the key matches the admin token.

My login method does indeed issue a token for each user that connects with correct credentials. That logic is:

var userServiceIdentity = ServiceIdentityMapper.ValidateUser(user.UserId, user.Password);

if (userServiceIdentity == null)
{
   return HttpStatusCode.Unauthorized;
}
   else
{   
   string token = _tokenizer.Tokenize(userServiceIdentity, this.Context);
   return new { Token = token };
}

I store the token and return it with each Ajax call. The implication here is that I do have the tokens recorded, otherwise authentication would fail. But if the keyChain.bin is not updated, then I can't pursue the idea of registering the token and user in a separate store, then purging that token to revoke access.


Solution

  • As explained to me by Jeff, the code's author, the keyChain.bin stores only the key that is used to generate the token. This is so that the relevant information is only stored on the client, and a simple comparison of the client token is used to avoid querying a back-end source. Jeff's complete explanation is here

    A possible solution would be to keep a separate list of black listed tokens / users. Perhaps this is best dictated by business practices. There are indeed times where you should lock a user out of immediately. This could be accomplished by issuing a purge for all tokens, and force a login for all legitimate users. A minor inconvenience for some scenarios, and unacceptable for others.