Most likely a dumb question but how do I create a ...
# cfml-general
r
Most likely a dumb question but how do I create a static bearer token that someone can send back to me when using my API?
b
Are you wanting a token that expires like Oauth or just a one-time token for that user>?
We do the latter in ForgeBox and it's literally just a giant random string we store in the user table as APIToken for them.
r
A one-time token I think
b
It's not related to their password and can be rotated if compromised and we use it to authenticate API calls
it's not quite as full fledged as an oauth flow which requires a refresh token and has a time limit and all that stuff
but it's much simpler to deal with
r
Yes, just a one-time token that I could rotate if required. Is there a special, recognised, way to generate them?
not neccesarily what it was intended for but you could probably use that
or just write a function like:
Copy code
<cfscript>
    function RandomString(length, chars="ABCDEFGHIJKLMNOPQRST0123456789-") {
        var i = 0;
        var theString = "";
        for (i = 0; i < length; i++) {
            theString &= Mid(chars, RandRange(1, len(chars), "SHA1PRNG"), 1);
        }
        return theString;
    }
</cfscript>
(which I copied from https://lunaticthinker.me/index.php/cfml-generating-random-string/)
b
For what it's worth, forgebox uses a sha-512 hash of a new GUID joined with the current time to try and have good randomness
I think the main goals is just to have tons of entropy and randomness
s
personally I think the CSRFGenerateToken() and CSRFVerifyToken() functions could possible do the trick if I am understanding your need correctly
seems like a simialr need to the cross site forgery prevention
r
Ah, I didn't think of
csrfGenerateToken()
, thanks.
b
Lucee's implementation of that BIf basically this
Copy code
public static String createRandomStringLC(int length) {
		if (length < 1) return "";
		SecureRandom sr = new SecureRandom();
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < length; i++) {
			int rnd = (int) (sr.nextDouble() * (CHARS_LC.length - 1));
			sb.append(CHARS_LC[rnd]);
		}
		return sb.toString();
	}
where CHARS_LC is an array of lower case letters and the length is 40
So honestly, that's not any different than the CFML code snippet above
s
I don't think I have ever used
csrfGenerateToken()
to prevent cross site request forgery but I have used it for other things, like generating a token for forgot password links that get emailed to users and stuff like that.
b
The thing I like about ForgeBox's approach is the inclusion of the date means the same token could never be generated twice
Most GUID generators also take date into account'
That Java code BTW is from Lucee's
RandomUtil.java
class on line 42
r
Thank you both, plenty of options to think about.
e
I think @ben had something on this about a decade ago.. Anyrate, you could do something like this: <cfset token = hash(getTickCount(), "SHA-256")> <cfif structKeyExists(getHTTPRequestData().headers, "Authorization") AND getHTTPRequestData().headers.Authorization EQ "Bearer #token#">
r
Yes, I should have remembered, all questions lead to an answer from Ben 🙂
b
I would not recommend ben's version at all.
Not random at all!
A hacker could guess all the API tokens your app will generate based on the time
This is why you should be very cautious to take crypto advice from the internet 🙂
r
🤔
b
That's why the forgebox version above takes the time AND a GUID (which uses your machine's randomness into account)
The hash does nothing to actually add entropy
In other words, you may has well just use the tick count as your API token as any hacker is capable of generating sha hashes!
If I knew you signed up for your API token between 1 and 2 pm, I would only need to check a few thousand possible hashed integers to discover your token
e
Or you can turn all those lines into basically this: <cfset guid = createUUID()> <cfset currentTime = timeFormat(now(), "HHmmss")> <cfset dayOfMonth = left(day(now()), 1)> <cfset lastLetterOfHour = right(hour(now()), 1)> <cfset token = hash("#guid##currentTime##dayOfMonth##lastLetterOfHour#", "SHA-256")> <cfif structKeyExists(getHTTPRequestData().headers, "Authorization") AND getHTTPRequestData().headers.Authorization EQ "Bearer #token#">
b
You're not adding any entropy by chopping up the date like that
e
Its entropic enough
you could grab session id
b
Plus now you've basically come full circle to what I said ForgeBox was doing above
e
its either is or isnt what forgbox is doing
b
Whether you format the date or use the tick count, it's not random. That's the key here. Predictability has low entropy regardless of the format
e
hah
All encryption is predictable, it's just a matter of time.
b
That's a nonsense statement. The current date/time is predicable. A (well-written) random library is not predictable.
Most all GUID generators I've seen in java use
java.util.Random
e
b
Honestly, just using a GUID here is probably just as secure as anything, lol. Sha 512 hashing it will make it look longer, but again, it's not actually adding any entropy if a hacker knows you sha-512 has your values.
UUIDs and GUIDs are generated in the same matter. It's just a matter of where you insert the dashes
e
We are taking a random number, crapping it to another random number, then taking two random numbers by a moment of time, binding it all, and encrypting it. Its random enough 🙂
It's like bitcoin mining, the first few coins will always be easily obtainable and sucky, but as time moves on and more primes are hashed, it becomes an ever-surmountable yet obtainable mountain of decryption. Sure, its possible to reverse it all, and in time someone will do so, maybe with the next Nvidia graphics card designed to run call of duty at a reasonable frame rate emulated in ColdFusion :)
and in defense of ForgeBox (and all the cool other boxes) if you can redesign your stuff using their framework DO IT, save yourself in the end.