Where to store hashes, salts, keys in Desktop Applications - java

I am trying to figure out where or how i should store application secrets and keys inside a desktop application.
For example a facebook app key or dropbox key and secret.
So I've read that i should hash, salt, encrypt etc etc these values. This is to prevent someone from reverse engineering my code and seeing the keys.
The is all good and well, but with all these methods, i'm just storing a salt or hash value somewhere instead of the key itself, in the end. Surely if a hacker can get to the salt/hash and possibly the source code, they will be able to decrypt the encrypted key and get my password/key/secret anyway?
One option I've read about that seems the most secure is to not store this value in the desktop app at all, but to call a web service to obtain the key (probably encrypted).
But my question is, even in this case, a decent hacker will surely just do a memory dump or something to see what the value returned from the web service is, and then we're back at square 1.
The next best alternative seems to be obscurity.
Am I missing something completely?
On a side note, what use will a facebook/twitter/dropbox/etc key/secret be to a hacker anyway?
Surely they would still need a user's credentials or access token to be able to use it anyway?
Any advice or suggestions will be appreciated.

For each user account generate a new access token for the application when they successfully log into your service. Your login service should be designed much like a login for a website:
The API should only allow a set number (say 5) bad login attempts that reports back to the desktop client that the username/password do not match.
The API should return a token affiliated with only that user when the user successfully logs in.
Use SSL and a localized hashing method to pass user passwords to your API
This auth token provided by your API will only work for the individual account and as such should only allow the user to perform operations to their individual account. So for instance, if a user wants to perform an operation they must be able to provide a valid auth token in order to complete the action. Using this method attackers will still be able to obtain an auth key, but that auth key will only be able to perform operations for the account in which it is generated. It will not be able to perform operations on anyone else account. The idea here is to let them mess with data but to keep the bad activity compartmentalized to one account.
From there, if you do have generic API calls (say an image search) that accesses data from multiple accounts make sure that you are never returning or allowing for any account to access all the data in your system outright. Provide only a limited number of records. In this case the system is still performing its job, but at no point allows all the records in your system to be accessed.
I typically implement a service like this:
User logs in and gets an auth token. I store said auth token in a database associated with that user.
User calls web service with auth token. I lookup user account by the transmitted auth token and User ID (two forms of authentication) and use the discovered user account to perform all operations. I don't just assume the User ID is correct, it has to be the one the auth token authenticated against.
If a user needs to perform a delicate operation like reset a password, my app opens a browser window or browser task in the app where the user can request and administer a reset. I can more-easily secure a web application than one on an unknown client.
Using these methods you should be able to make a fully operational desktop application. There are outliers to this functionality, if you have any post them up in the comments and we can dive further into the problem and see if this solution can still work for you.

Related

Encryption algorithm for URL Identifiers

I am working on a Spring Web application, and came across a scenario that requires passing an identifier in the URI (GET over HTTPS), for example: https://www.targetdomain.com/services?id=123. This URI appears on the end user browser, and my concern is that, anyone can tamper this identifier "123" that is linked in my database as primary key in one of the table.
One way to resolve this issue could be to save this in user's session (HTTPSession), another could be to encrypt it and throw that in browser as https://www.targetdomain.com/services?id=jk3434jj123jkh23jh213h. Once end user clicks on the link, I can decrypt that on the server side to retrieve the identifier.
I am new to encryption, and I wanted to know what suitable encryption algorithm, I should use to encrypt this identifier before printing that on browser, so that I can retrieve it on the server
I came across some post (for example - encrypt and encode URL parameters spring mvc) where a working code is presented using "AES/CBC/PKCS5Padding" as cipher. Does that looks a good solution for this use case?
The most secure solution would be to manage the parameter in the session as you described, if that's an option. That way it's all on the server and it's protected against an attacker having access to a user session in a browser (but not to the server). If you can do this, it's probably the right thing.
However, sometimes you need to pass through the browser. For whatever you send to the browser, you might have two distinct requirements:
You might want that the user cannot read it, for which the solution is encryption. In case of an id, this is probably less relevant, but your ids might also be sensitive in some way, only you can tell.
You might want that the user cannot modify them, and for this you need message authentication. This requires a secret on the server, used to generate an authentication code for your parameter, that upon receiving them back can be verified (using the secret again).
Note that these are two separate things, encrypted messages are not necessarily authenticated, and authenticated messages are not encrypted.
So if you only care about message authentication, you could add an authentication code as a separate parameter, generated with eg. HMAC, and then check that upon getting your parameter back.
Or depending on your requirements, you can choose an authenticated encryption (AEAD), which provides both features in one. Such an algorithm is eg. AES in GCM mode. (AES-CBC mentioned in your question is not an authenticated mode for AES.)
Note that you would have to consider replay attacks as well. If you only authenticate or encrypt the parameter itself, a user can observe such encrypted parameters in other sessions for example, and replay those in his own session. One standard solution to this is to include a timestamp as well so that such secure parameters are also timebound, and even this in your specific scenario might not be enough. For example if access control is based on such an authenticated parameter, an observed authenticated, timebound parameter in another user's session might be used to access data in the current user's session (albeit this would be harder to actually exploit).
Or you can still just do it through the session... :)

Should we delete or invalidate jwt after every login?

