Fixing Cookie Validation in Flutter and Dart
The Problem
I ran into an issue when developing an API client in Flutter: Dart will not validate cookie values if they contain double-quote characters!
FormatException: Invalid character in cookie value, code unit: '34'
This is a problem can effect interacting with popular websites and APIs. For example, parsing cookies from https://instagram.com will throw an exception.
Why is this a problem?
Today’s mobile development is heavily dependent on interacting with web APIs. Should a server send you Set-Cookie
headers that have values in double-quotes, you will not be able use that API with Dart or Flutter.
Here’s where the issue lies: Line 994 of _validate() in Dart’s sdk/http_header.dart.
for (int i = 0; i < value.length; i++) {
int codeUnit = value.codeUnits[i];
if (!(codeUnit == 0x21 ||
(codeUnit >= 0x23 && codeUnit <= 0x2B) || // right here
(codeUnit >= 0x2D && codeUnit <= 0x3A) ||
(codeUnit >= 0x3C && codeUnit <= 0x5B) ||
(codeUnit >= 0x5D && codeUnit <= 0x7E))) {
throw new FormatException(
"Invalid character in cookie value, code unit: '$codeUnit'");
}
}
There’s a jump between characters 0x21
and 0x23
. Character 0x22
(hex for 34) is the double-quotes "
character.
Solution
Upstream
The correct behavior is to allow cookie values that are encapsulated in double-quotes, like so:
// check if first and last characters are double-quotes
// if they are, strip them from the string
if (value[0] == '"' && value[value.length - 1] == '"')
value = value.subString(1, value.length - 1)
for (int i = 0; i < value.length; i++) {
int codeUnit = value.codeUnits[i];
if (!(codeUnit == 0x21 ||
(codeUnit >= 0x23 && codeUnit <= 0x2B) ||
(codeUnit >= 0x2D && codeUnit <= 0x3A) ||
(codeUnit >= 0x3C && codeUnit <= 0x5B) ||
(codeUnit >= 0x5D && codeUnit <= 0x7E))) {
throw new FormatException(
"Invalid character in cookie value, code unit: '$codeUnit'");
}
}
Practical Solution
Unfortunately, building and maintaining a separate branch of Dart was out of scope for the project I was working on. Since I had control over the service’s API, I chose to use token-based authentication to move forward with rapid implementation.
Eventually, for the couple of APIs I didn’t have control over, I wrote an HTTP client that implemented cookie parsing on its own.
Why am I posting this here?
- There isn’t much written about this error, just a few Github Issues for various Dart projects that consume the http standard library.
- Because of issues like this, I try to wait until early-stage platforms stablize before adopting them. I hope to save another developer the time I lost tracking this bug down.
- dart-lang’s Issues page on GitHub is long and the issues it lists are old. Perhaps others that ran into this issue will make their voices heard and this issue will take precendence.
I’ve submitted a pull request with the fix. If you’ve been affected by this bug, please feel free to make some noise so that it gets fixed.
See also
- Cookie validation is broken in Flutter - My post on Reddit
- Validate cookie values wrapped in double-quotes #33765 - GitHub PR
- Dificult [sic] with cookies #8 - Dio’s GitHub Issues
- Cookie.fromSetCookieValue doesn’t handle double quotes #33327 - dart-lang’s GitHub Issues