OpenID Connect and ZNC, Part 1
ZNC has two main modules for sign-in, cyrusauth
and imapauth
In evaluating them, I found some major shortcomings that wouldn’t be easy to
correct; imapauth requires the user to exist in ZNC’s configuration before
they can log in, and both cyrusauth, imapauth and the core of ZNC don’t
allow users to change their username. Additionally, imapauth would require me to
either run another dovecot instance or have scope validation not work properly
and cyrusauth would require me to write a saslauthd.
Writing a ZNC plugin is fairly easily, and using cyrusauth
as an example to
learn what functions we need to override to implement an authentication
provider we get the following:
|
|
Now ZNC doesn’t have any built-in library for making http requests, so we’ll use libcurl via the wonderful Curl for People. OAuth2 and by extension OpenID Connect both make heavy use of JSON so we’ll also make use of nlohmann’s JSON for Modern C++.
We are going to use the OAuth 2 Resource Owner Password Credentials Grant as defined in section 4.3 of RFC 6749 to provide authentication for ZNC. To get around ZNC’s inability to change usernames we’ll be creating users using the subject-identifier as their username.
Since I hadn’t implemented user cloning, I manually created the user in the
znc.conf
and started znc up, only to have it terminate with an error:
[ ** ] Invalid user [21ffb2d9-18f0-40b0-8d6a-7c166c52fa56] Username is invalid [ ** ] Unrecoverable config error.
Apparently, “21ffb2d9-18f0-40b0-8d6a-7c166c52fa56” is an invalid username. So I
grep through the ZNC source and discover
CUser::IsValidUserName
gets called
when parsing the configuration.
|
|
The function has a handy comment at the top which gives the validation in regular expression form. We can see that since the username doesn’t start with a letter it is therefore invalid.
Now the SSO provider I’m using uses UUIDs for subject identifiers so if I were to just prefix the username with a string starting with a letter, the rest of the username would pass validation because UUIDs only contain hexadecimal and dash separators. However, OpenID Connect makes no such guarantees about the subject identifier, implementations can use any unique string for it.
We can implement something similar to percent-encoding except using an “@” instead of a percent sign for escaping characters that would otherwise be invalid in an username. This in addition to prepending some letters should be enough to satisfy the requirements of a username in ZNC.
|
|