I'm creating an app where in, a client sends a request to the server and in turn gets a unique request id. This unique request id would be used later authenticate the client when it wants to interact again with the server.
The request of client are of two types:
New request, where it has no existing id and the response from the
server generates and returns an id.
Existing request with the id. The server then processes the clients
request for the id supplied.
My problem is how do I generate the id? I'm using Java and MySQL server database. If I use an auto-incremented database generated id, then it becomes too easy for the client to guess the ids. Another client could maliciously generate a few ids by guessing and misuse them (There is no authentication between the client/sever, except for the ids :< )
If I generate a random id using UUID or some other randomize algorithm, then I need to check the entire database (which could have thousands of records), to really check and guarantee if the random id is unique indeed? Or would it be fast inside the database to check if the id exits and won't cause performance issues?
What measures should I take? Do I need to have more security measures for authentication between the client and the server, other than the unique id?
Using java.util.UUID.randomUUID(); you can generate a cryptographically secure, random UUID.
Since the UUID is 128 bit long, the chance for a collision is negligible, but if you really want to check for collisions, you can do that by storing active UUIDs in the database and check for duplicates after generation.
You can use Java's UUID.
Something like :
UUID uniqueKey = UUID.randomUUID();
And if you don't wanna use that, you can use the time, as it is always changing, add a random number if u wanna be sure.
Create an encoded and unique key for each session, that will be created using the unique data you have of that user, something like his email, current time, etc.
String yourString = "user#email.com"+"timestamp";
byte[] bytesOfMessage = yourString.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] thedigest = md.digest(bytesOfMessage);
Would generate a unique id for each request, store them in a table in your database that contains an expiry timestamp, userid and the key. The on each request, renew the "expiry" time if its still valid, or return error if its expired or invalid.
The valid keys table I use is something like:
userId(int)
key(varchar(32))
expiry(int)
Then if you wanted to see if a user has a valid session open you'd just check that table for the userId and make sure that it's a unique column, to avoid storing a historic of previous sessions.
If you use Spring Framework you may found useful another UUID implementation org.springframework.util.AlternativeJdkIdGenerator:
IdGenerator generator = new AlternativeJdkIdGenerator();
UUID uuid = generator.generateId();
Which is from the documentation:
An {#link IdGenerator} that uses {#link SecureRandom} for the initial
seed and * {#link Random} thereafter, instead of calling {#link
UUID#randomUUID()} every * time as {#link
org.springframework.util.JdkIdGenerator JdkIdGenerator} does. * This
provides a better balance between securely random ids and performance.
If you 'd like to generate it on MySQL side, I think this will do just fine
md5(concat(UNIX_TIMESTAMP(),<user_id>))
If the field is indexed, query won't take long.
Use a UUID to generate a base ID that is nearly always unique.
Hash the base ID to make it difficult for clients to guess and spoof.
Store the hashed ID in the database using a column with a unique constraint.
On the rare occasion the unique constraint is violated, repeat the above steps.
Related
I'm trying to turn multiple integers into a fixed length hash value.... so far so good, however, I need to be able read and decode the hash later on and get my integers back.
To give a little more context, I'm generating a cursor based pagination for an API call that queries multiple tables. So I need to be able to obfuscate multiple table ID's into a string like hash, send it to Front End. Also, I need to be able to receive any cursor hash, decode it into multiple table ID's and query the tables from that ID onward.
What's the right way to do this?
If you consider this a security feature e.g. to prevent users from enumerating the rows in the table by incrementing identifier you probably should generate these user-facing hashes randomly and store them with each table row. In this approach rows will have a shorter numeric primary key (usually better for indexes due to smaller size) and an external user-facing identifier (pretty much not guessable if you use a UUID).
Alternatively you can try to:
Generate hashes separately for each user while storing them in the session. You can use random hashes as long as you have a 1-to-1 mapping between a hash and a row identifier, they will be valid only for the user that opened the session.
Use strong symmetric cryptography (e.g. AES) to encode and decode a a salted value salt + id. This will make it harder to guess what is used to create the hash.
Your current approach with reversible function sounds like security through obscurity or I'm getting paranoid :)
I want to make a javaEE application when users can register and confirm their email when receiving a email with a link after inserting their data in registration form (name, mail...)
To do that I am going to generate a long and unique key with java.util.UUID, store in a database and then send an email to the user with that key being part of the URL (Example: www.mysite.com/account.xhtml?id=KEY). Then the user will click the link, I extract the key from the URL and check if that key is stored in the DB. If it is, the user registration will be completed.
My question is, when creating that key with java.util.UUID, how can I know that it is a unique key? Should I check if there is another equal key in the DB and if so create a new one until the created key is unique?
What's the chance that a randomly-generated 128-bit integer will be equal to another randomly-generated integer?
If you just need peace of mind, use a primary key and if the insert fails due to a key collision, re-create a new UUID and retry the insert.
There are couple of ways you can do UUID in Java.
Java 5 onwards better practice is using java.util.UUID It is size of the string 36 characters. This link gives you simple example.
This discussion will give you answer to your question. It is very strong. I have never came across someone is complaining about its uniqueness.
But if you adding into DB or using in storage or using through network, size may be matters. So converting to other formats - Bases is good solution (Base64, Base85 etc). Please check this discussion here. You can use apache library org.apache.commons.codec.binary.Base64. Base85 is not safe for URLs.
My recommendation is, if you have may application/session beans/web services (many interconnections other applications and data transfers etc) are creating UUIDs, I prefer to do unique application name padding too. Like APP1, APP2 etc and then decode to other bases. If UUID is 6fcb514b-b878-4c9d-95b7-8dc3a7ce6fd8, then APP1-6fcb514b-b878-4c9d-95b7-8dc3a7ce6fd8 like that...
Though it is off the topic here, BUT When you use a URL like this www.mysite.com/account.xhtml?id=KEY, beware about SQL injection hacking attacks.
I'm generating a unique id(generated by the frame work used are, so I should use only this ID and there is no API in the framework to check if this generated by the framework. Thanks RichieHH for pointing this) for each request in the web application and this can be presented back as a part of another request to the system. Now, I am storing these unique ID's generated in the database, and for every request the DB query is issued to check if this ID already exists(this is how the validation is done currently for the unique ID's). Now, if I have to validate the ID sent in the request has been generated by the application with out using the persistent storage, which approach should I be following?
My initial approacht is to generate the ID which adds to particular sum after hashing, but this can be identified after going through the patterns.
It will be great if some one can help me with an approach to solve this problem in a way it can validate the uniqueID generated with in the application. Thanks.
Use UUID, which is pretty standard solution for this task. You don't need to validate UUID, you can assume that it is unique always.
You can use ServerName+Timestamp+some extra. It can be more advantageous for debug but less secure.
Is there any way to configure(xml) tomcat (6.x) to generate unique SessionId.
(Without extending ManagerBase/StandardManager).
I am capturing user login details in db table,with Session Id in a column with unique constraint,and am getting unique constraint exception
You should not store the Tomcat-generated session ID as an unique constraint in the DB. This makes no sense. Tomcat's session ID is only unique within all existing active sessions. The Servlet spec does not forbid to reuse the ID of an expired session for a new session at some point, months or years later. With a fixed length 32-char hexadecimal string as session ID, all possible IDs are not "unlimited". You can't prevent it from being reused for a different client at some point.
I do not understand why you would ever store a Tomcat-generated session ID in the DB lifetime long. You should remove it from the DB whenever it has expired. Or you should solve your problem differently. As you didn't state anything about the functional requirement behind this "solution", I cannot give a more suited answer. Here are however some hints:
Do it the other way round: insert or select the necessary data in/from DB, get the DB-generated ID and store it as an attribute of the HttpSession. For example the logged-in user ID, or just the whole User object.
Or, if it needs to expand the default lifetime of a session, e.g. "Remember me" option, then you should generate an UUID yourself (and test if it doesn't exist in DB yet) and use it in a separate cookie instead.
I'm working on this issue myself, and I'd like to mention that it is possible to generate a guaranteed unique ID using 128 bits (32 hexadecimal digits) using UUID. It is based on UTC time, and is guaranteed to be unique as long as the usec timestamps at which different UUID are generated are different.
See also RFC4122: https://www.ietf.org/rfc/rfc4122.txt
Java has a standard class for generating these IDs:
http://docs.oracle.com/javase/6/docs/api/java/util/UUID.htm
Just use a compound primary key, as CONSTRAINT PRIMARY KEY ("SID" , datum);
I want to resemble the typical "confirmation of account" procedure seen in multiple websites. When a user registers an email is sent to him with a confirmation link. Once the user goes to that confirmation link its account gets confirmed. Don't worry about the email sending process. The thing is that I need to generate a URL to which the user can then enter to get his new account confirmed. This page will need to receive some parameters but I don't want the url to be something like .../confirmation?userId=1 . I want it to be an ecrypted url to avoid abuses, is this possible? So far, I have something like this:
public class CancelReservationPage extends WebPage{
public CancelReservationPage(PageParameters pageParameters){
// get parameters
// confirm account
// etc..
}
}
What's next?
Thanks!
You don't need encryption, better making your parameter totally agnostic. Just generate a random string, for example 12 char long, that you store in DB in the user table.
Aside from the solutions with storing unique key in the DB, there is a more convenient but perhaps less secure method (vulnerable to disclosure of the secret key and breaking of the hash).
Generate a URL containing userId and hash(userId + secretKey), where secretKey is an unique key of your application and hash is something like SHA-1. So, malicious person can't compute the hash unless he knows the secret key, and you can validate the confirmation request by comparing incoming hash with the newly computed one.
SHA-1 can be computed using java.security.MessageDigest or Apache Commons Codec's DigestUtls.shaHex().
You may also include an expiration date to make your confirmation link valid for the limited time.
Pretty simple:
before sending the email, generate a
unique key (a series of characters,
the easiest would be a GUID)
store this unique key in the database and link it to the
associated user account
include this key as a parameter in the account confirmation URL sent in the email
in the account confirmation page code, check the database to see if
the received code is genuinely
generated by your code
if the key is in your database then activate the account