Week 38, 2026 (Sept 14 - Sept 20)
JWT in Headers
Last week I said I was blocked by servant's header system. This week, I used the source code of servant-auth-server as reference 1, and with some reference to the AddHeader typeclass 2, I made sense of the interface and was able to add cookie headers to the HTTP response.
Encoding and Decoding JWT
I have encountered many difficulties with the JWT format. According to the JWT standard, the sub (Subject) claim of the JWT body can be used to encode "statements about the subject" 3.
The specification for the sub claim states:
The "sub" value is a case-sensitive string containing a StringOrURI value.
Here, the StringOrURI value is a string where if the string contains a :, it must also be an URI. When I tried to put an encoding of the user object into the sub claim, the : in JSON bytestring conflicted with the specification, causing issue when decoding.
In JOSE, this requirement is encoded by the type StringOrURI 4. Interfacing with this type was rather difficult where fromString is essentially the only way to construct such value from scratch.
Understanding Show
Initially, I constructed the sub claim using show:
fromString $ show $ encode userId :: StringOrURI
The behaviour of show on ByteString surrounds the byte string with a pair of "..." . As such, the length of show $ encode userId is actually 3. This was unexpected. Furthermore, I created even more quotation marks on decoding.
The correct solution was to use pack and unpack 5
pack :: String -> ByteString unpack :: ByteString -> String
And we have the following dataflow:
Creating JWT | Reading JWT
UserId ---> ByteString ---> String ---> StringOrURI ---> Text ---> ByteString ---> UserId
| | | | | |
encode unpack fromString Lens encodeUTF8 decodeStrict
Authentication
I also proposed a authentication method last week. I tried to implement one of the AuthProtect combinator, and the server worked with it. Will have to see if having two different AuthProtect with different symbol still works.
Other
I did not do as much Haskell development this week because I was also working a separate project in C. Had to read a lot of man pages.
Footnotes:
servant-auth-server Hackage, acceptLogin
servant Hackage, Class AddHeader
JOSE Hackage, Crypto.JWT, StringOrURI
ByteString Hackage, Data.ByteString.Char8, pack