-
Notifications
You must be signed in to change notification settings - Fork 166
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refine JSON serialization to use UTF-8 encoding for user.id
and userHandle
#2013
Comments
A side effect of this change might be that RP's feel empowered to use PII-containing identifiers here since they're already strings. However I think we could easily enough suggest base64url-encoding 64 random bytes and then using that string as |
I don't think a minor convenience improvement is worth breaking the pattern and making user handles behave differently from all other binary values. In my own software development experience, exceptions (AKA broken invariants) are the root of (almost) all evil. I don't think this exception seems valuable enough to defy that principle. Also in my own experience developing apps around WebAuthn, I find it convenient enough to just use the base64 encoding of the user handle as the canonical representation of it - not least because strings in JavaScript can be compared using the |
The spec is pretty clear that
|
It took me a minute to understand what's going on here. Basically the chosen value for So if you pass the userID string through Go's I agree with the other comments here. Consistency seems more important, and we shouldn't handle encoding of these individual fields differently. (I will look into whether we can make Chromium's base64 decoder stricter for the JSON parsing methods.) |
You need to use |
The issue is with padding bits within a final sextet. RawURLEncoding I think controls the '=' padding character to pad the string into multiples of 4. |
(Sorry, I mixed up some things in my original response above. Updated for correctness.) |
Alright, this isn't necessarily a hill I want to die on, but I figured I'd give it a shot. I know WebAuthn has recommended Thanks for humoring me ✌️ |
Yeah, I do agree that this could be useful. Many applications I've worked with use UUIDv4s as primary account identifiers and just use the UTF-8 encoding of those as the user handle. It is sometimes a bit of a hassle to have to juggle the various representations of that, but ultimately I think that introducing a special case for user handles in JSON I/O would replace a small problem with a much bigger one. |
I agree with @emlun. The spec treats the user handle as a binary string (rather than an encoded text string) in various ways, and I think it would be a liability to change that. Further, supporting UTF-8 would imply that it is reasonable to encode something more structured or even user-provided instead of random. This could be sufficiently secure, but the use of an opaque binary string encourages a secure implementation by default. |
Proposed Change
The JSON serialization logic we added in L3 consistently uses base64url encoding for any value that's an
ArrayBuffer
in the browser. However, in my experience it makes for easier debugging during authentication when UTF-8 encoding is used specifically foruser.id
anduserHandle
as it helps developers immediately see the user ID in a recognizable format.For example, consider an RP that generates its own string identifiers for users:
An RP dev may naively specify this value for
user.id
when callingparseCreationOptionsFromJSON()
believing, "it's non-PII so why not?"If the RP commits to the spec's JSON serialization methods during a subsequent authentication then they'll experience an unintuitive footgun:
The user ID gets munged! The
userHandle
becomes unusable, and the dev falls back to using credential ID to determine which user should be logged in (which is a bad idea as @sbweeden re-confirmed recently in #1909 (comment))In my opinion (gleaned through practical experience) if
userHandle
is the same then it's easy to pull that value out of the front end and cross-reference it when pulling database records, query logging for the value, use and compare the value programmatically in other areas of the product...currently RP devs (that correctly base64url-encoded the UTF-8 bytes in"USER2ML8P7C08R"
as per the current text in L3 and specifyuser.id
as"VVNFUjJNTDhQN0MwOFI"
instead) have to base64url-decodeuserHandle
to bytes and then UTF-8 encode those bytes to get back to"USER2ML8P7C08R"
before continuing with their troubleshooting.I therefore assert that it is more useful to RP devs for
userHandle
out of a call totoJSON()
to be the same as theuser.id
string passed intoparseCreationOptionsFromJSON()
. We can remove this footgun by updating the JSON serialization logic so that theuser.id
argument is allowed to be any UTF-8 string when callingparseCreationOptionsFromJSON()
, and that UTF-8 encoding is used to serializeuserHandle
whentoJSON()
is called.Potential Impact
While trying to find a browser I could run sample code in to put this all together I noticed that only Firefox currently has fully implemented the JSON serialization methods. Chrome currently only supports
parseCreationOptionsFromJSON()
andtoJSON()
, while Safari doesn't currently support any of the methods.I'm hoping this means there's still a chance to discuss updating this logic, as it would mean breaking any current use of these methods.
Footgun Repro
The text was updated successfully, but these errors were encountered: