from Hacker News

Making Beautiful API Keys

by savannahkc on 1/10/25, 2:01 PM with 103 comments

  • by stitched2gethr on 1/10/25, 2:41 PM

    I guess this is an unpopular opinion given the existing comments, but I don't get it. They spent time and energy on this instead of writing features or fixing bugs and I don't think it matters at all. The only interaction I have with my API keys is copying them from one place to another. If I need to manually identify a key then putting the first or last few chars, whatever they are, in my working memory is more than sufficient.
  • by lovasoa on 1/10/25, 2:34 PM

    Dashes in API keys are really annoying. Double-clicking doesn’t select the full key, which just adds extra hassle. It would be much better if they used a continuous string without any separators. Makes copying and pasting way easier, and doesn't affect security at all.
  • by theamk on 1/10/25, 2:12 PM

    One of the best things you can do to your API key is to give it a fixed prefix. Makes it very easy to tell that you have the right string, to detect accidental secret leakage, etc...

    IMHO this makes key much more beautiful than any internal structure.

  • by anticorporate on 1/10/25, 2:25 PM

    I love the throwback reference to the Diablo II CD key. There are some CD keys that will be forever etched in my brain, no matter how many PINs I struggle to remember. I suspect a good number of you know far too much of a certain string that starts with FCKGW.
  • by remram on 1/10/25, 2:45 PM

    I use URLs as API keys, so they are self-descriptive (links to a page that tells you what it is/what service it's for) and self-revocable (there's a button, no need to post it to a GitHub repo to have them revoke it for you with their secret scanner [1]).

    I bring this up a lot [2] but I do think there is value in being able to tell if something is a secret and tell where to go to revoke it if found. Most current API keys use some sort of prefix at least (AWS, SendGrid, GitHub, etc).

    [1]: https://docs.github.com/en/code-security/secret-scanning/int...

    [2]: https://news.ycombinator.com/item?id=28296864

  • by PaulHoule on 1/10/25, 2:23 PM

    I invented (more or less) Crockford Base32 back in 2001 which I called "Base32t" (t for Tapir, because it was part of the "Tapir User Management System") for encoding password reset tokens and such. (Minus those squicky check symbols... Right out of the mind that left us the seductive but slightly flawed JSON [1])

    I used T.U.M. for a number of sites including one that was in the Alexa top 2000, even though it was open source it got no pickup from anyone else. The standard at the time was to pick up some software like PHPNuke which did a lot of things badly as opposed to my Yahoo-inspired approach of "pick the best of breed software and plug them into a common user management system".

    The idea didn't get any traction until 2013 when things like this popped up like mushrooms. Seemed the missing features were "vendor lock-in", "somebody else owns your user database", "they might shut down, get bought by Google or kick you out of the free tier."

    [1] I've seen it enough that I'd expect higher uptake if you inject small flaws into a specification like that.

  • by philo23 on 1/10/25, 2:39 PM

    A bit off topic, but on the copying issue with dashes, you can wrap the whole key in a span styled with “user-select: all” to improve the copying experience. Well, on the web at least!
  • by fusspawn on 1/10/25, 2:46 PM

    I really dont see the benefit of these. its just guids with extra steps. its not any easier to read than guids.

    its an alphanumeric random string in both systems.

    yes theres is kinda symetrical. but im not going to find it easier to communicate/remember say:

    38QARV0-1ET0G6Z-2CJD9VA-2ZZAR0X

    any easier than i am

    d1756360-5da0-40df-9926-a76abff5601d

    both are long random strings. both are awkward to have to read over say a phone call.

    what am I missing here?

  • by mtmail on 1/10/25, 2:20 PM

    "encodes UUIDs to a readable Key format via the Base32-Crockford codec and also decodes them back to UUIDs."

    Example: "d1756360-5da0-40df-9926-a76abff5601d" => "38QARV0-1ET0G6Z-2CJD9VA-2ZZAR0X"

    I think now you risk having 0 vs O or I vs 1 readability issues. [edit: good news, I was wrong]

  • by a12k on 1/10/25, 2:42 PM

    This is the very definition of bikeshedding. It should be included as a reference in any definition of that term.
  • by progbits on 1/10/25, 2:41 PM

    This is missing a checksum which helps secret scanning avoid false positives in other high entropy strings.

    See for example: https://docs.github.com/en/code-security/secret-scanning/sec...

  • by savannahkc on 1/11/25, 9:04 PM

    Hey everyone. Thanks for all the discussion on the article. We wanted to respond to a few common themes:

    0. Some folks don't care about API Keys, that's okay! But for those of you who did respond and do care, we are updating our design based on your feedback.

    1. When we got to work on making our API Keys, we looked for an obvious standard but didn't find one. So we decided on our approach quickly and put together uuidkey in an afternoon. We knew it was not going to be everyone’s preferred design, but we wrote up the article to share our thought process as well as generate some marketing. We are happy to see that the article did well and we got feedback! :)

    2. The ability to double-click to copy, which was lost with the addition of dashes, was more important to developer commenters than we thought it'd be (even if only needed once). We heard you, so we've already updated https://github.com/agentstation/uuidkey to support a `WithoutHyphens` option for the `Encode` function so you can generate keys without dashes.

    3. Some folks were worried that our resulting key after encoding has fewer bits of entropy compared to the original UUID. The Crockford base32 encoding does not reduce entropy, it is a 1:1 mapping.

    4. One quality piece of feedback pointed out that the UUID spec warns against using UUIDv7 (only 74 bits of entropy) and even UUIDv4 (standard 122 bits of entropy) alone for API Keys. We plan on still supporting UUIDv7 and UUIDv4, but will add additional entropy bits to follow the official recommendation.

    4. Lots of commenters like prefixes, which make it easier to identify & search for keys (particularly to ensure they don’t get accidentally committed to a repo). We plan to add an option for that. Worth mentioning that a few folks pointed us to Github's auth token implementation that includes prefixes, which is a pretty great standard - https://github.blog/engineering/platform-security/behind-git...

    Thanks again for reading, debating, and giving us some good advice! We want a product that feels good for developers to use. :D

  • by smashed on 1/10/25, 2:52 PM

    I don't quite understand the need for a timestamp. This only reduces entropy? You wouldn't think of using the current date in a password prefix for example.

    Aren't you going to track the keys in a database, where you can keep the tenant id and creation time, scope of the key and any other significant metadata anyway?

    A static prefix + checksum, maybe a version number so you can future-proof the system sounds like best practice. For example `ASKEY1-(128bit random base32 encoded)-(chksum)`.

  • by voidUpdate on 1/10/25, 2:28 PM

    It may just be personal preference but I think I'd find it more beautiful if there were 5 characters per block, instead of 7. It has a better rhythm to say it in my head
  • by tzury on 1/10/25, 2:53 PM

    API keys and UUIDs serve fundamentally different purposes, even though they may look similar as random strings:

    1. API keys are security credentials: - They are meant to be secret and revocable - They often encode metadata about permissions and identity - Compromised API keys must be invalidated and replaced - They function like passwords for authentication/authorization

    2. UUIDs are identifiers: - They are designed to be globally unique but not secret - They contain no inherent permissions or privileges - There's no security risk if others know a UUID - They function like serial numbers for identification

    To use an analogy: An API key is like the key to your house (needs to be kept secret, grants access, can be changed if compromised), while a UUID is like your house's street address (can be public, just identifies the location, doesn't grant any access by itself).

    Thinking they're equivalent is like saying your house key and address are the same thing just because they're both strings of characters. This misconception could lead to serious security vulnerabilities if API keys are treated with the same casualness as UUIDs.

    PS, we all liked this site, right? https://everyuuid.com/

  • by pksunkara on 1/10/25, 3:02 PM

    This ulid Postgres extension doesn't have any performance issues compared to native uuidv7 in Postgres. https://github.com/pksunkara/pgx_ulid. Just wanted to bring it up since it looks like the author didn't come across it when looking for ulid generators in postgres.

    Disclaimer: I built it.

  • by gioazzi on 1/10/25, 2:46 PM

    I love using Crockford's Base32 to encode "invite codes" or any ID that you may want to share/write down/spell out: don't have to worry about mixing up O-s and zeroes - or care about casing.

    I try to make it obvious in UI by automatically converting to uppercase, replacing O->0 etc, and adding a dash in the middle.

  • by error404x on 1/10/25, 2:34 PM

    This is so amazing, thanks for sharing!

    I usually create an API key like this: `sk_${randomUUID().replace(/-/g, '')}`.

  • by xdennis on 1/10/25, 3:24 PM

    > uppercase letters and numbers for "blocky" aesthetics and readability

    I'm not sure if this is meant to be read as "uppercase (letters and numbers)", but it is effectively what he's referring to.

    Lowercase digits do exist[1], but there's no Unicode encoding for them and fonts typically have to choose to support one or the other.

    [1]: https://en.wikipedia.org/wiki/Text_figures

  • by cynicalsecurity on 1/10/25, 3:11 PM

    This is an absolute useless feature. It's actually even dangerous, because the "beauty" of API keys makes absolutely no sense. Only security matters.
  • by bArray on 1/10/25, 2:54 PM

    > The dashes do remove easy double-click copying, but we think this a fine trade off for readability. We don't want users copying and pasting them everywhere, in fact we want them to be handled with care. Ideally, users copy each key exactly once - when they generate the key from our dashboard - so we added a copy button to our UI to solve that case.

    Or, just ignore the dashes? It's not that difficult, we have the technology.

  • by realaleris149 on 1/10/25, 8:33 PM

    I used https://github.com/jetify-com/typeid for generating api keys for a project. They are nice because you can use prefixes for different type of keys and know immediately what they represent. No dashes also makes them easier to copy paste.
  • by seveibar on 1/10/25, 9:07 PM

    IMO the prefixed api key convention with a public portion and base58 encoding that i wrote about 2 years ago is so so much better than CD-key style API keys https://github.com/seamapi/prefixed-api-key
  • by bkummel on 1/10/25, 3:28 PM

    I'm not sure whether the result is more readable than a UUID. With a UUID you at least know that it can only be [0-9A-F]. Besides, who on earth _types_ API keys? You should copy/paste them and store them in a password manager. So they don't _need_ to be readable.
  • by balls187 on 1/10/25, 3:12 PM

    This reminds me of every time I heard a complaint that a url is “ugly”
  • by alt227 on 1/10/25, 3:24 PM

    > Overall, developers like to use UUIDs - they just don't like how they look.

    I have never ever heard a developer even mention the way api keys look before.

  • by skerit on 1/10/25, 3:18 PM

    What's up with these comments? Let these folks format their keys the way they want.
  • by benterix on 1/10/25, 3:02 PM

    The author mentions readability - if they care about it, they should eliminate all ambiguous characters like 0Oo1l.
  • by robertclaus on 1/10/25, 2:29 PM

    This type of key editing always makes me nervous. I know how uuids behave. I'm not a security expert, but I'm 99% sure the formatting steps here don't increase the chance of key collisions or security implications significantly. Is that 1% risk worth it?