I am trying to implement signup and login functionality and I am using Spring Boot and java stack. I am following this tutorial(you don't have to click on it, just putting here for reference and completeness of this question).
Spring Security MySQL JWT Tutorial - Grokonez
Now I have an endpoint for signup and login. After signing up and adding user to database, I am logging in. For the sign in endpoint, I am getting a jwt token. Using this token, I am able to access restricted resources. Everything is awesome till now. Now, when I hit the signin endpoint again, I get another token.
This is where my dilemma is. Since I have two tokens, I can essentially login using two tokens. Now of course, both of these tokens have an expiry date(for example like a day). But in terms of good practice, should we invalidate the old token meaning that at any given point of time, there will be only ONE token that any user can use to login to our system?
If that's the case, would that mean that user cannot use our app simultaneously on both devices like laptop and mobile phone? In that case then, what's the upper limit on active tokens?
I have heard something about refresh token etc, but I just want to keep this simple and I am ok with having just a single token called access token.
So, if you think I should invalidate jwt and keep only one active jwt per user at any given point of time, how would I do that? Store jwts in db and do something?
If you are going to store the JWT token in the database, then, no point of using JWT token. Because, the main reason for having a self-contained, singed token is to avoid the database validation when user access the application.
I can suggest below way to avoid creating multiple active tokens.
You can keep the JWT token created time(last) in the database, and then, you can cross check the last created time (compare with the current time) when user sign in to the application.

How to prevent token substitution attack?

Suppose we have two users doing following operation -
User1 requested to the auth server for access token and granted also.
Now user1 save the token into localstorage/cookie for future api access.
Now User2 approach User1 browswer and get the access_token some how.
Now User2 call the api using user1's access_token and get the access too without login.
Now Can we validate the token anyhow?
You can't avoid that happening. However, the token should have an expiration time, so the attacker will only have access during that time. Also, if you know that a token has been stolen, you can revoke it so it's no longer valid.
You could apply more security measures such as associating the token with a specific IP address, or some advanced services that even use machine learning to detect unusual behaviours.
Confidential information such as an OAuth Token should never be stored in HTTP Cookies unless encrypted. The encryption should be client / session specific meaning that a different encryption key should be used for each client session. If an intruder were to extract the encrypted cookie and attempt to use it for a different session the decryption would fail rendering the cookie invalid.
In your scenario, User B obtains access to User A's session. There is not much protection available. This would be similar to you logging into your bank, leaving your desk for coffee and someone else sits down and starts transferring money using the same browser window that you logged into.
Security is only as strong as the weakest link. Each component must implement strong security. If a single component can be breached, then the other security components might also fail.
There is a tradeoff between very tight security and convenience. Human beings tend to sacrifice security if the processes are too tedious or too difficult or just plain get in the way.
My bank does something interesting. Once I login and keep doing stuff (clicking links, moving the mouse, etc.) I stay authenticated. If I pause for one minute, then the next time I click a link I must reauthenticate. Interesting strategy to detect a person who might have left his desk unattended.

how to detect the user in OpenID Connect provider token endpoint

talking about the authorization_code grant type. In authorization end point of the OpenID Connect provider we gave an authorization code to the relying party and then they makes a back channel request(no browser involved) to the token end point with this code.
so the question is , How to distinguish this user at the token end point?I guess no session exist for this call since its a back channel request.
What methods can be used to identify the user. could a stored HashMap in memory with key as authorization_code be the ideal solution
Storing it in a HashMap is a solution that does not scale, as internal memory is not shared accross server nodes.
You'll have to store it in some form of persistent store
a SQL database
a NoSQL database
a key value database
Note that you'll not only need to be able to determine the user, for which it was made, but also the client, as clients don't need to authenticate themselves to get a code. Also know that you'll need to be able to determine which scopes are covered by a given code, and to detect double usage of a code, and in case of double usage, to revoke associated access tokens.
On the other hand, you need to be able to easily forget the codes again. They're short term use, and it's no use keeping them around after their ttl.
You'll have similar requirements for storing the access tokens, refresh and id tokens you produce, so it'll make sense to build something which can also be used for those.

Can JJWT invalidate tokens on the server-side?

I'm new to JWT and was wondering if it is possible to invalidate/void JWTs on the server-side when a user signs out of an application (I'm also wondering if it even makes sense to do so!). Idea is:
User clicks a sign out link in their app
App makes a call to POST https://api.myapp.example.com/auth/invalidate
The JWT (which is an authorization/bearer token in the HTTP request header) is somehow invalidated
Now, no one can ever use that JWT again
I'm not sure if this is an unorthodox approach to signout logic or not, or whether its acceptable to just let the JWT linger as valid, even after the user signs out (I guess I could shorten the life of the JWT expiry to, say, 60 mins or something).
So again: wondering if its possible to do this kind of "invalidation" using JJWT (and if so, how?!) as well as whether it even makes sense to do this (and if not, what does a typical signout flow look like?!). Thanks!
The other answers are correct in that you normally don't need a sign-out/invalidate endpoint. A user signing out from your application means you just delete his/her token from local storage.
If you are however still determined to implement a token invalidation endpoint, you could do it by keeping track of a "blacklist" containing the IDs of invalidated tokens:
When a user calls the endpoint, you add the token's ID to the blacklist.
For every authenticated request you first check if the token's ID is contained in the blacklist and refuse access accordingly.
Make sure that old/obsolete blacklist entries are automatically cleaned up and don't eat up your memory.
However also make sure that the blacklist's entries' time-to-live is at least as long as the token's validity duration.
For the implementation, you don't necessarily need a DB, you can use an in-memory self-expiring map like f.i. guava's CacheBuilder or one of the alternatives discussed in this thread.
You don't invalidate JWT, JWTs are immutable. Validity of the token depends on expiration time and signed key, in a serious security incident you can change the signed key then already issued tokens will be invalidated. Also you can use blacklist of tokens in the database, but this will cost another trip to database, if you use this the authentication flow won’t be stateless anymore.
Once user signed out, then the token must be deleted from client side where the token is stored, typically storage of the token is a cookie or the localStorage of browser.
This is one of the core downsides of JWT--they're self-contained tokens, which means there's no inherent way to invalidate them. At most, you could create a token ID (UUID.randomUUID()) and try to maintain a revocation list, but then you're back to needing most of the infrastructure JWT is supposed to free you from.

Categories