plugin | ||
.gitignore | ||
flake.lock | ||
flake.nix | ||
package.nix | ||
README.md | ||
test-nixos.nix |
Keycloak allow/ban plugin
This is a plugin for Keycloak that checks an allow-list and a ban list for users from GitHub.
Configuration
Add the plugin to your keycloak plugins list. The plugin can be obtained via
nix build .#packages.default
.
The configuration of this plugin is in a directory of text files with the
format github-id github-username
, allowing #
comments.
Specify a Keycloak config file option
spi-authenticator-allow-ban-check-authenticator-dbpath
pointing to the
directory with the configuration. Note that the error if you don't configure
this is complete garbage, and is also not printed by default (sorry)! Use
kc.sh --verbose start
to read your NullPointerException
.
There are three notable files in there:
-
banned-users.txt
: contains a list of GitHub IDs which will be rejected outright on login.If you newly ban a user, you have to kill all their sessions across all infrastructure, including existing Keycloak sessions, since bans only apply on login.
-
allowed-users.txt
: contains a list of GitHub IDs which will be allowed if the allow-list is enabled. -
use-allow-list.txt
: if present, the allow-list mechanism is used. Otherwise it is bypassed and all logins are allowed.
The intent of the configuration is that it is synced by a cron job pulling a git repo.
Setup
-
In the GitHub Identity Provider configuration on Keycloak, set up a mapper with type "Attribute Importer", importing the JSON field path "id" as a user profile attribute "githubId".
-
Create an auth flow for post login on the identity provider, containing one element "Allow/Ban check". This is necessary since it bypasses the standard login flow if you log in via the external IdP.
-
In the identity provider, set the Post Login Flow to the flow just created.
-
Add the "Allow/Ban check" action to the main login flow as a Required element at a point after the username is determined.
Notes
We are unsure if Store Tokens is necessary to set; it is not for this plugin, but it might be a good idea to simply have them around.
We don't think there are ways to ban-evade, since this is managed by a user-invisible profile attribute that is permanently glued to all accounts originating from GitHub.
We have tested this on Keycloak 23 and 24.
Test environment!
There is a test environment included with this plugin to avoid testing in prod. Run:
nix run .#
Then in a separate terminal:
sudo socat TCP-LISTEN:443,fork,reuseaddr TCP:127.0.0.1:4043
and add 127.0.0.1 identity.test.lix.systems
to /etc/hosts
. Dump Firefox
DNS cache if necessary (about:networking
), and create a GitHub OAuth app.
You can ssh into the machine on port 2022 on localhost as root, with no password.
Then finally go to https://identity.test.lix.systems/superadmin
, and log in
with admin
/Password1
.
Attaching a debugger to Keycloak
We are so sorry.
If you are doing this to the VM here, change the last line of the keycloak startup script to this:
DEBUG=true DEBUG_PORT='*:1337' DEBUG_SUSPEND=y kc.sh --verbose start --optimized --debug
To actually make that work, you want to copy the file from systemctl cat keycloak.service
to /start-keycloak
, then systemctl edit --runtime keycloak
, with the contents:
[Service]
ExecStart=
ExecStart=/start-keycloak
Then systemctl restart keycloak
. Next create a forward like ssh -L1337:localhost:1337 localvm
and attach your Java debugger to port 1337.
Future steps
We might need to do account age stuff, if we get sockpuppet problems.
Note this also: https://keycloak.discourse.group/t/retrieve-identity-provider-github-token/16613
Also, the GitHub IdP mappers get all of this response's info, including account age: https://docs.github.com/en/rest/users/users?apiVersion=2022-11-28#get-the-authenticated-user