Best practices for SessionId/Authentication Token generation
UUID
generation is random, but random with bad entropy means that you will end up with easy to guess UUID
s. If you use a good random number generator, you can generate UUID
s that can be used for sessions. The catch to this, however, is that UUID
s don't have built-in re-play prevention, tampering, fixation, etc., you have to handle that on your own (read: a UUID by itself shouldn't be considered a valid session ID by itself). That said, here's a good snippet for how you would generate a secure UUID
using python
:
Unique session id in python
Disclaimer: I am not a cryptographer.
Do not assume that UUIDs are hard to guess; they should not be used as security capabilities (identifiers whose mere possession grants access), for example.
While in general that is true, it should also be noted that some systems produce UUIDs using cryptographically strong pseudo random number generators (e.g. Java):
public static UUID randomUUID()
Static factory to retrieve a type 4 (pseudo randomly generated) UUID. The UUID is generated using a cryptographically strong pseudo random number generator.
Returns:
A randomly generated UUID
I was wondering, what algorithms are used for example in Java and .NET for SessionId/AuthenticationToken generation.
Tomcat does not use UUIDs as session tokens but uses a SHA1PRNG secure random generator for producing session IDs:
/**
* The name of the algorithm to use to create instances of
* {@link SecureRandom} which are used to generate session IDs. If no
* algorithm is specified, SHA1PRNG is used. To use the platform default
* (which may be SHA1PRNG), specify the empty string. If an invalid
* algorithm and/or provider is specified the {@link SecureRandom} instances
* will be created using the defaults. If that fails, the {@link
* SecureRandom} instances will be created using platform defaults.
*/
private String secureRandomAlgorithm = "SHA1PRNG";
This is just the default and you can provide your custom session ID generator by implementing the org.apache.catalina.SessionIdGenerator
interface.
Other than using a randomly generated string in the session ID, the standard implementation also adds a jvmRoute
to the session IDs that it generates:
A routing identifier for this Tomcat instance. It will be added to the session id to allow for stateless stickyness routing by load balancers. The details on how the jvmRoute will be included in the id are implementation dependent. See Standard Implementation for the default behavior.
Strength of SHA1PRNG
has already been discussed here.
Is UUID indeed unsuitable for these purposes in an application that has more than average security needs?
Java UUIDs are almost as secure as Tomcat's default session ID generator which generates 16 byte long session IDs:
Tomcat:
/** Number of bytes in a session ID. Defaults to 16. */
private int sessionIdLength = 16;
java.util.UUID in OpenJDK 7:
public static UUID randomUUID() {
SecureRandom ng = numberGenerator;
if (ng == null) {
numberGenerator = ng = new SecureRandom();
}
byte[] randomBytes = new byte[16];
ng.nextBytes(randomBytes);
randomBytes[6] &= 0x0f; /* clear version */
randomBytes[6] |= 0x40; /* set to version 4 */
randomBytes[8] &= 0x3f; /* clear variant */
randomBytes[8] |= 0x80; /* set to IETF variant */
return new UUID(randomBytes);
}
But you can configure Tomcat's session ID generator to use more than 16 bytes for added security.
Further reading:
- https://security.stackexchange.com/a/7945/122069